反爬有很多手段,字体反爬就是其中之一。之前一直都是听过,但是却没怎么在实际爬虫中遇到过,最近在一个爬虫题目网站上看到了,试了试,发现还挺麻烦,当然自己从头研究字体肯定麻烦,简单的是模块多的是,选几个就过了。
字体反爬
爬虫与反爬一直在不停的斗争,手段层次不穷。字体反爬算是常见的一种手段,大抵的思路是通过字体文件将浏览器渲染结合起来,让浏览器看到的内容与肉眼看到的内容不一致,达成一定的反爬目的。
比如,我们定义一个字体<1> 但是对应的svg显示为<5> ,那么肉眼看到的是5 ,通过源码或抓取得到的确是1。 之前的时候是通过一个字体文件,现在慢慢演变为动态字体,每次看到的都不同,所以现在我们需要对字体进行解析,得到最终的数据。
反爬
这里有个题目http://glidedsky.com/level/crawler-font-puzzle-1 ,不是打广告哈,关于字体反爬的一个题目。
我按照这个题目进行整理实现思路,可能不具有通用性。
目标地址
http://glidedsky.com/level/web/crawler-font-puzzle-1 ,根据给定的地址,我们可以看到源码与数字是不同的,那么我们可以通过控制台很容易找到这个字体,而且可以找到该字体是通过页面中的base64来指定的字体文件。
先将base64 转为 ttf 文件
代码或工具都可以:
https://www.motobit.com/util/base64-decoder-encoder.asp 工具转换。
代码转换(nodejs):
const base64str = `xxxx由于太长,此处不写了`;//data:font;charset=utf-8;base64, 之后的内容,不要逗号
const fs = require('fs');
fs.writeFileSync('./demo.ttf',Buffer.from(base64str,'base64'));
通过fontcreator
软件打开后可以看到,字体展示与unicode标注的都是不同的。
但是...
目前,还没找到除了ocr识别外的更好的办法,之前看文档有说可以从ttf中拿到映射关系的,不过我没处理出来..能力有限。而且,这个我也没有使用ocr
,直接使用了一个下标判断。
将ttf解析为xml ,并转为对象,然后获取下标,得到映射
const font = require('font-carrier');
const xml2json = require('xml2json');
//加载字体
let transFont = font.transfer('./demo.ttf');
let str = transFont.toString();
let json = xml2json.toJson(str);
let obj = JSON.parse(json);
let fonts = obj.svg.defs.font.glyph;
let map = {};
//就目前来看,还没找到对应的映射关系,比较理想的是,根据下标,除去第一个,从0开始。
fonts.forEach((t, i) => {
if (i>0) {
let code = t.unicode;//4
let index = i - 1;//0
//对应的意思就是:给浏览器一个字符串4 ,显示出来是 0 。
map[code] = index;
}
})
console.log(map);
剩下的就是一页一页的抓取,然后获取ttf并解析,最终进行匹配了..
关于ocr 一直不太懂,而且python也不会,最近也一直想了解下这部分的内容,正在努力学习中..
其实一直想实现的就是给定一张图,从图中找到某个字,并返回对应字体在图中的位置..感觉好多地方都会用到,可惜实力不允许,太菜了。