我正在为项目(数据科学)搜索有关元理论的公共数据,为了有效地做到这一点,我需要在403响应代码的情况下更改我的scrapy请求中使用的代理。
为此,我定义了一个下载中间件来处理这种情况,如下所示
class ProxyMiddleware(object):
def process_response(self, request, response, spider):
if response.status == 403:
f = open("Proxies.txt")
proxy = random_line(f) # Just returns a random line from the file with a valid structure ("http://IP:port")
new_request = Request(url=request.url)
new_request.meta['proxy'] = proxy
spider.logger.info("[Response 403] Changed proxy to %s" % proxy)
return new_request
return response
在将类正确添加到settings.py之后,我希望这个中间件通过使用新代理生成新请求来处理403响应,从而完成200响应。观察到的行为是它实际上被执行了(我可以看到有关Changed代理的Logger信息),但似乎没有新的请求。相反,我得到了这个:
2018-12-26 23:33:19 [bot_2] INFO: [Response] Changed proxy to https://154.65.93.126:53281
2018-12-26 23:33:26 [bot_2] INFO: [Response] Changed proxy to https://176.196.84.138:51336
...无限期地使用随机代理,这让我觉得我仍在检索403错误而代理没有改变。
阅读the documentation,关于process_response,它指出:
(...)如果它返回一个Request对象,则暂停中间件链,并重新安排返回的请求,以便将来下载。这与从process_request()返回请求的行为相同。
是否“未来”不是“归还后”?从那一刻起,我该如何更改所有请求的代理?
默认情况下,Scrapy会将重复请求丢弃到同一个URL,这可能就是蜘蛛上发生的事情。要检查这是否是您的情况,您可以设置此设置:
DUPEFILTER_DEBUG=True
LOG_LEVEL='DEBUG'
要解决这个问题,你应该添加dont_filter=True
:
new_request = Request(url=request.url, dont_filter=True)
试试这个:
class ProxyMiddleware(object):
def process_response(self, request, response, spider):
if response.status == 403:
f = open("Proxies.txt")
proxy = random_line(f)
new_request = Request(url=request.url)
new_request.meta['proxy'] = proxy
spider.logger.info("[Response 403] Changed proxy to %s" % proxy)
return new_request
else:
return response
更好的方法是使用scrapy随机代理模块:
'DOWNLOADER_MIDDLEWARES' : {
'rotating_proxies.middlewares.RotatingProxyMiddleware': 610,
'rotating_proxies.middlewares.BanDetectionMiddleware': 620
},