本来吧,这节课准备写我自己期待很久的Javascript对抗的,但是发现上节课讲了偏技术的Cookie感觉反响一般,所以还是准备再插几节闲聊猎奇型的反爬技巧,再到最终的Javascript吧,放最后一篇文章写,不然我害怕写完那篇,就写不动了。
好了,同样前几篇文章链接:
从今天这篇文章开始,主要给大家过一些小众的反爬策略以及其中的利弊,所以一般来说都会有一个特定的示例,比如今天的反爬策略就来自反爬界大神之一的去哪儿(当然也是爬虫界的)手机版。
我们先来用chrome的手机模式开一下去哪儿的机票:
看着叫一个干净整洁,完全没毛病。但是!当我们掀开被子看源码的时候 震惊了:
不知道大家能不能看清图,我码字注解一下,显示的价格是560,而源码中的价格则是540!
我们这篇文章就来看看去哪儿手机版是怎么做到的(当然偷偷剧透下,下篇文章咱们主角还是去哪儿)
其实同学们只要智商在线,看到标题就知道,这是用字体实现,我们看右侧的css面板也可以看到,这个dom元素的字体是单独设置的。也就是去哪儿通过修改字体,让4显示成了6。
感觉从这篇文章开始这个套路快进行不下去了。为什么字体可以反爬? 首先这个迷惑性太大,很多马虎的工程师以为可以了,直接就爬下来,当然就是被老板骂的体无完肤了,对反反爬工程师的精神可以造成1万点伤害。同时呢,去哪儿这个字体是动态生成的字体,也就是说你也不知道下一次刷出来的4到底是几显示出来的。这个道行就比较高了。
这种反爬策略用在数字上确实天衣无缝,非常优雅。唯一值得提的就是一点,如何动态生成字体和页面来做好对应关系。其实这是一个工程性的问题,大部分编程语言都含有生成字体的库,如果对网站整体性能比较自信的话,完全可以每次请求都动态生成,当然这样确实会比较慢,比较推荐是通过定时任务,去更新一个字体池。每次有请求过来,从字体池中随机拿一个字体,换一个随机的名字(可以通过url rewrite来实现),并和现在的数字做一次映射,调整页面显示后整体输出,就可以在尽量不影响性能的情况下搞死反反爬。
当然使用字体也是有局限的,其中最大的问题莫过于@font-face的兼容性问题,所以去哪儿只在移动端采用这个反爬策略,可能也有兼容性的考虑吧,相比之下,去哪儿的pc端的反爬写法则丑陋很多。
好了,万一我就是要爬去哪儿机票了怎么办呢?其实字体反爬处理也并不复杂,就像前面说到的,大部分语言都有字体处理类库,而这种情况大概率来讲只有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;
————————————————–最后说两句———————————————————-
好了,从这一篇字体反爬开始,咱们算是进入 真·奇技淫巧 部分了,应该说了解这类反爬手段无论对咱们做反爬还是反反爬都有很大帮助,当然也很趣。大家可以根据自己的应用场景来选择自己的合适的反爬手段。反过来说,道高一尺魔高一丈,反爬永远有对应的反反爬,这就是一个人之间的对抗罢了,而说到底则是利益之间的对抗。
当然你要问我为什么把这段代码贴出来,也许很多天真的朋友以为有了这个就可以去爬去哪儿了,我只能说一句:
有话要说