1

我在尝试用我的蜘蛛管理 404 响应时遇到了一些问题。似乎 ScrapySlash 用 200 掩盖了 404 响应。

这是我的代码

def buildRequest(self, url, dbid):
     request = Request(url, self.parse, meta={
                  'splash': {
                      'args':{
                          'html': 1,
                          'wait': 5
                          },
                      'magic_response':True,
                      },
                 'dbId': dbid
                  }, errback=self.errback_httpbin, dont_filter=True)
     return request

一个简单的print response.status总是显示 200。测试我的 urlscrapy shell将显示response <404 http://www.foo.com/>

当我使用 Request 对象时,我的蜘蛛会转到self.errback_httpbin方法,但使用 SpaslRequest 它不会。SlashRequest 正确处理 502 但不是 404。

谢谢

4

1 回答 1

2

看来您只能将/execute响应与“魔术响应”(默认情况下为 ON)结合使用来实现此目的:

meta['splash']['magic_response']- 当设置为 True 并且从 Splash 接收到 JSON 响应时,响应的几个属性(标题、正文、url、状态代码)使用 JSON 中返回的数据填充:

  • response.headers 由 ' headers' 键填充;
  • response.url 设置为 ' url' 键的值;
  • response.body 设置为“ html”键的值,或“body”键的 base64 解码值;
  • response.status 设置为“ http_status”键的值。(...)

如果True您使用SplashRequest.

其他端点喜欢/render.html并且/render.json将针对来自远程服务器的 4xx 和 5xx 响应返回 502 Bad Gateway(待检查)。

以 README 中的 Lua 脚本示例为基础:

function main(splash)
  splash:init_cookies(splash.args.cookies)
  assert(splash:go{
    splash.args.url,
    headers=splash.args.headers,
    http_method=splash.args.http_method,
    body=splash.args.body,
    })
  assert(splash:wait(0.5))

  local entries = splash:history()
  local last_response = entries[#entries].response
  return {
    url = splash:url(),
    headers = last_response.headers,
    http_status = last_response.status,
    cookies = splash:get_cookies(),
    html = splash:html(),
  }
end

(注意最后的表格,返回 url、headers、http_status、html 和 cookies。)

...当您将此脚本与/execute,SplashRequest和 errbacks 一起使用时,您可以从 Scrapy docs 重现 errback 示例

import scrapy

from scrapy.spidermiddlewares.httperror import HttpError
from twisted.internet.error import DNSLookupError
from twisted.internet.error import TimeoutError, TCPTimedOutError

from scrapy_splash import SplashRequest

script = """
function main(splash)
  splash:init_cookies(splash.args.cookies)
  assert(splash:go{
    splash.args.url,
    headers=splash.args.headers,
    http_method=splash.args.http_method,
    body=splash.args.body,
    })
  assert(splash:wait(0.5))

  local entries = splash:history()
  local last_response = entries[#entries].response
  return {
    url = splash:url(),
    headers = last_response.headers,
    http_status = last_response.status,
    cookies = splash:get_cookies(),
    html = splash:html(),
  }
end
"""

class ErrbackSpider(scrapy.Spider):
    name = "errback_example"
    start_urls = [
        "http://www.httpbin.org/",              # HTTP 200 expected
        "http://www.httpbin.org/status/404",    # Not found error
        "http://www.httpbin.org/status/500",    # server issue
    ]

    def start_requests(self):
        for u in self.start_urls:
            yield SplashRequest(u, callback=self.parse_httpbin,
                                   errback=self.errback_httpbin,
                                   endpoint='execute',
                                   args={'lua_source': script})

    def parse_httpbin(self, response):
        self.logger.info('Got successful response from {}'.format(response.url))
        # do something useful here...

    def errback_httpbin(self, failure):
        # log all failures
        self.logger.error(repr(failure))

        # in case you want to do something special for some errors,
        # you may need the failure's type:

        if failure.check(HttpError):
            # these exceptions come from HttpError spider middleware
            # you can get the non-200 response
            response = failure.value.response
            self.logger.error('HttpError on %s', response.url)

        elif failure.check(DNSLookupError):
            # this is the original request
            request = failure.request
            self.logger.error('DNSLookupError on %s', request.url)

        elif failure.check(TimeoutError, TCPTimedOutError):
            request = failure.request
            self.logger.error('TimeoutError on %s', request.url)

用scrapy 1.3运行它,你会得到:

$ scrapy crawl errback_example
2017-01-11 18:07:20 [scrapy.utils.log] INFO: Scrapy 1.3.0 started (bot: test404)
(...)
2017-01-11 18:07:20 [scrapy.core.engine] INFO: Spider opened
(...)
2017-01-11 18:07:21 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET http://www.httpbin.org/status/500 via http://localhost:8050/execute> (failed 1 times): 500 Internal Server Error
2017-01-11 18:07:21 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://www.httpbin.org/status/404 via http://localhost:8050/execute> (referer: None)
2017-01-11 18:07:21 [errback_example] ERROR: <twisted.python.failure.Failure scrapy.spidermiddlewares.httperror.HttpError: Ignoring non-200 response>
2017-01-11 18:07:21 [errback_example] ERROR: HttpError on http://www.httpbin.org/status/404
2017-01-11 18:07:21 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET http://www.httpbin.org/status/500 via http://localhost:8050/execute> (failed 2 times): 500 Internal Server Error
2017-01-11 18:07:21 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.httpbin.org/ via http://localhost:8050/execute> (referer: None)
2017-01-11 18:07:21 [scrapy.downloadermiddlewares.retry] DEBUG: Gave up retrying <GET http://www.httpbin.org/status/500 via http://localhost:8050/execute> (failed 3 times): 500 Internal Server Error
2017-01-11 18:07:21 [scrapy.core.engine] DEBUG: Crawled (500) <GET http://www.httpbin.org/status/500 via http://localhost:8050/execute> (referer: None)
2017-01-11 18:07:21 [errback_example] INFO: Got successful response from http://www.httpbin.org/
2017-01-11 18:07:21 [errback_example] ERROR: <twisted.python.failure.Failure scrapy.spidermiddlewares.httperror.HttpError: Ignoring non-200 response>
2017-01-11 18:07:21 [errback_example] ERROR: HttpError on http://www.httpbin.org/status/500
2017-01-11 18:07:21 [scrapy.core.engine] INFO: Closing spider (finished)
2017-01-11 18:07:21 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 5365,
 'downloader/request_count': 5,
 'downloader/request_method_count/POST': 5,
 'downloader/response_bytes': 17332,
 'downloader/response_count': 5,
 'downloader/response_status_count/200': 1,
 'downloader/response_status_count/400': 4,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2017, 1, 11, 17, 7, 21, 715440),
 'log_count/DEBUG': 7,
 'log_count/ERROR': 4,
 'log_count/INFO': 8,
 'response_received_count': 3,
 'scheduler/dequeued': 8,
 'scheduler/dequeued/memory': 8,
 'scheduler/enqueued': 8,
 'scheduler/enqueued/memory': 8,
 'splash/execute/request_count': 3,
 'splash/execute/response_count/200': 1,
 'splash/execute/response_count/400': 4,
 'start_time': datetime.datetime(2017, 1, 11, 17, 7, 20, 683232)}
2017-01-11 18:07:21 [scrapy.core.engine] INFO: Spider closed (finished)

这些[errback_example] ERROR行显示了调用 errback 的时间,即在这里您通过 errback 方法获得 404 和 500。

于 2017-01-11T17:13:59.627 回答