爬虫遇见诡异字体-反反爬(58同城字体)
2018-09-26 本文已影响823人
___简爱
今天在溜达58同城时,发现租房里面的价格等数字被替换成了看似像乱码的字符串,这明显就是为反爬虫而设计的,琢磨很久,最后在网上发现了解决办法。
先打开58同城的租房信息,由于有的页面做了反爬,有的没做,所以先要找到做过反爬的页面,如下:
浏览时图片
看上面图片,很整洁的样子,其实看源码吓我一跳。
源码中数字被替换
800变成了三个字,这让程序员怎么玩。
1、为什么字体可以反爬
这个字体库是动态生成的字体,也就是说你不知道下一次刷新出来的数字到底对应的是哪个字。所以就不能直接抓取信息了,这个道行就很厉害了。
2、怎么做好字体反爬?
这种反爬策略用在数字上确实天衣无缝,非常优雅。唯一值得提的就是一点,如何动态生成字体和页面来做好对应关系。其实这是一个工程性的问题,大部分编程语言都含有生成字体的库,如果对网站整体性能比较自信的话,完全可以每次请求都动态生成,当然这样确实会比较慢,比较推荐是通过定时任务,去更新一个字体池。每次有请求过来,从字体池中随机拿一个字体,换一个随机的名字(可以通过url rewrite来实现),并和现在的数字做一次映射,调整页面显示后整体输出,就可以在尽量不影响性能的情况下搞死反反爬。
当然使用字体也是有局限的,其中最大的问题莫过于@font-face的兼容性问题。
3、遇到字体反爬怎么办?
遇到这种反爬虫怎么办呢!!!其实也不复杂,大部分语言都有字体库处理类库,这种情况只要每次解析出10个数字对应的字就可以了。用java来解决的话,推荐使用Apache.Fontbox,具体代码如下:
public static List<String> getMapper(String fontBase64) {
List<String> dic = new ArrayList<>();
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) {
CmapSubtable[] tables = ttf.getCmap().getCmaps();
CmapSubtable table = tables[0];// No matter what
for (int i = 1; i <= 10; i++) {
dic.add(String.valueOf((char) (int) (table.getCharacterCode(i))));
}
}
} catch (IOException e) {
}
return dic;
}
上面代码传入一段base64字符串,如果是文件可以稍作修改即可。
字体反爬,我在网寻找好久也没找见,后来偶然发现《神箭手》上面有相关解决办法,这里贴上原文,有兴趣可以看看:爬虫与诡异的字体-反爬与反反爬的奇技淫巧