/execute
「魔法の応答」(デフォルトでオンになっている)と組み合わせた応答でのみこれを達成できるようです:
meta['splash']['magic_response']
- True に設定され、JSON 応答が Splash から受信された場合、JSON で返されたデータを使用して、応答のいくつかの属性 (ヘッダー、本文、URL、ステータス コード) が入力されます。
- response.headers は '
headers
' キーから入力されます。
- response.url は '
url
' キーの値に設定されます。
- response.body は、'
html
' キーの値、または base64 でデコードされた 'body' キーの値に設定されます。
- response.status は '
http_status
' キーの値に設定されます。(...)
True
を使用する場合、このオプションはデフォルトで に設定されますSplashRequest
。
その他のエンドポイントは、リモート サーバーからの 4xx/render.html
および/render.json
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、ヘッダー、http_status、html、および Cookie を返す最後のテーブルに注目してください。)
... このスクリプトを と errbacks で使用すると/execute
、Scrapy docs から errbackSplashRequest
の例を再現できます:
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 が呼び出されたときを示しています。つまり、ここでは、404 と 500 が errback メソッドを通過しています。