所谓反爬虫就是被爬取的网站通过一定的技术手段如判断User-Agent或者限制IP等方式防止爬虫爬取,而反反爬虫则是有针对性的通过技术手段突破这些限制,依旧爬取到想获取的信息。本文主要介绍几个实用的反反爬虫的技术。
1.切换User-Agent:
最简单的方法:在settings.py中设置多个User-Agent ,把他定义成一个常量
USER_AGENT_LIST = [ "...", "...",...]
然后再spider中
这个方法是放在spider中,当你在spider中凡是有yield scrapy.Request(...)的时候,就调用一下这个getUA方法,这样User-Agent就会改变。
但是每次Request都要获取调用getUA函数会很难受。
所以我们写在中间件中。
scrapy的源码中其实就有一个useragent.py,里面写着一个
UserAgentMiddleware中间件,它里面做了一件事情,他从settings获取USER_AGENT这个常量,并且将他设成默认header
中间件的源码位于D:\python3.6\Lib\site-packages\scrapy\downloadermiddlewares
在中间件中,可以修改request和response,而且是全局性的修改。
如果我们要写自己的user-agent中间件,我们必须先将他源码中的user-agent中间件取消掉。
现在我们在middlewares.py中写自己的useragent中间件类
这里使用from_crawler是为了获取配置信息。
定义了from_setting或者from_crawler就必须return cls(...),而且必须定义__init__
上面的return cls(crawler) 中的cls就是RandUAMiddleware类本身。cls()是实例化RandUAMiddleware类并且向这个类的初始化方法传入一个crawler参数。
所以__init__方法中有一个crawler的形参供传递。
可是,自己定义的User-Agent毕竟有限,如果想要获取无限随机的User-Agent,可以实用python的fake-useragent模块
pip install fake-useragent
使用方法:
集成到scrapy的middleware中
PS:如果request.headers.setdefault()方法失效了,导致User-Agent没有填进去,我们可以这样:
request.headers['User-Agent'] = self.ua.random
2.设置代理IP
有些网站会通过检测一段时间内某个IP的访问次数来判断你是否在用爬虫爬取他的网站信息,如果几秒内这个ip的访问次数达到上百次,那很明显就是有爬虫在爬取,此时这个IP就会被列入黑名单,运气好只会限制该IP一段时间不能访问,运气不好可能会永久封禁。这种方式是最常见也最有效的一种的反爬虫的技术。
而想要突破这种防范,我们就要使用多个IP轮流访问,这样相当于是很多用户在正常访问这个网站。为此我们需要使用代理IP。
代理ip的原理:
假如有一个23.225.228.56:80的代理ip,我们要爬取lagou.com
原本我们是直接请求lagou.com的服务器
但现在,我是先请求23.225.228.56的服务器,之后这个服务器再去请求拉钩网的服务器并将数据返回给我。
设置代理ip很简单,只需要在middleware的process_request中这样:
即可
但关键是怎么获取这些代理IP
接下来我们要设置一个ip代理池,做法是,在“快代理”这个免费代理ip网中爬取他的代理ip,并保存到数据库中。
“快代理”代理IP
等我们要用到这些代理ip的时候,直接从数据库里面调用就是。
获取3个字段:类型(http/https),ip,端口
创建数据表
爬取代理网站的蜘蛛如下:
item如下:
pipeline如下:
这样就能够获取很多免费的代理IP,但是免费的代理IP有很多是无效的,不能访问的,为此还写了一个用来获取有效代理ip的类,放在tool目录中,下面的脚本要爬取到代理IP之后才能执行:
每调用一次tool.get()方法就会从数据库中获取代理(所以要先爬到很多代理ip才能用ProxyTool类去获取代理ip),然后用这个代理访问百度,如果访问百度失败说明是个无效ip
就会从数据库中干掉。
结果发现,每10个ip只有1个能用,而且检测的过程很耗时间。
结论:使用免费代理ip不是一个可靠的方案
还有其他两种可靠方案:
crawlera:官方ip代理插件,需要去官网购买key,可靠稳定,强大
tor洋葱网络 : 匿名发送数据,需要翻墙,稳定性非常高
3. 限速爬取
如果使用免费代理IP觉得很慢,又不想花钱去买高效的代理IP,我们可以通过限速爬取来应对封禁IP的防范,当然是以降低爬取速度作为牺牲
scrapy有一套自己的限速机制,但是要在settings.py中设置才行。
找到
DOWNLOAD_DELAY = 1
AUTOTHROTTLE_ENABLED = True
这两句
然后将他们的注释去掉
DOWNLOAD_DELAY设置的越大,爬取的速度越慢,越能有效防止被封
4.禁用cookie
有些网站的反爬虫是通过检测的请求中的cookie信息进行的
对于一些不需要登陆的网站,我们禁用cookie即可反反爬虫
setting中的:
COOKIES_ENABLED = False
将这句注释去掉即可
5.使用selenium模块进行动态爬取
有一些网站的内容是通过js动态加载的,例如使用ajax请求,这样动态加载的内容无法出现在源代码中,我们就无法获取到这部分内容。有时候,这是因为业务逻辑的需求要使用 js 动态加载,但是有时候也是因为防止爬虫而使用 js 加载。
selenium的原理是模仿浏览器访问页面,将动态加载的内容也渲染到页面时候,再获取渲染好的页面代码。从而解决这个问题。
selenium的使用具体在下一节介绍