反爬虫原理与绕过实战笔记

静态网页与动态网页

  • 传统的静态网页指没有数据库和不可交互的纯HTML页面,不修改代码则显示内容不会改变。
  • 传统的动态网页指在不改变页面HTML代码的情况下,能够根据不同用户或者不同操作而显示不同内容的网页。
    在爬虫领域中,静态网页与动态网页的定义与传统定义是完全不同的。
  • 静态网页指网页主题内容的渲染工作在服务器端完成,并通过响应正文返回的网页。
  • 动态网页指的是主体内容或者全部内容都需要客户端执行JavaScript代码来计算或渲染的网页。

爬虫并非所见即所得。在得到的资源中,最重要的就是响应正文。但是由于Python、Java和PHP等变成语言没有JavaScript解释器和渲染引擎,所以使用变成语言编写的爬虫程序无法渲染页面,它们智能爬取响应正文中的内容。有一些工具已经集成了渲染页面索需要的组件,并且开放API允许变成语言操作页面以获取渲染后的页面代码。

  • Splash:异步的JavaScript渲染服务
  • Selenium: 自动化测试框架
  • Puppeteer:一个通过DevTools协议控制Chrome的Node.js库

反爬虫的概念与定义

书内约定,限制爬虫程序访问服务器资源和获取数据的行为成为反爬虫。限制手段包括但不限于请求限制、拒绝响应、客户端身份验证、文本混淆和使用动态渲染技术。可以分成主动反爬和被动反爬。

  • 主动型反爬虫:开发者有意识地使用技术手段区分正常用户和爬虫,并限制爬虫对网站的访问行为,如验证请求头信息、限制访问频率、使用验证码等。
  • 被动型反爬虫:为了提升用户体验或节省资源,用一些技术间接提高爬虫访问难度的行为,比如数据分段加载、点击切换标签页、鼠标悬停预览数据等。
    还可以从特点上对反爬虫进行更细致的划分,如信息校验型反爬虫、动态渲染型反爬虫、文本混淆型反爬虫、特征识别型反爬虫等。需要注意的是,同一种限制现象可以被柜内到不同的反爬虫类型中,比如通过JS生成随机字符串并将字符串放在请求头中发送给服务器,服务器校验客户端身份的这种限制手段既可以说是信息校验型反爬虫,也可以说是动态渲染反爬虫。

反爬手段

信息校验型反爬虫

信息校验中的“信息”指的是客户端发起网络请求时的请求头和请求正文,而“校验”指的是服务器端通过对信息的正确性、完整性或唯一性进行验证或判断,从而区分正常用户和爬虫程序的行为。
在Web应用中,用户每次请求都会先经过服务器,然后转发到对应的后端程序。后端面临众多请求时要如何识别哪些是用户请求,哪些是爬虫请求?校验请求头和请求正文就可以区分正常用户和爬虫程序

User-Agent反爬虫

这是一种较为初级的反爬虫手段。
浏览器是一种用于检索并展示万维网信息资源的应用程序,使用浏览器在各个网页之间跳转其实就是访问不同的信息资源,服务器会根据客户端传递的请求信息以及身份信息返回客户端所希望接收的内容。User-Agent就是请求头域之一,服务器能够从User-Agent对应的值中识别客户端使用的操作系统、CPU类型、浏览器、浏览器引擎、操作系统语言等。之所以选择User-Agent头域作为校验对象,是因为很多变成语言和软件有默认的标识。比如使用Python中的Requests库向服务器发送HTTP请求时,服务器读取的User-Agent值为:

python-requests/2.21.0
使用Java和PHP等语言编写的库也有类似的默认标识。在nginx中可以设定黑名单,用以屏蔽爬虫程序的请求。nginx的配置生效后,只要请求头中的User-Agent头域值包含黑名单中的关键词,那么这次请求就无法通过校验。

1
2
3
4
5
6
7
# selenium 4
from selenium.webdriver.chrome.options import Options
user_agent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
options = Options()
options.add_argument(f"--User-Agent={user_agent}")
driver = webdriver.Chrome(options=options)
driver.get(url)

Cookie反爬虫

Cookie不近可以用于Web服务器的用户信息存储或状态保持,还能够用于反爬虫。大部分的爬虫程序在默认情况下只请求HTML文本资源,这意味着它们不会主动完成浏览器保存Cookie的操作,这次的反爬虫正式利用了这个特点。浏览器会自动检查响应头中是否存在Set-Cookie头域。如果存在,则将值保存在本地,而且往后的每次请求都会自动携带对应的Cookie值,这时候只要服务器端对请用头中的Cookie值进行校验即可。服务器会校验每个请求头中的Cookie值是否符合规则,对于不符合的请求将重新定向到首页。

  • 若携带正确Cookie,那么浏览器、Postman和爬虫程序发出的请求都可以正常响应。
  • 若未携带正确Cookie,那么浏览器、Postman和爬虫程序发出的请求都被重定向
  • 只有首页页面的响应头中有Set-Cookie头域,内容页的响应头中没有
    User-Agent和Cookie都是请求头的默认头域,在值的设定方面有一定的局限性,但是与JavaScript结合后,就会变得很灵活。相对服务器软件来说,后端程序的校验更为灵活且准确,但使用后端程序进行校验所需的步骤较多,在实际应用时可以根据需求选择合适的校验方式。

签名验证反爬虫

签名是根据数据源进行计算或加密的过程,签名的结果是一个具有唯一性和一致性的字符串。签名结果的特性使得它成为验证数据来源和数据完整性的条件,可以有效避免服务器端将伪造数据或被篡改的数据当成正常数据处理。
签名验证是防止恶意连接和数据被篡改的有效方式之一,也是目前后端API最常用的防护方式之一。与Cookie、User-Agent、Host和Referer等请求头域不同,用于签名验证的信息通常被放在请求正文中发送到服务器端。
(那跟我应该就没啥关系了,另外也看不懂了。。涉及到好多前端、后端、JavaScript的知识。。。)

动态渲染反爬虫

Selenium可破/doge

异步渲染服务Splash

如果只需要在一台计算机上运行爬虫程序,那么使用Selenium套件或者Puppeteer就可以满足渲染需求了。但如果是分布式爬虫呢?假如我们需要在30台服务器上启动爬虫程序,那么要在每一台服务器上安装一个Selenium套件嘛?
Splash是一个异步的JavaScript渲染服务,它是带有HTTP API的轻量级Web浏览器。SPlash能够并行地处理多个页面请求,在页面上下文中执行自定义的JavaScript以及浏览器中的点击、下滑等操作。有了Splash之后情况就变得不一样了,我么可以将Splash服务部署到云服务器上并配置负载均衡。这样做的好处是渲染服务压力大的时候,可以动态的增加Splash渲染服务。多个爬虫程序公用Splash服务还可以节省硬件资源。

(坑)

渲染工具知识扩展

但是Selenium有一个非常明显的问题就是:慢。开启webdriver,访问页面等待元素加载,模拟点击等等耗时过长。有没有更快的方法呢?
比如,页面上的内容是由JavaScript代码计算得出时,可以获得源数据后模仿JS逻辑自己在本地运算。

相比于直接使用浏览器的Selenium和Puppeteer来说,Splash在页面渲染、对新特性的支持等方面是比较差的。这个差距表现在对DOM节点的渲染和HTML Element时间操作上,例如点击事件触发后内容无法渲染到指定的位置。但是在浏览器中经常使用到的操作比如点击、滑动、拖拽、文本输入、复制、页面前进、后退、截图、文件下载等,Splash也同样能做到。

文本混淆反爬虫

文本混淆可以有效地避免爬虫获取Web应用中重要的文字数据,使用文本混淆限制爬虫虎丘文字数据的方式称为文本混淆反爬虫。反爬虫的前提是不能影响永固正常浏览网页和阅读文字内容,直接混淆文本很容易被看出来,所以开发者通常是利用CSS的特性来实现混淆。常见的文本混淆手段有图片伪装、文字映射和自定义字体等。

图片伪装反爬虫

图片伪装指的是将带有文字的图片与正常文字混合在一起,以达到“鱼目混珠”的效果,这种混淆方式不会影响用户阅读,但是可以让爬虫程序无法获得“所见”的文字内容。
(如何解决?上OCR!)

CSS偏移反爬虫

CSS偏移反爬虫指的是利用CSS央视将乱序的文字排版为人类正常阅读顺序的行为。这个概念不是很好理解,我们可以通过对比两段文字来加深对这个概念的理解。

HTML文本中的文字:我的学号是1308205,我在北京大学读书
浏览器显示的问题:我的学号是1380205,我在北京大学读书
爬虫看到的学号是1308205,但用户在浏览器中看到的却是1380205.如果不细心观察,爬虫工程师很容易被爬取结果糊弄。这种混淆方法和图片伪装一样,是不会影响用户阅读的。
这种情况可能需要观察页面上的CSS样式,找出其中的规律,将爬虫看到的数据转换成展示给用户的数据。

SVG映射反爬虫

字体反爬虫

文本混淆反爬虫通用解决方法

特征识别反爬虫

webdriver识别

浏览器特征

爬虫特征

隐藏链接反爬虫

App反爬虫

App抓包

APK文件反编译

代码混淆反爬虫

App应用加固知识扩展

了解应用程序自动化测试工具

验证码

字符验证码

计算型验证码

滑动验证码

滑动拼图验证码

滑动拼图验证吧在滑动验证码的基础上增加了随机滑动距离,用户需要使用滑动的方式完成拼图,才能通过校验。

文字点选验证码

鼠标轨迹的检测和原理

验证码产品赏析

综合知识

编码与加密

JavaScript代码混淆

前端禁止事件

法律法规