052-听说你爬回来的都是乱码?以某团为例讲解四种方案解决CSS字体反爬

1,518 阅读3分钟

这是坚持技术写作计划(含翻译)的第52篇,定个小目标999,每周最少2篇。


本文以某团为例讲解如何获取css字体的真实内容


关于css3字体

在以前,前端工程师只能使用浏览器主机已经安装的字体,要实现一些比较风骚的字体效果,只能用flash或者图片,从css3以后,可以使用 @font-face 属性 实现,基本现代浏览器都支持,具体参考 www.caniuse.com/?search=fon… ,但是在人均爬虫时代,被玩出了新花样,包括但不限于 金额,数量,地址,名称等信息用webfont替代文本来抵挡一部分低级爬虫而又不影响用户阅读和查看。

访问 fontdrop.info/ ,下载 s3plus.meituan.net/v1/mss_73a5… ,并上传就能看到了
image.png

方案一 OCR

这个思路是基于任何产品都不会牺牲用户阅读体验来提升反爬门槛,也就是说,用户肉眼能看到最终呈现效果,所以你把他当做是图片,用OCR产品去识别就可以了,除了占资源较多,识别效率较低外,鲁棒性更高。

常见的开源方案是 tesseract

方案二 映射

针对的是小站,自己费劲搞了一套web font万能不变,爬虫工程师定点爆破,假设有100套(这是往多了说的,实际上很可能就1套),把这些有限的web font都down下来,然后本地建立一个映射关系,爬取的内容 替换一下就行了

方案三 KNN/K近邻/K相邻

方案二的基础是web font有限且不变的前提,如果像某音,某团这种的机器随机生成的,那就没法了,这时候可以用KNN
参考 python爬虫: 使用knn算法破解猫眼动态字体反爬

方案四 欧氏距离

方案三 有点杀鸡用牛刀了 就为了个字体反爬,至于用KNN么,还得自己弄样本数据

计算欧氏距离只需要一个样本,找到映射关系,其余的只需要跟样本比较就行了

# 下载 http://s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/6cf535d2.woff
base = TTFont(self.getFontFile(baseFontFile))
font = TTFont(self.getFontFile(fontFile))
# baseGlyf = base.get('glyf')
# glyf = font.get('glyf')

# np1 = np.array([j for j in baseGlyf[0].coordinates])
# np2 = np.array([j for j in glyf[0].coordinates])

np.linalg.norm(np1 -np2, 'constant', constant_values=0)

代码只贴出关键部分
通过 TTFont 解析font,取 glyf[n]coordinates  取出点数组,使用numpy计算欧式距离,进行排序,最接近的就是符合的(两层循环),甚至可以观察下,欧式距离普遍小于几,假设是1500,那内层循环小于1500就跳出就行了,注意np1,np2要补齐成一样长,否则会报错

补充一下,如果后期平台可能会同比缩放点位,这样简单计算欧氏距离就白搭了,需要把xy点位同比进行处理

招聘小广告


山东济南的小伙伴欢迎投简历啊 加入我们 , 一起搞事情。
长期招聘,Java程序员,大数据工程师,运维工程师,前端工程师。

参考资料