リクエストとレスポンス¶
Scrapyは、Webサイトのクロールに Request
と Response
オブジェクトを使用します。
通常、 Request
オブジェクトはスパイダーで生成され、ダウンローダーに到達するまでシステム内をあちこち旅行(pass across)します。ダウンローダーはリクエストを実行し、リクエストを発行したスパイダーに Response
オブジェクトを返します。
Request
クラスと Response
クラスの両方には、基本クラスでは必要のない機能を追加するサブクラスがあります。これらについては、 Requestのサブクラス と Responseのサブクラス で説明しています。
Requestオブジェクト¶
-
class
scrapy.http.
Request
(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback, flags, cb_kwargs])¶ Request
オブジェクトはHTTPリクエストを表します。これは通常スパイダーで生成され、ダウンローダーによって実行され、そして、Response
が生成されます。- パラメータ
url (string) -- このリクエストのURL
callback (callable) -- 最初のパラメーターとしてこのリクエストのレスポンス(ダウンロード後)に呼び出される関数。詳細については、以下の 追加のデータをコールバック関数に渡す を参照してください。リクエストでコールバックが指定されていない場合、スパイダーの
parse()
メソッドが使用されます。 処理中に例外が発生した場合、代わりにエラーバック(errback)が呼び出されることに注意してください。method (string) -- このリクエストのHTTPメソッド。デフォルトは
'GET'
です。meta (dict) --
Request.meta
属性の初期値。指定すると、このパラメーターに渡された辞書は浅いコピー(shallow copy)されます。body (str or unicode) -- リクエスト・ボディ。
unicode
が渡されると、渡されたencoding
(デフォルトはutf-8
)を使用してstr
にエンコードされます。body
が与えられない場合、空の文字列が保存されます。この引数のタイプに関係なく、保存される最終的な値はstr
(決してunicode
やNone
ではありません)。headers (dict) -- このリクエストのヘッダー。 辞書値は、文字列(単一値のヘッダーの場合)またはリスト(複数値のヘッダーの場合)です。 値として
None
が渡された場合、HTTPヘッダーはまったく送信されません。リクエスト・クッキー。これらは2つの形式で送信できます。
辞書の使用:
request_with_cookies = Request(url="http://www.example.com", cookies={'currency': 'USD', 'country': 'UY'})
辞書のリストの使用:
request_with_cookies = Request(url="http://www.example.com", cookies=[{'name': 'currency', 'value': 'USD', 'domain': 'example.com', 'path': '/currency'}])
後者の形式では、クッキーの
domain
およびpath
属性をカスタマイズできます。これは、クッキーが後のリクエストのために保存される場合にのみ役立ちます。一部のサイトが(レスポンスで)クッキーを返すと、それらはそのドメインのクッキーに保存され、今後のリクエストで再度送信されます。これは通常のWebブラウザの一般的な動作です。けれども、何らかの理由で既存のクッキーとのマージを避けたい場合は、
Request.meta
でdont_merge_cookies
キーをTrueに設定することで、Scrapyにそうするよう指示できます。クッキーをマージしないリクエストの例:
request_with_cookies = Request(url="http://www.example.com", cookies={'currency': 'USD', 'country': 'UY'}, meta={'dont_merge_cookies': True})
詳細については、 CookiesMiddleware を参照してください。
encoding (string) -- このリクエストのエンコーディング(デフォルトは
'utf-8'
)。このエンコードは、URLをパーセントエンコードし、本文をstr
に変換するために使用されます(unicode
として指定された場合)。priority (int) -- このリクエストの優先度(デフォルトは
0
)。スケジューラーは優先度を使用して、リクエストの処理に使用される順序を定義します。より高い優先度値を持つリクエストは、より早く実行されます。比較的低い優先度を示すために、負の値が許可されています。dont_filter (boolean) -- このリクエストは、スケジューラによってフィルタリングされるべきではないことを示します。 これは、重複フィルターを無視するために、同じリクエストを複数回実行する場合に使用されます。注意して使用しないと、クロールループに陥ります。デフォルトは
False
です。errback (callable) -- リクエストの処理中に例外が発生した場合に呼び出される関数。これには、404 HTTPエラーなどで失敗したページが含まれます。最初のパラメーターとして Twisted Failure インスタンスを受け取ります。 詳細については、以下の リクエスト処理で例外をキャッチするためにエラーバック(errback)を使用する を参照してください。
flags (list) -- リクエストに送信されたフラグは、ロギングまたは同様の目的に使用できます。
cb_kwargs (dict) -- キーワード引数としてリクエストのコールバックに渡される任意のデータを含む辞書。
-
url
¶ このリクエストのURLを含む文字列。 この属性にはエスケープされたURLが含まれているため、コンストラクターで渡されるURLとは異なる場合があることに注意してください。
この属性は読み取り専用です。リクエストのURLを変更するには、
replace()
を使用します。
-
method
¶ リクエスト内のHTTPメソッドを表す文字列。 これは大文字であることが保証されています。 例:
"GET"
、"POST"
、"PUT"
など
-
headers
¶ リクエスト・ヘッダーを含む辞書のようなオブジェクト。
-
meta
¶ このリクエストの任意のメタデータを含む辞書。 この辞書は、新しいリクエストに対して空であり、通常、さまざまなScrapyコンポーネント(拡張機能、ミドルウェアなど)によって設定されます。したがって、この辞書に含まれるデータは、有効にした拡張機能によって異なります。
Scrapyによって認識される特殊なメタ・キーのリストについては、 Request.meta 特殊キー を参照してください。
この辞書は
copy()
またはreplace()
メソッドを使用してリクエストが複製されたときに浅いコピーされ(shallow copied)、スパイダーでresponse.meta
属性からアクセスすることもできます。
-
cb_kwargs
¶ このリクエストの任意のメタデータを含む辞書。その内容は、キーワード引数としてリクエストのコールバックに渡されます。新しいリクエストの場合は空です。つまり、デフォルトではコールバックは引数として
Response
オブジェクトのみを取得します。この辞書は、
copy()
またはreplace()
メソッドを使用してリクエストが複製されたときに浅いコピーされ(shallow copied)、スパイダーでresponse.cb_kwargs
属性からアクセスすることもできます。
-
copy
()¶ このリクエストのコピーである新しいリクエストを返します。 追加のデータをコールバック関数に渡す も参照してください。
-
replace
([url, method, headers, body, cookies, meta, flags, encoding, priority, dont_filter, callback, errback, cb_kwargs])¶ 指定されたキーワード引数によって新しい値が指定されたメンバーを除き、同じメンバーを持つリクエスト・オブジェクトを返します。
Request.cb_kwargs
およびRequest.meta
属性は(新しい値が引数として与えられない限り)デフォルトでは浅くコピー(shallow copy)されます。 追加のデータをコールバック関数に渡す も参照してください。
追加のデータをコールバック関数に渡す¶
リクエストのコールバックは、そのリクエストのレスポンスがダウンロードされるときに呼び出される関数です。コールバック関数は、ダウンロードされた Response
オブジェクトを最初の引数として呼び出されます。
例:
def parse_page1(self, response):
return scrapy.Request("http://www.example.com/some_page.html",
callback=self.parse_page2)
def parse_page2(self, response):
# this would log http://www.example.com/some_page.html
self.logger.info("Visited %s", response.url)
場合によっては、後で2番目のコールバックで引数を受け取ることができるように、これらのコールバック関数に引数を渡すことに興味があるかもしれません。 次の例は、 Request.cb_kwargs
属性を使用してこれを実現する方法を示しています:
def parse(self, response):
request = scrapy.Request('http://www.example.com/index.html',
callback=self.parse_page2,
cb_kwargs=dict(main_url=response.url))
request.cb_kwargs['foo'] = 'bar' # add more arguments for the callback
yield request
def parse_page2(self, response, main_url, foo):
yield dict(
main_url=main_url,
other_url=response.url,
foo=foo,
)
ご用心
Request.cb_kwargs
はバージョン 1.7
で導入されました。 それ以前は、コールバックに情報を渡すために Request.meta
を使用することが推奨されていました。1.7
以降では、 Request.cb_kwargs
がユーザー情報を処理するための好ましい方法となり、 Request.meta
は、ミドルウェアや拡張機能などのコンポーネントとの通信のために残されています。
リクエスト処理で例外をキャッチするためにエラーバック(errback)を使用する¶
リクエストのエラーバック(errback)は、処理中に例外が発生したときに呼び出される関数です。
最初のパラメーターとして Twisted Failure インスタンスを受け取り、接続確立タイムアウト、DNSエラーなどを追跡するために使用できます。
すべてのエラーをログに記録し、必要に応じて特定のエラーをキャッチするスパイダーの例を次に示します:
import scrapy
from scrapy.spidermiddlewares.httperror import HttpError
from twisted.internet.error import DNSLookupError
from twisted.internet.error import TimeoutError, TCPTimedOutError
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
"http://www.httpbin.org:12345/", # non-responding host, timeout expected
"http://www.httphttpbinbin.org/", # DNS error expected
]
def start_requests(self):
for u in self.start_urls:
yield scrapy.Request(u, callback=self.parse_httpbin,
errback=self.errback_httpbin,
dont_filter=True)
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)
Request.meta 特殊キー¶
Request.meta
属性には任意のデータを含めることができますが、Scrapyとその組み込み拡張機能によって認識される特殊なキーがあります。
以下がその特殊キーです:
ftp_user
(詳細はFTP_USER
参照)ftp_password
(詳細はFTP_PASSWORD
参照)
bindaddress¶
リクエストの実行に使用する発信IPアドレスのIP
download_timeout¶
ダウンローダーがタイムアウトするまで待機する時間(秒)。 DOWNLOAD_TIMEOUT
も参照してください。
download_latency¶
リクエストが開始されてから、つまりネットワークを介して送信されたHTTPメッセージから、レスポンスの取得に費やされた時間。 このメタ・キーは、レスポンスがダウンロードされた場合にのみ使用可能になります。他のほとんどのメタ・キーはScrapyの動作を制御するために使用されますが、これは読み取り専用であると想定されています。
download_fail_on_dataloss¶
壊れたレスポンスで失敗するかどうか。 DOWNLOAD_FAIL_ON_DATALOSS
を参照してください。
max_retry_times¶
メタ・キーを使用して、リクエストごとに再試行回数を設定します。初期化されると、 max_retry_times
メタ・キーは RETRY_TIMES
設定よりも優先されます。
Requestのサブクラス¶
以下は組み込みの Request
のサブクラスのリストです。また、サブクラス化して独自のカスタム機能を実装することもできます。
FormRequestオブジェクト¶
FormRequestクラスは、ベースの Request
をHTMLフォームを処理する機能に関して拡張します。 lxml.html forms を使用して、フォームフィールドに Response
オブジェクトからのフォームデータを事前入力します。
-
class
scrapy.http.
FormRequest
(url[, formdata, ...])¶ FormRequest
クラスはコンストラクターに新しい引数を追加します。残りの引数はRequest
クラスと同じであり、ここでは説明しません。- パラメータ
formdata (dict or iterable of tuples) -- これは、URLエンコードされてリクエストの本文に割り当てられるHTMLフォームデータを含む辞書(または (キー, 値)タプルの反復可能要素)です。
FormRequest
オブジェクトは、標準のRequest
メソッドに加えて、次のクラスメソッドをサポートします:-
classmethod
from_response
(response[, formname=None, formid=None, formnumber=0, formdata=None, formxpath=None, formcss=None, clickdata=None, dont_click=False, ...])¶ 指定のレスポンスに含まれるHTML
<form>
要素で見つかった値が事前に入力されたフォームフィールド値を持つ新しいFormRequest
オブジェクトを返します。例については、 FormRequest.from_response() を使用してユーザーログインをシミュレートする を参照してください。ポリシーは、デフォルトでは、
<input type="submit">
のようにクリック可能に見えるフォームコントロールのクリックを自動的にシミュレートすることです。 これは非常に便利で、多くの場合望ましい動作ですが、時にはデバッグが困難な問題を引き起こす可能性があります。 たとえば、javascriptを使用して、入力 and/or 送信されたフォームを操作する場合、デフォルトのfrom_response()
動作は最適ではない場合があります。この動作を無効にするには、dont_click
引数をTrue
に設定します。 また、(無効にするのではなく)クリックしたコントロールを変更したい場合は、clickdata
引数を使用することもできます。ご用心
オプション値に先頭または末尾の空白があるselect要素でこのメソッドを使用すると、lxml 3.8で修正されるべきlxmlのバグ(bug in lxml)のために機能しません。
- パラメータ
response (
Response
object) -- フォームフィールドに事前入力するために使用されるHTMLフォームを含むレスポンスformname (string) -- 指定した場合、name属性をこの値に設定したフォームが使用されます。
formid (string) -- 指定した場合、この値に設定されたid属性を持つフォームが使用されます。
formxpath (string) -- 指定すると、xpathに一致する最初のフォームが使用されます。
formcss (string) -- 指定した場合、cssセレクターに一致する最初のフォームが使用されます。
formnumber (integer) -- レスポンスに複数のフォームが含まれる場合に使用するフォームの数。 最初のもの(およびデフォルト)は
0
です。formdata (dict) -- フォームデータでオーバーライドするフィールド。レスポンス
<form>
要素にフィールドが既に存在する場合、その値はこのパラメーターで渡された値によってオーバーライドされます。このパラメーターに渡された値がNone
の場合、フィールドはレスポンス<form>
要素に存在していても、リクエストに含まれません。clickdata (dict) -- クリックされたコントロールを検索する属性。 指定されていない場合、最初のクリック可能な要素のクリックをシミュレートしてフォームデータが送信されます。 html属性に加えて、コントロールは
nr
属性を介して、フォーム内の他の送信可能な入力に対するゼロベースのインデックスによって識別できます。dont_click (boolean) -- Trueの場合、要素をクリックせずにフォームデータが送信されます。
このクラスメソッドの他のパラメーターは、
FormRequest
コンストラクターに直接渡されます。バージョン 0.10.3 で追加:
formname
パラメータ。バージョン 0.17 で追加:
formxpath
パラメータ。バージョン 1.1.0 で追加:
formcss
パラメータ。バージョン 1.1.0 で追加:
formid
パラメータ。
Request使用例¶
HTTP POST経由でデータを送信するためにFormRequestを使う¶
スパイダーでHTMLフォームPOSTをシミュレートし、いくつかのキー値フィールドを送信する場合、以下のように(スパイダーから) FormRequest
オブジェクトを返すことができます:
return [FormRequest(url="http://www.example.com/post/action",
formdata={'name': 'John Doe', 'age': '27'},
callback=self.after_post)]
FormRequest.from_response() を使用してユーザーログインをシミュレートする¶
Webサイトでは通常、セッション関連データや認証トークン(ログインページ用)などの <input type="hidden">
要素を介して事前入力されたフォームフィールドを提供します。 スクレイピングするとき、これらのフィールドは自動的に事前入力され、ユーザー名やパスワードなどのいくつかのフィールドのみがオーバーライド必須です。この作業には FormRequest.from_response()
メソッドを使用できます。以下はこれを使用するスパイダーの例です:
import scrapy
def authentication_failed(response):
# TODO: Check the contents of the response and return True if it failed
# or False if it succeeded.
pass
class LoginSpider(scrapy.Spider):
name = 'example.com'
start_urls = ['http://www.example.com/users/login.php']
def parse(self, response):
return scrapy.FormRequest.from_response(
response,
formdata={'username': 'john', 'password': 'secret'},
callback=self.after_login
)
def after_login(self, response):
if authentication_failed(response):
self.logger.error("Login failed")
return
# continue scraping with authenticated session...
JsonRequest¶
JsonRequestクラスは、ベースの Request
クラスにJSONリクエストを処理する機能をくわえます。
-
class
scrapy.http.
JsonRequest
(url[, ... data, dumps_kwargs])¶ JsonRequest
クラスは、コンストラクターに2つの新しい引数を追加します。残りの引数はRequest
クラスと同じであり、ここでは説明しません。JsonRequest
を使用すると、Content-Type
ヘッダーをapplication/json
にセットし、そして、Accept
ヘッダーをapplication/json, text/javascript, */*; q=0.01
にセットします。- パラメータ
data (JSON serializable object) -- JSONエンコードして本文に割り当てる必要があるJSONシリアル化可能オブジェクトです。
Request.body
引数が指定されている場合、このパラメーターは無視されます。Request.body
引数が提供されておらず、データ引数が提供されている場合、Request.method
は'POST'
に自動的に設定されます。dumps_kwargs (dict) -- データをJSON形式にシリアル化するために使用される、基礎となる json.dumps メソッドに渡されるパラメーター。
JsonRequest使用例¶
JSONペイロードを含むJSON POSTリクエストを送信する:
data = {
'name1': 'value1',
'name2': 'value2',
}
yield JsonRequest(url='http://www.example.com/post/action', data=data)
Responseオブジェクト¶
-
class
scrapy.http.
Response
(url[, status=200, headers=None, body=b'', flags=None, request=None])¶ Response
オブジェクトはHTTPレスポンスを表し、通常は(ダウンローダーによって)ダウンロードされ、処理のためにスパイダーに送られます。- パラメータ
url (string) -- このレスポンスのURL
status (integer) -- レスポンスのHTTPステータス。デフォルトは
200
です。headers (dict) -- このレスポンスのヘッダー。 辞書値は、文字列(単一値のヘッダーの場合)またはリスト(複数値のヘッダーの場合)です。
body (bytes) -- レスポンス・ボディ。 デコードされたテキストにstr(Python2ではユニコード)としてアクセスするには、エンコード対応(encoding-aware)である、
TextResponse
のような Responseのサブクラス のresponse.text
を使用できます。flags (list) --
Response.flags
属性の初期値を含むリストです。 指定すると、リストは浅くコピー(shallow copy)されます。request (
Request
object) --Response.request
属性の初期値。これは、このレスポンスを生成したRequest
を表します。
-
status
¶ レスポンスのHTTPステータスを表す整数。例:
200
、404
-
headers
¶ レスポンス・ヘッダーを含む辞書のようなオブジェクト。値にアクセスするには、
get()
を使用して指定した名前の最初のヘッダー値を返すか、getlist()
を使用して指定した名前のすべてのヘッダー値を返します。たとえば、以下のの呼び出しはヘッダーのすべてのクッキーを提供します:response.headers.getlist('Set-Cookie')
-
body
¶ このResponseのボディ。Response.bodyは常にバイト・オブジェクトであることに注意してください。Unicodeバージョンが必要な場合は、
TextResponse.text
を使用します(TextResponse
と、そのサブクラスでのみ使用可能)。この属性は読み取り専用です。 レスポンスのボディを変更するには、
replace()
を使用します。
-
request
¶ このレスポンスを生成した
Request
オブジェクト。この属性は、レスポンスとリクエストが、すべての ダウンローダー・ミドルウェア を通過した後、Scrapyエンジンで割り当てられます。 特に、これは以下を意味します:HTTPリダイレクトにより、元のリクエスト(リダイレクト前のURLへ)がリダイレクトされたレスポンス(リダイレクト後の最終URL)に割り当てられます。
Response.request.urlは必ずしもResponse.urlと同じではありません
この属性は、スパイダー・コード、および スパイダー・ミドルウェア でのみ使用できます。ただし、(他の方法でリクエストを使用できる場合の)ダウンローダー・ミドルウェアと
response_downloaded
シグナルのハンドラーには含まれません。
-
meta
¶ Response.request
オブジェクトのRequest.meta
属性(つまりself.request.meta
)へのショートカット。Response.request
属性とは異なり、Response.meta
属性はリダイレクトと再試行に沿って伝播されるため、元のRequest.meta
がスパイダーから送信されます。参考
Request.meta
属性
-
flags
¶ このレスポンスのフラグを含むリスト。フラグは、レスポンスのタグ付けに使用されるラベルです。 例:
'cached'
、'redirected
' など。これらは、エンジンがログ記録に使用するResponse ( __str__ メソッド)の文字列表現に表示されます。
-
copy
()¶ このレスポンスのコピーである新しいレスポンスを返します。
-
replace
([url, status, headers, body, request, flags, cls])¶ 指定されたキーワード引数によって新しい値が指定されたメンバーを除き、同じメンバーを持つレスポンスオブジェクトを返します。属性
Response.meta
はデフォルトでコピーされます。
-
urljoin
(url)¶ 指定の url (たぶん相対URL)と レスポンスの
url
(Response.url
) を組み合わせて、絶対URLを構築します。これは urlparse.urljoin のラッパーであり、以下の呼び出しを行うための単なるエイリアスです:
urlparse.urljoin(response.url, url)
Responseのサブクラス¶
使用可能な組み込みResponseのサブクラスのリストは以下のとおりです。 Responseクラスをサブクラス化して、独自の機能を実装することもできます。
TextResponseオブジェクト¶
-
class
scrapy.http.
TextResponse
(url[, encoding[, ...]])¶ TextResponse
オブジェクトは、エンコード機能を、ベースのResponse
クラスに追加します。これは、画像、音声、メディアファイルなどのバイナリデータにのみ使用することを目的としています。TextResponse
オブジェクトは、ベースのResponse
オブジェクトに加えて、新しいコンストラクター引数をサポートします。残りの機能はResponse
クラスと同じであり、ここでは説明しません。- パラメータ
encoding (string) -- このレスポンスに使用するエンコーディングを含む文字列です。 ユニコード・ボディで
TextResponse
オブジェクトを作成する場合、このエンコードを使用してエンコードされます(body属性は常に文字列であることに注意してください)。encoding
がNone
(デフォルト値)の場合、代わりにレスポンス・ヘッダーとボディからエンコードを検索します。
TextResponse
オブジェクトは、標準のResponse
に加えて、次の属性をサポートします:-
text
¶ ユニコードとしてのレスポンス・ボディ
response.body.decode(response.encoding)
と同じですが、最初の呼び出し後に結果がキャッシュされるため、余分なオーバーヘッドなしでresponse.text
に複数回アクセスできます。注釈
unicode(response.body)
はレスポンス・ボディをユニコードに変換する正しい方法ではありません。レスポンス・エンコーディングの代わりにシステムのデフォルト・エンコーディング(通常はascii
)を使用することになります。
-
encoding
¶ このレスポンスのエンコードを含む文字列。 エンコードは、次のメカニズムを順番に試して解決されます:
コンストラクタ
encoding
引数に渡されたエンコーディングContent-Type HTTPヘッダーで宣言されたエンコーディング。 このエンコードが有効でない(つまり不明の)場合、無視され、次の解決メカニズムが試行されます。
レスポンス・ボディで宣言されたエンコーディング。 TextResponseクラスは、このための特別な機能を提供しません。 ただし、
HtmlResponse
とXmlResponse
クラスはサポートします。レスポンス・ボディを見て推測するエンコーディング。 これはより壊れやすい方法ですが、最後に試す方法でもあります。
-
selector
¶ レスポンスをターゲットとして使用する
Selector
インスタンス。セレクターは最初のアクセスで遅延的(lazily)にインスタンス化されます。
TextResponse
オブジェクトは標準のResponse
に加えて以下のメソッドをサポートします:-
xpath
(query)¶ TextResponse.selector.xpath(query)
へのショートカット:response.xpath('//p')
-
css
(query)¶ TextResponse.selector.css(query)
へのショートカット:response.css('p')
HtmlResponseオブジェクト¶
-
class
scrapy.http.
HtmlResponse
(url[, ...])¶ HtmlResponse
クラスはTextResponse
のサブクラスで、HTMLの meta http-equiv 属性を調べることでエンコーディングの自動検出サポートを追加します。TextResponse.encoding
参照。
XmlResponseオブジェクト¶
-
class
scrapy.http.
XmlResponse
(url[, ...])¶ XmlResponse
クラスはTextResponse
のサブクラスで、XML宣言行を調べることでエンコーディングの自動検出サポートを追加します。TextResponse.encoding
参照。