发现一种有趣的防爬虫手段
本文所述仅局限于技术层面的探讨,请勿将本文思路用于违法犯罪活动,否则后果自负!
背景
前段时间,有个朋友在群里提到一件怪事:在某网站上,拷贝正常的文本再粘贴到其它地方时,全都是乱码,只能使用网站提供的复制功能。
1 | 看到的文本:笔名 |
这一下子勾起了我极大的兴趣,于是我打开了这个网站,开始研究它里面的门道。
探索过程
监听拷贝事件
听到这个趣事时,我的直觉告诉我,它可能是监听了用户的复制事件,把本来正常的文本转成了乱码。但我很快就被打脸了:
- 通过浏览器控制台,查看网页源码时,看到的确确实实是乱码
- 查看 JS 代码,也没有找到任何监听复制事件的逻辑
乱码转换方法
然后,我的探索方向变成:网页下载的是乱码,但通过 JS 内置的转换规则,可以把乱码转成正常文本。但很快,这个思路也走不通了:
- 通过在 JS 脚本中打断点,一步步观察可疑变量,并没有找到乱码转换的内置逻辑
- 官方提供的复制功能,实际是通过网络请求获取的正常文本
字体问题
就在一筹莫展的时候,我的一个无意举动,打开了新世界的大门。
在反复浏览它的网页源码时,我发现明明很多字的样式都差不多,但是却给很多段落使用了不同的 font-family
,而且这些 font-family
是自定义的,而非标准字体。
于是我随手把某个段落设定的 font-family
去掉,发现原本正常的文本乱码了!也就是说:
- 网站下载的确实是乱码,但乱码和正常文本的转换关系是在服务端设定好的
- 通过设定一系列字体,来控制前端乱码转换的效果
这防爬虫手段,真的是不可不谓之妙啊妙啊!
如何破解
以下内容仅作为技术探讨,请勿用于违法犯罪活动,否则后果自负!
OCR 解千愁
其实,最最简单的方法,是不要去理会它的转换关系:直接截图,丢到 OCR 软件中识别,就可以得到正常的文本。但是,OCR 的识别并不总是可靠的。尤其需要拷贝长文本的时候,需要人为去逐字校验一遍,太费眼睛了。
那么,有没有更好一点的办法呢?
找文本编码转换的规律
对于防爬手段不够高明的网站来说,它的乱码和文本之间,可能存在非常简单转换关系,比如仅是 unicode 编码偏移。
1 | 看到的文本:笔名 |
以上面的文本为例,笔
和 名
的 Unicode 为 31508
和 21517
,而 笞
和 吗
的则为 31518
和 21527
,两者的差值刚好是 10
。
所以,在获取到 HTML 文本之后,可以对文本做一个简单的转换,从而得到正确的文本。
1 | // 笞 => 笔 |
找字体轮廓的规律
有的时候,网站的文本转换关系可能并不像上述例子中直接,或者它就是没有相对固定的规律。这个时候,就要从字体的轮廓中找找规律了。
一种可行的思路是,通过 opentype.js 或者 FontDrop! 在线工具,分析和对比字体的 Path Data 数据,得到文本的映射关系。
有的时候,网站开发者会对字形做微调,导致轮廓数据无法完美匹配。这种情况下,还可以尝试用一些简单的机器学习算法(如 KNN)找出最相近的文本。
PS:如果要涉及到非常复杂的机器学习算法(甚至是神经网络模型),那还是建议用成熟的 OCR 软件吧!