6

一个技术精致的网站:接口设计和图片加载

 1 year ago
source link: https://feizhaojun.com/?p=3832
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一个技术精致的网站:接口设计和图片加载

分类: 前端  标签:
作者: mukti  时间:2023-04-20 22:53:06 (星期四)

本文仅适用于互联网web开发者。

我们在看到一个网站的时,首先关注到的多是它的界面设计,美观并炫酷的页面,是让我们对它的开发者产生敬意的最容易的方式。

抛开界面和用户交互之后,从代码实现上,怎么才能看出一个网站的技术优雅而精致呢?

互联网从业者,不管是前端还是后端,肯定对这个问题多多少少都考虑过,但是我们的方向大概只有两个:一个是从用户角度提高访问速度,一个是从开发者角度提高可维护性。

至于网站的性能优化,相信大家也可以侃侃而谈,前端会大谈特谈 Vue 和 React,他们的周边生态,后端会聊起 Java 和 PHP,甚至 GoLang,告诉你缓存和分布式。

我最近关注到一个美国的珠宝电商网站 Brilliant Earth,它还用到了国内开发者嗤之以鼻的 jQuery,因为最近我想爬取一些他们的商品图和信息,这个过程中我发现了几处细节,让我对这个网站的开发者十分钦佩,钦佩到要专门写一篇文章来讲一讲。

前些年我们特别喜欢谈前后端分离,现在现在我们多数开发团队都实现了它,导致公司招聘前后端至少2个人才能组队。工作中前后端的界限也十分明显,两者通过接口URL来对接。

基于我们前文提到的两个方向,访问速度和可维护性,前后端分离这种方式对开发者确实十分“友好”,也能在用户访问体验上做些文章,但是对搜索引擎十分不友好,于是硬生生又创造出“SSR”(服务器端渲染)这样的名词。

后端在提供给前端接口的时候,多数采用了 JSON 格式,供前端方便地组织、渲染数据。但是这样的接口也很容易被“恶意”地爬取,尤其是一些行业数据类的网站,比如京东的商品信息、豆瓣的电影图书等等。尤其是豆瓣,自己的后端接口开发出来多是被其他应用调用,浪费了大量服务器资源。

其实网站既然能被访问,就难逃被爬的命运。反爬的策略也只是提高一下爬取的门槛儿。常见的方式多是携带特殊参数、验证请求headers、cookies等等。

比如豆瓣,后端接口要求携带 apiKey,并验证了 header 中的 Referer 和 User-Agent,但是这种策略很容易被绕过,参见《豆瓣开发者不完全指南》

Brilliant Earth 非常适度地使用了前后端分离,并且借用了浏览器的 replaceState 属性来避免爬取,这是我第一次见到这种反爬策略。

进一步解释一下,我们在豆瓣电影首页找到某个XHR请求,复制为 cURL,然后到命令行/终端界面直接输入后回车,就可以看到返回的前端所需数据。

image

根据请求中的信息(如参数、headers、cookie等),我们便可以在 Postman 类工具中模拟浏览器请求接口数据。

但是我们使用同样的方法操作 Brilliant Earth 的接口,会发现返回的数据并不是预期的。你可以在如下图所示的 sapphire 产品列表页试一下相关接口:

image

你发现返回的并不是产品列表的数据,而是一个带有 history.replaceState 代码的页面,这个页面上是服务器端生成的一些二次验证的参数,需要再次提交才能拿到真正所需的数据。

如果在浏览器里面,接口会通过 replaceState 自动跳转到下一步,而如果你如果使用命令行/代码/Postman 爬取,就无法直接拿到结果。

当然,我前面也有说,任何反爬策略都可以被绕过,但是 Brilliant Earth 是我见过最“聪明”的反爬策略了。

在 Brilliant Earth 的产品详情页,提供了产品的360°视图,通过鼠标拖拽可以通过各个角度查看产品。

比如下面这个海蓝宝戒指,红框中左侧的戒指和右侧裸石都是可以360°查看的。左侧戒指采用的是一个叫 ImgJize 的第三方服务,右侧裸石采用的是 VISION 360°,是一个专门拍摄宝石并提供展示服务的印度公司。

image

因为这两个视图都是通过 iframe 引入到 Brilliant Earth 页面的,所以他们的加载和相关技术和 Brilliant Earth 的页面互不影响,我们拆开来看看。

左侧展示戒指的 ImgJize 用的是大多数开发者的方法,他们环绕着戒指拍了 192 张照片,然后通过 <img /> 标签引入图片,循环显示便完成了一个360°视角的动画。

VISION 360° 在右侧的裸石视图上就更为巧妙。他们使用了 256 张图片,但是这些图片是分量加载的。

他们先从 256 张图片张图片中按等分角度(90°)挑选 4 张,组成圆周 4 个角度的视图,将这 4 张图片转成 base64 格式的数据放到一个 json 文件里面,命名为 1.json

使用 base64 可以保证这 4 张图同时加载,而避免了随着图片增加,不同的图片加载时间不一致的问题。比如 ImgJize 的方式,要等 192 张图片全部加载完成才能开始展示。而 VISION 360° 只要加载了最初的 4 张图,就可以开始展示一个 360° 动画,虽然这个动画连贯性目前还很差。

下一步,开发者从上一步 4 张图的每两个图的角度中间的角度各选一张图,得到 4 张图放到 2.json 里面,等 2.json 加载完,便得到了 8 张图片,增加了动画的连贯性。然后再从 8 张图的每两图之间继续抽出一张图,一共 8 张图放到 3.json,得到 16 张图……再取 16 张、32张、64张、128张,一共 7 个 JSON 文件,得到 256 张图。

这 256 张图渐进式地加载完,便完成了一个非常顺滑的圆周视图动画。

不过这里他们还有一个非常有趣的处理,通过 JSON 得到的这 256 张图,并不是按照圆周角度的顺序排放的。也就是说,你就算爬取到了这 256 张图,如果想连贯的按照 360° 播放,还需要一张一张图查看,手动地去排好序才能使用。

VISION 360° 自己使用这些图片的时候,额外提供了一个记录图片顺序的数据,而这个数据是经过加密的。这样就大大提高了爬取者的成本,就算你拿到了他们网站所有的图片,也没法做一个 360° 的展示功能,需要人工对每个产品、每个图识别、排序之后才能使用。

遗憾的是,检查网站的 js 文件,虽然代码经过了混淆加密处理,但是 CryptoJS 这个字眼过于明显,通过细心地查找,不难发现解码的 key

还是那句话,反爬策略只能增加了爬取者门槛和成本,总能有办法破解。

您的赞助将会支持作者创作及本站运维

wxpay-qrcode.png

alipay-qrcode.png


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK