我正在使用scrapy 1.1来抓一个网站.该网站需要定期重新登录.我知道何时需要这个,因为当需要登录时,会发生302重定向.基于#http://sangaline.com/post/advanced-web-scraping-tutorial/,我已经将RedirectMiddleware子类化,使蜘蛛中的位置http头可用于:
request.meta['redirect_urls']
Run Code Online (Sandbox Code Playgroud)
我的问题是登录后,我已经设置了一个函数来循环100页来刮.让我们说15页后,我发现我必须重新登录(根据request.meta ['redirect_urls']的内容).我的代码看起来像:
def test1(self, response):
......
for row in empties: # 100 records
d = object_as_dict(row)
AA
yield Request(url=myurl,headers=self.headers, callback=self.parse_lookup, meta={d':d}, dont_filter=True)
def parse_lookup(self, response):
if 'redirect_urls' in response.meta:
print str(response.meta['redirect_urls'])
BB
d = response.meta['d']
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我收到了'通知'需要在BB中的parse_lookup重新登录,但需要反馈这些信息以取消在test1(AA)中创建请求的循环.如何在先前的回调函数中使用解析查找中的信息?
为什么不使用DownloaderMiddleware?
您可以像这样编写DownloaderMiddleware:
编辑:我编辑了原始代码,以解决OP在评论中遇到的第二个问题.
from scrapy.http import Request
class CustomMiddleware():
def process_response(self, request, response, spider):
if 'redirect_urls' in response.meta:
# assuming your spider has a method for handling the login
original_url = response.meta["redirect_urls"][0]
return Request(url="login_url",
callback=spider.login,
meta={"original_url": original_url})
return response
Run Code Online (Sandbox Code Playgroud)
因此,在进入parse_lookup并重新登录/修复错误并产生新请求之前,您将"拦截"响应...
就像TomášLinhart所说的那样,请求是异步的,所以我不知道你是否可以通过连续几次"重新登录"来遇到问题,因为多个请求可能同时被重定向.
请记住将中间件添加到您的设置:
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 542,
'myproject.middlewares.CustomDownloaderMiddleware': 543,
}
Run Code Online (Sandbox Code Playgroud)