Web scraping 无法使用Scrapy修改中间件中的请求

Web scraping 无法使用Scrapy修改中间件中的请求,web-scraping,scrapy,scrapy-spider,Web Scraping,Scrapy,Scrapy Spider,我正在为一个项目(数据科学)收集有关方法学的公共数据,为了有效地做到这一点,我需要在收到403响应代码的情况下更改用于我的scrapy请求的代理 为此,我定义了一个下载中间件来处理这种情况,如下所示 class ProxyMiddleware(object): def process_response(self, request, response, spider): if response.status == 403: f = open(

我正在为一个项目(数据科学)收集有关方法学的公共数据,为了有效地做到这一点,我需要在收到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个响应中完成。观察到的行为是它实际上得到了执行(我可以看到关于已更改代理的记录器信息),但新请求似乎没有发出。相反,我得到的是:

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个错误,并且代理没有改变

阅读,关于过程\响应,它指出:

(…)如果它返回一个请求对象,中间件链将停止,返回的请求将被重新安排在将来下载。这与从进程_request()返回请求的行为相同


有没有可能“将来”不是“归还之后”呢?从那一刻起,我应该如何更改所有请求的代理?

默认情况下,Scrapy会将重复请求删除到同一url,因此您的爬行器上可能就是这样。要检查这是否是您的情况,您可以设置以下设置:

DUPEFILTER_DEBUG=True
LOG_LEVEL='DEBUG'
要解决此问题,您应该添加
dont\u 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 random proxies模块:

'DOWNLOADER_MIDDLEWARES' : {
    'rotating_proxies.middlewares.RotatingProxyMiddleware': 610,
    'rotating_proxies.middlewares.BanDetectionMiddleware': 620
},

从那时起,我应该如何更改所有请求的代理可能在
处理请求中执行此操作。另外,如果您认为request.meta没有被更改,请检查它。另外,如果这实际上是您正在运行的代码,您将希望
f.close()
或使用
with
语句,否则您将泄漏文件句柄。有没有一种好方法可以使进程响应影响进程请求?目前我唯一的想法是定义一个全局变量,该变量由process\u响应修改并由process\u请求检测。可行吗?