Scrapy-应对反爬虫机制
我们在运行爬虫的时候,如果爬取的网页较多,经常会遇到反爬虫问题,不让开发者进行爬取。因为现在很多网站都有相应的反爬虫机制,避免爬虫的而已爬取。所以,当我们要进行爬取大量网页的时候,很可能收到对方服务器的限制,从而被禁止,显然这不是我们想要的结果。在Scrapy项目中,主要可以通过以下方法来避免被禁止:
禁止Cookie
在Scrapy项目中的settings文件,可以发现文件中有以下代码:
# COOKIES_ENABLED = False
这句代码的用途是用来禁用Cookie的,只需将注释取消即可。让那些通过用户Cookie信息对用户进行识别和分析的网站无法识别我们,即无法禁止我们爬取。
设置下载延时与自动限速
有的网站会通过我们队网页的访问频率进行分析,如果爬取频率过快,则判断为爬虫自动爬取行为,识别后对我们进行相应限制,比如禁止我们再爬取该服务器上的网页等。对于这一类网站,我们只需要控制一下爬行时间间隔即可。在Scrapy项目中,我们可以直接在settings.py
文件进行相应的设置:
DOWNLOAD_DELAY = 3
这样,我们就实现了下载延时的功能,下载网页的时间间隔将为3秒。设置好了之后,就可以避免被这一类反爬虫机制的网站禁止。其实DOWNLOAD_DELAY = 3
在settings.py
中是存在的,只不过被注释了,我们只需要将这一行的注释取消即可。但是存在一个问题,DOWNLOAD_DELAY
设置完成之后,不能动态改变,导致访问延时都差不多,也容易被发现。不过我们可以设置RANDOMIZE_DOWNLOAD_DELAY
字段,进行动态调整:
RANDOMIZE_DOWNLOAD_DELAY = True
如果启用,当从相同的网站获取数据时,Scrapy将会等待一个随机的值,延迟时间为0.5到1.5之间的一个随机值乘以DOWNLOAD_DELAY
。这回大大降低被发现的几率,有一些网站会检测访问延迟的相似性,也有被发现的可能。Scrapy提供了一种更智能的方法来解决限速的问题:通过自动限速扩展,该扩展能根据Scrapy服务器及爬取的网站的负载自动限制爬取速度。
Scrapy是如何实现自动限速扩展的呢?在Scrapy中,下载延迟是通过计算建立TCP连接并接收到HTTP包头之间的时间间隔来测量的,该扩展就是以此为前提进行编写的,实现自动限速功能组要几个重要的配置:
# 启动自动限速扩展
AUTOTHROTTLE_ENABLED = True
# 初始下载延时,单位为秒
AUTOTHROTTLE_START_DELAY = 5
# 在高延迟情况下的最大下载延迟,单位为秒
AUTOTHROTTLE_MAX_DELAY = 60
# 启动DEBUG模式
AUTOTHROTTLE_DEBUG = True
# 对单个网址进行并发请求的最大值
CONCURRENT_REQUESTS_PER_DOMAIN = 8
# 对单个IP进行并发请求的最大值,如果非零,则自动忽略CONCURRENT_REQUESTS_PER_DOMAIN
CONCURRENT_REQUESTS_PER_IP = 0
设置IP池
有的网站会对用户的IP进行检测,如果同一个IP在短时间内对自己服务器上的网页进行大量的爬取,那么可以初步判定为网络爬虫的自动爬取行为,该网站有可能会针对该IP的用户禁止访问。如果我们的IP被禁止访问了,就需要更换IP,对于普通用户来说IP资源可能会有限,那么怎么样才能有较多的IP呢?利用代理服务器我们可以获取不同的IP,所以此时我们可以获取多个代理服务器,将这些服务器的IP组成一个IP池,爬虫每次对网页进行爬取的时候,可以随机选择IP池中的一个IP进行访问。如需满足以上需求,须要几个重要步骤:
- 在settings文件中添加:
# IP池
IPPOOL = [
{"ipaddr":"182.92.242.11:80"},
{"ipaddr":"222.132.194.45:8118"},
{"ipaddr":"114.239.146.29:808"},
{"ipaddr":"114.239.148.97:808"}
]
- 中间件(即 middlewares.py,创建project时自动创建此文件)设置,将中间件原先代码清空,添加以下代码:
import scrapy
import random
from BanSpider.settings import IPPOOL
import scrapy.downloadermiddleware.httpproxy import HttpProxyMiddleware
class IPPools(HttpProxyMiddleware):
def __init__(self,ip=""):
self.ip = ip
def process_request(self,request,spider):
# 随机取出一个ip字典
ipDict = random.choice(IPPOOL)
request.meta["proxy"] = "http://"+ipDict["ipaddr"]
将此中间件添加到settings
文件中:
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddleware.httpproxy.HttpProxyMiddleware':123,
# 中间件middlewares中IPPools函数的路径,根据值排序
'BanSpider.middlewares.IPPools':120
}
使用用户代理池
我们知道,网站服务器可以识别爬行时候用户代理信息,通过用户代理信息可以判断出我们使用的是什么浏览器、什么形式的客户端等。所以对方的网站服务器可以根据我们的User-Agent信息,对我们的爬行行为进行分析,以此来实现反爬虫处理。最为爬虫方,显然不希望就这样被封禁,为了避免这一类的禁止,我们可以使用用户代理池进行处理。如需满足以上需求,须要几个重要步骤:
- settings设置用户代理池
USER_POOL = [
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
]
- 创建一个下载中间件文件usermiddleware
import random
from BanSpider.settings import USER_POOL
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
class UserMid(UserAgentMiddleware):
def __init__(self,user=""):
self.user = user
def process_request(self,request,spider):
user = random.choice(USER_POOL)
request.headers.setdefault("User-Agent",user)
将此中间件添加到settings
文件中:
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware':100,
'BanSpider.usermiddleware.UserMid':99
}
ROBOTSTXT
有时我们进行网络爬虫时,会遇到这样的问题:
DEBUG:Forbidden by robots.txt
解决:
在settings文件中,找到ROBOTSTXT设置,将True改为False
ROBOTSTXT_OBEY = False