爬虫工程师和反爬虫工程师之间的友好问候

爬虫和反爬虫

爬虫工程师的手段

从渲染好的 html 页面直接找到感兴趣的节点,然后获取对应的文本

去分析对应的接口数据,更加方便、精确地获取数据

反爬虫:

基于用户行为

检测cookie,封ip

动态网页

某一时间内请求次数过多

反爬虫措施

反爬虫的措施

  • 使用HTTPS 协议
  • 单位时间内限制掉请求次数过多,则封锁该账号
  • 前端技术限制 (接下来是核心技术)

比如需要正确显示的数据为“19950220”

  1. 先按照自己需求利用相应的规则(数字乱序映射,比如正常的0对应还是0,但是乱序就是 0 <-> 1,1 <-> 9,3 <-> 8,…)制作自定义字体(ttf)
  2. 根据上面的乱序映射规律,求得到需要返回的数据 19950220 -> 17730220
  3. 对于第一步得到的字符串,依次遍历每个字符,将每个字符根据按照线性变换(y=kx+b)。线性方程的系数和常数项是根据当前的日期计算得到的。比如当前的日期为“2018-07-24”,那么线性变换的 k 为 7,b 为 24。
  4. 然后将变换后的每个字符串用“3.1415926”拼接返回给接口调用者。(为什么是3.1415926,因为对数字伪造反爬,所以拼接的文本肯定是数字的话不太会引起研究者的注意,但是数字长度太短会误伤正常的数据,所以用所熟悉的 Π)

前端拿到数据后再解密,解密后根据自定义的字体 Render 页面

  1. 先将拿到的字符串按照“3.1415926”拆分为数组
  2. 对数组的每1个数据,按照“线性变换”(y=kx+b,k和b同样按照当前的日期求解得到),逆向求解到原本的值。
  3. 将步骤2的的到的数据依次拼接,再根据 ttf 文件 Render 页面上。

后端需要根据上一步设计的协议将数据进行加密处理

下面以 Node.js 为例讲解后端需要做的事情

  • 首先后端设置接口路由
  • 获取路由后面的参数
  • 根据业务需要根据 SQL 语句生成对应的数据。如果是数字部分,则需要按照上面约定的方法加以转换。
  • 将生成数据转换成 JSON 返回给调用者

前端根据服务端返回的数据逆向解密

比如后端返回的是323.14743.14743.1446,根据我们约定的算法,可以的到结果为1773

  • 根据 ttf 文件 Render 页面 上面计算的到的1773,然后根据ttf文件,页面看到的就是1995
  • 然后为了防止爬虫人员查看 JS 研究问题,所以对 JS 的文件进行了加密处理。如果你的技术栈是 Vue 、React 等,webpack 为你提供了 JS 加密的插件,也很方便处理
  • 个人觉得这种方式还不是很安全。于是想到了各种方案的组合拳。比如

反爬升级版

个人觉得如果一个前端经验丰富的爬虫开发者来说,上面的方案可能还是会存在被破解的可能,所以在之前的基础上做了升级版本

  1. 组合拳1: 字体文件不要固定,虽然请求的链接是同一个,但是根据当前的时间戳的最后一个数字取模,比如 Demo 中对4取模,有4种值 0、1、2、3。这4种值对应不同的字体文件,所以当爬虫绞尽脑汁爬到1种情况下的字体时,没想到再次请求,字体文件的规则变掉了 😂
  2. 组合拳2: 前面的规则是字体问题乱序,但是只是数字匹配打乱掉。比如 1 -> 4, 5 -> 8。接下来的套路就是每个数字对应一个 unicode 码 ,然后制作自己需要的字体,可以是 .ttf、.woff 等等。

这几种组合拳打下来。对于一般的爬虫就放弃了。

反爬手段再升级

上面说的方法主要是针对数字做的反爬手段,如果要对汉字进行反爬怎么办?接下来提供几种方案

  1. 方案1: 对于你站点频率最高的词云,做一个汉字映射,也就是自定义字体文件,步骤跟数字一样。先将常用的汉字生成对应的 ttf 文件;根据下面提供的链接,将 ttf 文件转换为 svg 文件,然后在下面的“字体映射”链接点进去的网站上面选择前面生成的 svg 文件,将svg文件里面的每个汉字做个映射,也就是将汉字专为 unicode 码(注意这里的 unicode 码不要去在线直接生成,因为直接生成的东西也就是有规律的。我给的做法是先用网站生成,然后将得到的结果做个简单的变化,比如将“e342”转换为 “e231”);然后接口返回的数据按照我们的这个字体文件的规则反过去映射出来。
  2. 方案2: 将网站的重要字体,将 html 部分生成图片,这样子爬虫要识别到需要的内容成本就很高了,需要用到 OCR。效率也很低。所以可以拦截钓一部分的爬虫
  3. 方案3: 看到携程的技术分享“反爬的最高境界就是 Canvas 的指纹,原理是不同的机器不同的硬件对于 Canvas 画出的图总是存在像素级别的误差,因此我们判断当对于访问来说大量的 canvas 的指纹一致的话,则认为是爬虫,则可以封掉它”。

本人将方案1实现到 Demo 中了。

关键步骤

  1. 先根据你们的产品找到常用的关键词,生成词云
  2. 根据词云,将每个字生成对应的 unicode 码
  3. 将词云包括的汉字做成一个字体库
  4. 将字体库 .ttf 做成 svg 格式,然后上传到 icomoon 制作自定义的字体,但是有规则,比如 “年” 对应的 unicode 码“\u5e74” ,但是我们需要做一个 恺撒加密 ,比如我们设置 偏移量 为1,那么经过恺撒加密 “年”对应的 unicode 码是“\u5e75” 。利用这种规则制作我们需要的字体库
  5. 在每次调用接口的时候服务端做的事情是:服务端封装某个方法,将数据经过方法判断是不是在词云中,如果是词云中的字符,利用规则(找到汉字对应的 unicode 码,再根据凯撒加密,设置对应的偏移量,Demo 中为1,将每个汉字加密处理)加密处理后返回数据
  6. 客户端做的事情:
    • 先引入我们前面制作好的汉字字体库
    • 调用接口拿到数据,显示到对应的 Dom 节点上
    • 如果是汉字文本,我们将对应节点的 css 类设置成汉字类,该类对应的 font-family 是我们上面引入的汉字字体库

实现的效果

  1. 页面上看到的数据跟审查元素看到的结果不一致
  2. 去查看接口数据跟审核元素和界面看到的三者不一致
  3. 页面每次刷新之前得出的结果更不一致
  4. 对于数字和汉字的处理手段都不一致

这几种组合拳打下来。对于一般的爬虫就放弃了。

建议

  1. 先设计一个字体图标的制作规则
  2. JS 接入之后修改设置字体的处理展示逻辑
  3. 如果使用传统的网页开发技术(比如传统的 jQuery 模式)建议你将业务设计的 JS 进行 加密混淆,这里是一个混淆工具,增加反爬成本。如果是使用的 webpack 类的方式那么可以设置压缩规则,代码可读性也下降了。(当然推荐读者自己去研究下在使用 webpack 模式下如何让打包出的代码更加难以阅读,因为我的经验是即使 Vue、React 脚手架打包出的工程的 js, 在 Chrome 开发者模式下点击代码左下角的 {} 按钮(Pretty Print) 可以对混淆后的代码进行格式化,可读性又好一些了,还是方便调试和阅读)

程序员都不容易,做爬虫的尤其不容易。可怜可怜他们给他们一小口饭吃吧。没准过几天你就因为反爬虫做得好,改行做爬虫了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值