现在许多网站采用字体反爬策略,即替换一些字符的unicode编码并且将生成的字体文件加密后传输到前端,由前端解析并显示正常的字符。
部分参考崔老师的一篇博客 https://cuiqingcai.com/6431.html,这篇博客讲述了处理字体反爬最初思路。但该博客只提供了大致的处理思路,受博客的启发,我整理了另一直做法来克服多个页面的不同汉字的变化。
首先,我们要大致理解字体反爬是怎么实现的。在崔老师的博客中提及到ttf文件以及对应的xml文件。观察内容,xml文件中包含了一些映射以及字体内容。这里所谓的字体内容就是这个字的字形数据,通过这些字形数据,能勾画出字符。我们找到这个字形数据是通过unicode编码以及映射在文件里找到对应的TTGlyph标签。所以当我们使用的是服务端传来的字体文件时,能根据传来的“错误的”unicode编码去找到正确的字形数据并展示到页面上。个人猜测,服务端根据要返回的敏感信息的字生成临时的字体文件,并设新的unicode编码,返回时将字体文件内容加密传给前端,前端一律使用生成的字体文件,所以能解析传来的unicode编码。同时因为字体文件是会刷新生成的,所以崔老师博客里的代码偶尔会失效。在理清了字体反爬后,我们就可以开始做出相应的处理。
方法一:字体内容比对法
这也是我最初的做法,观测网站得知,前端使用的字体文件第一个是后端返回解析后生成的,第二个是微软雅黑,所以我选择去试验。按博客的过程,找到一个页面爬取并保存生成的font文件和xml文件。如”陈“字,通过font文件,利用服务端返回的unicode编码在xml文件中找到对应的字形数据。然后下载微软雅黑字体并生成对用的xml文件。通过”陈“字对应的unicode编码找到对应的字形数据,与前面的对比,得出:除了顶部unicode编码不一致,其余一致。
到这里,剩余的问题就迎刃而解了。我们可以先读取微软雅黑的xml文件,建立一个unicode编码与字形数据的映射,这里使用dict即可。但我们的目的是找到”正确“的unicode编码,我们手头上有的是”错误“的unicode编码以及字体的xml文件。所以我们的字典key和value应该互换位置:字形数据作为key,微软雅黑的unicode编码作为value,那么我们就可以通过”错误“的unicode编码 -> 字形数据 -> ”正确“的unicode编码。看起来已经大功告成了,但我们还需要处理一下字形数据的问题。字形数据里面可以包含多层,不过可以通过解析xml结构来解决,但是这么长的数据作为key也不太好。我这里因为字体常用不是很多,我选择把字形数据里的 x,y,on 连接起来并使用md5加密(这里我认为碰撞的几率很小很小,所以视加密后是唯一的),这样key的长度就很符合要求且冲突少了。
方法二:映射文件比对法
在爬取一段时间后,发现上面的方法失效了!查看生产的xml文件,发现映射对应不上了,但同时前端处理的方法也有所改变。前端不再读取内容,反正在一个cmap的映射里,将“错误”的unicode编码和“正确”的unicode编码关联起来,这样反而解析速度更加快了。
缺点:
两种方法都要生成font和xml文件,但实际我们只需要xml文件的内容。因为技术有限,没有办法改造对应的库来简化操作,现在爬取速度很慢主要因为生成XML文件的I/O十分频繁。
各位有更好的想法提议可以留言!
著作权归作者所有,任何形式的转载都请联系作者。
网友评论