避免scrapy服务器IP地址被屏蔽的几种方法

你在这里

避免scrapy服务器IP地址被屏蔽的几种方法

一、爬虫被封IP的原因
很多被Scrapy等爬虫程序抓取的目标网站的服务器都会进行访问检测,没有通过检测的IP地址会被服务器加入黑名单,通常会返回拒绝服务403,其检测常包含以下几种方式:
1.访问频率限制:访问太快,服务器就会认为不是人而是爬虫的操作;
2.以固定间隔时间访问:每次访问间的时间间隔都固定,则服务器就会认为不是人而是爬虫的操作;
3.访问请求的头部user agent是否为通用浏览器访问时采用的请求头部,如果不是或者为空时,则服务器就会认为不是人而是爬虫的操作。
4.网站会通过Cookie识别用户身份,以此判断是人还是爬虫。
二、解决被封策略
1.设置下载延迟DOWNLOAD_DELAY,数字越大越安全
2.设置请求后一个随机时延,模拟更真实的人类访问
3.使用user agent池。也就是每次发送的时候随机从池中选择不一样的浏览器头信息,防止暴露爬虫身份
4.禁止Cookie,某些网站会通过Cookie识别用户身份,禁用后使得服务器无法识

5.使用代理IP池

6.分布式爬取,这个是针对大型爬虫系统的
7.伪造x-forward-for,伪装自身为代理,让服务器不认为你是爬虫
三、具体代码
具体实现中,ZZKOOK仅通过动态设置代理及请求头部,并增加请求时延,就打破了服务器的屏蔽,具体代码如下:
1.在scrapy工程myscrapy目录下的设置文件settings.py中
配置MY_USER_AGENTS和MY_PROXIES为自定义参数,动态设置代理及请求头部:
MY_USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
    "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
]
MY_PROXIES = [
    {'ip_port': '218.249.45.162:35586', 'user_pass': ''},
    {'ip_port': '115.238.59.86:53400', 'user_pass': ''},
    {'ip_port': '120.83.110.244:9999', 'user_pass': ''},
]
 
2.仍然是在settings.py中配置动态代理IP及请求头获取的中间件:
#scrapy代理IP、user agent的切换都是通过DOWNLOADER_MIDDLEWARES进行控制,下面我们创建middlewares.py文件。
DOWNLOADER_MIDDLEWARES = { 
'myscrapy.middlewares.RandomUserAgent': 1,
'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 110, 
'myscrapy.middlewares.ProxyMiddleware': 100 
}
 
3.在scrapy工程myscrapy目录下创建文件中间件文件middlewares.py,并在其中加入动态获取代理IP地址和请求头部的User agent的类:ProxyMiddleware和RandomUserAgent,具体代码如下:
from stockfetch.settings import MY_PROXIES
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware

#类ProxyMiddleware用来切换代理,proxy列表MY_PROXIES也是在settings.py中进行配置。
class ProxyMiddleware(object):
    def process_request(self, request, spider):
        proxy = random.choice(MY_PROXIES)
        if proxy['user_pass'] is not '':
            request.meta['proxy'] = "http://%s" % proxy['ip_port']
            encoded_user_pass = base64.b64encode(proxy['user_pass'].encode('utf-8'))
            request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass.decode()
            print("**************ProxyMiddleware have pass************" + proxy['ip_port'])
        else:
            print("**************ProxyMiddleware no pass************" + proxy['ip_port'])
            request.meta['proxy'] = "http://%s" % proxy['ip_port']

#类RandomUserAgent主要用来动态获取user agent,user agent列表MY_USER_AGENTS在settings.py中进行配置。
class RandomUserAgent(UserAgentMiddleware):
    def __init__(self, agents):
        self.agents = agents

    @classmethod
    #scrapy为我们提供了from_crawler()的方法访问设置信息,此处从settings里面取出USER_AGENT列表
    def from_crawler(cls, crawler):
        return cls(crawler.settings.getlist('MY_USER_AGENTS'))
        
    #随机从列表中选择一个,添加到headers里面,最后默认返回了None。
    def process_request(self, request, spider):
        agent = random.choice(self.agents)
        request.headers['User-Agent'] = agent
        request.headers.setdefault('User-Agent', random.choice(self.agents))
        print "**************" + agent


4.在Scrapy工程myscrapy的设置文件settings.py中设置时延、重试次数、请求并发次数等系统参数,如下:
#下载同一个网站下一个页面前需要等待的时间
DOWNLOAD_DELAY = 1
#重试次数
RETRY_ENABLED = True
RETRY_TIMES = 5
#请求并发数
CONCURRENT_REQUESTS = 3 

5.在蜘蛛文件,即myscrapy\spiders\myspider.py中每一次请求之间增加一个随机的时延,如下:
class MyspiderSpider(scrapy.Spider):
    name = 'myspider'
    def start_requests(self): 
        ....        
        request = Request(url)
         #增加一个随机时延,减小服务器地址被屏蔽的可能
         wait = random.randint(1,10)
         time.sleep(wait * 0.1)
         yield request
 

四、常见错误

1.twisted.python.failure.Failure twisted.internet.error.ConnectionLost: Connection to the other side was lost in a non-clean fashion
问题原因:
查看url,爬取简书网站,使用的url是start_url = “http://www.jianshu.com/”,一直报错,其他的各种浏览器数据都加了,包括浏览器头部user agent,但还是报上面那种错误。仔细对比,简书网站是重定向到https://www.jianshu.com/的,也就是说从http协议到https协议。
解决方案:
1)在http请求头部设置字段,即升级http协议的字段,让它支持https。
2)若果怕麻烦的,直接start_url = “https://www.jianshu.com/
 
2.An error occurred while connecting: 104: Connection reset by peer.
 
著作权归作者所有。商业转载请联系本站作者获得授权,非商业转载请注明出处 ZZKOOK

您可能感兴趣的文章

登录以发表评论

评论

程序猿的工作让人崩溃

 
17
sky的头像

感谢分享!!!

 
13
春芽儿的头像