リクエストとレスポンス¶
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 (
Responseobject) -- フォームフィールドに事前入力するために使用される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 (
Requestobject) --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参照。