Scrapyシェル

Scrapyシェルは、スパイダーを実行することなく、非常に迅速にスクレイピングコードを試行およびデバッグできる対話型シェルです。これは、データ抽出コードのテストに使用することを目的としていますが、通常のPythonシェルでもあるため、実際にはあらゆる種類のコードのテストに使用できます。

シェルは、XPath式またはCSS式をテストし、それらがどのように機能するか、およびスクレイピングしようとしているWebページからどのようなデータを抽出するかを確認するために使用されます。すべての変更をテストするためにスパイダーを実行する必要なく、スパイダーを作成している間に式をインタラクティブにテストできます。

Scrapyシェルに親しむと、スパイダーを開発およびデバッグするための非常に素晴らしいツールであることがわかります。

シェルの構成(configure)

IPython がインストールされている場合、Scrapyシェルは(標準のPythonコンソールの代わりに)それを使用します。 IPython コンソールははるかに強力で、とりわけスマートなオートコンプリートとカラー化された出力を提供します。

特に、( IPython が優れている)Unixシステムで作業している場合は、 IPython をインストールすることを強くお勧めします。 詳細については、 IPython installation guide を参照してください。

Scrapyは bpython もサポートしており、 IPython が利用できない場合はそれを使用しようとします。

Scrapyの設定により、インストールされているかどうかに関係なく、 ipython または bpython または、標準の python シェルのいずれかを使用するように設定できます。 これには SCRAPY_PYTHON_SHELL 環境変数を設定するか、または scrapy.cfg で定義することにより行います。

[settings]
shell = bpython

シェルを起動する

Scrapyシェルを起動するには、次のように shell コマンドを使用します:

scrapy shell <url>

<url> は、あなたがスクレイプしたいURLです。

shell はローカルファイルでも機能します。 これは、Webページのローカルコピーで遊んでみたい場合に便利です。 shell はローカルファイルの次の構文を理解します:

# UNIX-style
scrapy shell ./path/to/file.html
scrapy shell ../other/path/to/file.html
scrapy shell /absolute/path/to/file.html

# File URI
scrapy shell file:///absolute/path/to/file.html

注釈

相対ファイルパスを使用する場合は、明示的に指定し、 ./ (または関連する場合は ../ )を先頭に追加します。 scrapy shell index.html はあなたの予想どおりに機能しません(これは設計によるものであり、バグではありません)。

なぜなら、 shell はファイルURIよりもHTTP URLを優先し、 index.html は構文的に example.com に似ているため、 shellindex.html をドメイン名とみなしてDNSルックアップし、エラーをトリガします:

$ scrapy shell index.html
[ ... scrapy shell starts ... ]
[ ... traceback ... ]
twisted.internet.error.DNSLookupError: DNS lookup failed:
address 'index.html' not found: [Errno -5] No address associated with hostname.

shellindex.html というファイルが現在のディレクトリに存在するかどうかを事前にテストしません。繰り返しますが、明示的に指定してください。

シェルの使用

Scrapyシェルは、全くもってPythonコンソール(または、使用可能な場合は IPython コンソール)です。そして、便利な追加のショートカット機能を提供します。

利用可能なショートカット

  • shelp() - 利用可能なオブジェクトとショートカットのリストを含むヘルプを出力します

  • fetch(url[, redirect=True]) - 指定されたURLから新しいリクエストを取得し、それに応じてすべての関連オブジェクトを更新します。 HTTP 3xxリダイレクトの後に redirect=False を渡さないようにオプションで要求できます

  • fetch(request) - 特定のリクエストから新しいレスポンスを取得し、それに応じてすべての関連オブジェクトを更新します。

  • view(response) - 検査のために、指定されたレスポンスをローカルWebブラウザーで開きます。 これにより、外部リンク(画像やスタイルシートなど)が正しく表示されるように、 <base> tag がレスポンス・ボディに追加されます。 ただし、これによりコンピューターに一時ファイルが作成され、自動的には削除されないことに注意してください。

利用可能なScrapyオブジェクト

Scrapyシェルは、ダウンロードしたページから、 Response オブジェクトや、(HTMLコンテンツとXMLコンテンツの両方のために) Selector オブジェクトなどの便利なオブジェクトを自動的に作成します。

それらのオブジェクトは次のとおりです:

  • crawler - 現在の Crawler オブジェクト。

  • spider - URLを処理することが知られているスパイダー、または現在のURL用にスパイダーが見つからない場合は Spider オブジェクト

  • request - 最後に取得したページの Request オブジェクト。 replace() を使用してこのリクエストを変更するか、 fetch ショートカットを使用して、(シェルを離れずに)新しいリクエストを取得できます。

  • response - 最後に取得したページを含む Response オブジェクト

  • settings - 現在の Scrapy設定

シェル セッション の例

ここで、 https://scrapy.org ページをスクレイピングすることから始めて、 次に、 https://reddit.com ページのスクレイピングに進む、典型的なシェルセッションの例を以下に示します。 そして最後に、(Reddit)リクエストメソッドをPOSTに変更し、エラーを取得して再フェッチします。セッションを終了するには、Ctrl-D(Unixシステムの場合)、WindowsではCtrl-Zを入力します。

これらのページは静的ではなく、テストするまでに変更されている可能性があるため、ここで抽出したデータは同じではない可能性があることに注意してください。 この例の唯一の目的は、Scrapyシェルの仕組みを理解してもらうことです。

まず、私たちはシェルを起動します:

scrapy shell 'https://scrapy.org' --nolog

次に、シェルは(Scrapyダウンローダーを使用して)URLを取得し、使用可能なオブジェクトと便利なショートカットのリストを出力します(これらの行はすべて [s] 接頭辞で始まることがわかります):

[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x7f07395dd690>
[s]   item       {}
[s]   request    <GET https://scrapy.org>
[s]   response   <200 https://scrapy.org/>
[s]   settings   <scrapy.settings.Settings object at 0x7f07395dd710>
[s]   spider     <DefaultSpider 'default' at 0x7f0735891690>
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser

>>>

その後、オブジェクトで遊んでみましょう:

>>> response.xpath('//title/text()').get()
'Scrapy | A Fast and Powerful Scraping and Web Crawling Framework'

>>> fetch("https://reddit.com")

>>> response.xpath('//title/text()').get()
'reddit: the front page of the internet'

>>> request = request.replace(method="POST")

>>> fetch(request)

>>> response.status
404

>>> from pprint import pprint

>>> pprint(response.headers)
{'Accept-Ranges': ['bytes'],
 'Cache-Control': ['max-age=0, must-revalidate'],
 'Content-Type': ['text/html; charset=UTF-8'],
 'Date': ['Thu, 08 Dec 2016 16:21:19 GMT'],
 'Server': ['snooserv'],
 'Set-Cookie': ['loid=KqNLou0V9SKMX4qb4n; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 08-Dec-2018 16:21:19 GMT; secure',
                'loidcreated=2016-12-08T16%3A21%3A19.445Z; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 08-Dec-2018 16:21:19 GMT; secure',
                'loid=vi0ZVe4NkxNWdlH7r7; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 08-Dec-2018 16:21:19 GMT; secure',
                'loidcreated=2016-12-08T16%3A21%3A19.459Z; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 08-Dec-2018 16:21:19 GMT; secure'],
 'Vary': ['accept-encoding'],
 'Via': ['1.1 varnish'],
 'X-Cache': ['MISS'],
 'X-Cache-Hits': ['0'],
 'X-Content-Type-Options': ['nosniff'],
 'X-Frame-Options': ['SAMEORIGIN'],
 'X-Moose': ['majestic'],
 'X-Served-By': ['cache-cdg8730-CDG'],
 'X-Timer': ['S1481214079.394283,VS0,VE159'],
 'X-Ua-Compatible': ['IE=edge'],
 'X-Xss-Protection': ['1; mode=block']}
>>>

スパイダーからシェルを呼び出してレスポンスを検査する

あなたが期待するレスポンスがそこに到達していることを確認するためだけに、スパイダーの特定のポイントで処理されているレスポンスを検査したい場合があります。

これは scrapy.shell.inspect_response 関数を使用することで実現できます。

スパイダーから呼び出す方法の例を次に示します:

import scrapy


class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = [
        "http://example.com",
        "http://example.org",
        "http://example.net",
    ]

    def parse(self, response):
        # We want to inspect one specific response.
        if ".org" in response.url:
            from scrapy.shell import inspect_response
            inspect_response(response, self)

        # Rest of parsing code.

スパイダーを実行すると、次のようなものが得られます:

2014-01-23 17:48:31-0400 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://example.com> (referer: None)
2014-01-23 17:48:31-0400 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://example.org> (referer: None)
[s] Available Scrapy objects:
[s]   crawler    <scrapy.crawler.Crawler object at 0x1e16b50>
...

>>> response.url
'http://example.org'

そこから、抽出コードが機能しているかどうかを確認できます:

>>> response.xpath('//h1[@class="fn"]')
[]

Orz。期待したとおりではありません。 したがって、あなたはWebブラウザーでレスポンスを開き、それが期待したレスポンスかどうかを確認できます:

>>> view(response)
True

最後に、Ctrl-D(WindowsではCtrl-Z)を押してシェルを終了し、クロールを再開します:

>>> ^D
2014-01-23 17:50:03-0400 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://example.net> (referer: None)
...

Scrapyエンジンはシェルによってブロックされているため、ここでは fetch ショートカットを使用できないことに注意してください。 ただし、上記のように、シェルを離れた後、スパイダーは停止した場所からクロールを続けます。