水滴石主要分享一些生活中的经验和IT技术自学过程中积累的技术、学习资源和软件资源等。座右铭:坚持+自律=开挂人生。
当前位置: 首页 > python > 避免scrapy服务器IP地址被屏蔽的几种方法

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

标签: python爬虫

我们在使用python爬虫框架scrapy的时候,经常由于爬取速度设置不合理、伪装不成功等原因被封ip地址、被屏蔽,为了解决此问题,我在网上收集整理了几种解决方法,在此分享给大家,希望有用。

scrapy原理图


一、爬虫被封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.


通过以上办法基本上能够解决90%的scrapy被封ip的情况,剩下的10%的情况比较复杂,需要更深入的研究和学习才能解决,希望大家都能够学好scrapy,并将之应用于生活方便自己。

更多相关推荐

  • 没有相关文章

版权保护:本文《避免scrapy服务器IP地址被屏蔽的几种方法》由<我爱分享>原创,转载请保留链接:http://www.shuidi365.cn/python/79.html

相关推荐
  • 没有相关文章

此博客主要用来分享、推荐自己日常、学习过程中感觉比较实用的经验、IT技术和一些比较好的资源(各种软件、各种开发手册、各种学习资料、各种视频教程等),希望对大家有所帮助,有问题请留言,欢迎来交流,联系QQ邮箱/微信:342807450

文章分类
合作伙伴
冀ICP备19020226号-1 冀公网安备 13010902000246号