破解诡异字体


爬虫与诡异的字体-反爬与反反爬的奇技淫巧

从今天这篇文章开始,主要给大家过一些小众的反爬策略以及其中的利弊,所以一般来说都会有一个特定的示例,比如今天的反爬策略就来自反爬界大神之一的去哪儿(当然也是爬虫界的)手机版。
我们先来用chrome的手机模式开一下去哪儿的机票:
看着叫一个干净整洁,完全没毛病。但是!当我们掀开被子看源码的时候 震惊了:
不知道大家能不能看清图,我码字注解一下,显示的价格是560,而源码中的价格则是540!
我们这篇文章就来看看去哪儿手机版是怎么做到的(当然偷偷剧透下,下篇文章咱们主角还是去哪儿)
其实同学们只要智商在线,看到标题就知道,这是用字体实现,我们看右侧的css面板也可以看到,这个dom元素的字体是单独设置的。也就是去哪儿通过修改字体,让4显示成了6。

1.为什么字体可以反爬

感觉从这篇文章开始这个套路快进行不下去了。为什么字体可以反爬? 首先这个迷惑性太大,很多马虎的工程师以为可以了,直接就爬下来,当然就是被老板骂的体无完肤了,对反反爬工程师的精神可以造成1万点伤害。同时呢,去哪儿这个字体是动态生成的字体,也就是说你也不知道下一次刷出来的4到底是几显示出来的。这个道行就比较高了。

2.怎么做好字体反爬?

这种反爬策略用在数字上确实天衣无缝,非常优雅。唯一值得提的就是一点,如何动态生成字体和页面来做好对应关系。其实这是一个工程性的问题,大部分编程语言都含有生成字体的库,如果对网站整体性能比较自信的话,完全可以每次请求都动态生成,当然这样确实会比较慢,比较推荐是通过定时任务,去更新一个字体池。每次有请求过来,从字体池中随机拿一个字体,换一个随机的名字(可以通过url rewrite来实现),并和现在的数字做一次映射,调整页面显示后整体输出,就可以在尽量不影响性能的情况下搞死反反爬。
当然使用字体也是有局限的,其中最大的问题莫过于@font-face的兼容性问题,所以去哪儿只在移动端采用这个反爬策略,可能也有兼容性的考虑吧,相比之下,去哪儿的pc端的反爬写法则丑陋很多。

3.遇到字体反爬怎么办?

好了,万一我就是要爬去哪儿机票了怎么办呢?其实字体反爬处理也并不复杂,就像前面说到的,大部分语言都有字体处理类库,而这种情况大概率来讲只有10个数字的字体,我们将字体解析后只要能找到对应关系,就简单了。这里如果是Java工程师的话,推荐用Apache.Fontbox,贴一段解析的代码,注意这段代码不保证现在可用,仅做参考:
int[] digits = null;
BASE64Decoder decoder = new BASE64Decoder();
TTFParser parser = new TTFParser();
try {
byte[] bytes = decoder.decodeBuffer(fontBase64);
InputStream inputStream = new ByteArrayInputStream(bytes);
TrueTypeFont ttf = parser.parse(inputStream);
if(ttf != null && ttf.getCmap() != null &&
ttf.getCmap().getCmaps() != null &&
ttf.getCmap().getCmaps().length > 0){
digits = new int[10];
CmapSubtable[] tables = ttf.getCmap().getCmaps();
CmapSubtable table = tables[0];// No matter what
for(int i =0;i<10;i++){
digits[i] = table.getGlyphId(i+48)-1;
}
}
} catch (IOException e) {
digits = null;
}
return digits;


刘小恺(Kyle) wechat
如有疑问可联系博主