使用scrapy spider捕获http状态代码

rep*_*key 10 python scrapy web-scraping

我是scrapy的新手.我正在编写一个蜘蛛,旨在检查服务器状态代码的长列表,并在适当的情况下检查重定向到的URL.重要的是,如果存在重定向链,我需要知道每次跳转时的状态代码和URL.我正在使用response.meta ['redirect_urls']来捕获网址,但我不确定如何捕获状态代码 - 似乎没有响应元关键字.

我意识到我可能需要编写一些自定义中间件来公开这些值但是我不太清楚如何记录每一跳的状态代码,也不清楚如何从蜘蛛中访问这些值.我看过了,但找不到任何人这样做的例子.如果有人能指出我正确的方向,我将不胜感激.

例如,

    items = []
    item = RedirectItem()
    item['url'] = response.url
    item['redirected_urls'] = response.meta['redirect_urls']     
    item['status_codes'] = #????
    items.append(item)
Run Code Online (Sandbox Code Playgroud)

编辑 - 基于来自warawauk的反馈以及来自IRC频道(freenode #scrappy)的人的一些非常主动的帮助,我设法做到了这一点.我相信它有点hacky所以任何改进的意见欢迎:

(1)在设置中禁用默认中间件,并添加自己的:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.contrib.downloadermiddleware.redirect.RedirectMiddleware': None,
    'myproject.middlewares.CustomRedirectMiddleware': 100,
}
Run Code Online (Sandbox Code Playgroud)

(2)在middlewares.py中创建CustomRedirectMiddleware.它继承自主redirectmiddleware类并捕获重定向:

class CustomRedirectMiddleware(RedirectMiddleware):
    """Handle redirection of requests based on response status and meta-refresh html tag"""

    def process_response(self, request, response, spider):
        #Get the redirect status codes
        request.meta.setdefault('redirect_status', []).append(response.status)
        if 'dont_redirect' in request.meta:
            return response
        if request.method.upper() == 'HEAD':
            if response.status in [301, 302, 303, 307] and 'Location' in response.headers:
                redirected_url = urljoin(request.url, response.headers['location'])
                redirected = request.replace(url=redirected_url)

                return self._redirect(redirected, request, spider, response.status)
            else:
                return response

        if response.status in [302, 303] and 'Location' in response.headers:
            redirected_url = urljoin(request.url, response.headers['location'])
            redirected = self._redirect_request_using_get(request, redirected_url)
            return self._redirect(redirected, request, spider, response.status)

        if response.status in [301, 307] and 'Location' in response.headers:
            redirected_url = urljoin(request.url, response.headers['location'])
            redirected = request.replace(url=redirected_url)
            return self._redirect(redirected, request, spider, response.status)

        if isinstance(response, HtmlResponse):
            interval, url = get_meta_refresh(response)
            if url and interval < self.max_metarefresh_delay:
                redirected = self._redirect_request_using_get(request, url)
                return self._redirect(redirected, request, spider, 'meta refresh')


        return response
Run Code Online (Sandbox Code Playgroud)

(3)您现在可以访问蜘蛛中的重定向列表

request.meta['redirect_status']
Run Code Online (Sandbox Code Playgroud)