F.A.Q.(よくある質問と回答)

ScrapyはBeautifulSoupやlxmlと比較してどうですか?

BeautifulSouplxml は、HTMLとXMLを解析するためのライブラリです。 Scrapyは、Webサイトをクロールし、そこからデータを抽出するWebスパイダーを作成するためのアプリケーションフレームワークです。

Scrapyはデータを抽出するための組み込みメカニズムを提供します( セレクター とよばれます)が、より快適に作業できる場合は、代わりに BeautifulSoup (または lxml )を簡単に使用できます。結局のところ、それらは任意のPythonコードからインポートして使用できるライブラリを利用しているだけです。

いいかえると、 BeautifulSoup (または lxml )とScrapyを比較することは、 jinja2Django を比較するようなものです。

ScrapyでBeautifulSoupを使用できますか?

はい、できます。 上記 のように、 BeautifulSoup はScrapyコールバックでHTMLレスポンスをパースするために使用できます。 レスポンスのボディを BeautifulSoup オブジェクトに送り、必要なデータを抽出するだけです。

HTMLパーサーとして lxml を使用して、BeautifulSoup API を使用するスパイダーの例を次に示します:

from bs4 import BeautifulSoup
import scrapy


class ExampleSpider(scrapy.Spider):
    name = "example"
    allowed_domains = ["example.com"]
    start_urls = (
        'http://www.example.com/',
    )

    def parse(self, response):
        # use lxml to get decent HTML parsing speed
        soup = BeautifulSoup(response.text, 'lxml')
        yield {
            "url": response.url,
            "title": soup.h1.string
        }

注釈

BeautifulSoup はいくつかのHTML/XMLパーサーをサポートしています。利用可能なものについてはBeautifulSoupの公式ドキュメント(BeautifulSoup's official documentation) を参照してください。

ScrapyはどのPythonバージョンをサポートしていますか?

ScrapyはCPython(デフォルトのPython実装)での Python 2.7 および Python 3.5+ と、PyPy(PyPy 5.9以降) でサポートされています。Python 2.6のサポートはScrapy 0.20以降は削除されました。Python 3のサポートはScrapy 1.1で追加されました。 PyPyサポートはScrapy 1.4で追加され、PyPy3サポートはScrapy 1.5で追加されました。

注釈

WindowsでPython 3をサポートするには、 インストールガイドで概説 しているように、Anaconda/Miniconda を使用することをお勧めします。

ScrapyはDjangoからhogehogeを盗んだ?

たぶん。だけど、私たちはそういう言い方はしないな。 Django は素晴らしいオープンソースプロジェクトであり、従うべき例であると考えているため、Scrapyの着想を得るのに利用したんだよ。

車輪の再発明する必要はないという信念です。この信念は、オープンソースおよびフリーソフトウェアの基礎の1つであることに加えて、ソフトウェアだけでなく、ドキュメント、手順、ポリシーなどにも適用されます。したがって、各問題を自分で進めるのではなく、それらのプロジェクトからアイデアをコピーすることを選択します それが既に各問題を適切に解決しているので、私たちは解決する必要がある実際の問題に焦点を当てる事ができます。

私たちはScrapyが他のプロジェクトのインスピレーションとして役立つことを誇りに思います。 じゃんじゃん盗め!

ScrapyはHTTPプロキシ経由で動作しますか?

はい。 HTTPプロキシのサポートは、HTTPプロキシ・ダウンローダー・ミドルウェアを通じて提供されます(Scrapy 0.8以降)。 HttpProxyMiddleware を参照してください。

異なるページの属性を持つアイテムをスクレイピングするにはどうすればよいですか?

追加のデータをコールバック関数に渡す 参照。

Scrapyがクラッシュします。「ImportError: No module named win32api」

あなたは「このツイストバグ」(this Twisted bug)のため、 pywin32 をインストールする必要があります。

スパイダーでユーザーログインをシミュレートするにはどうすればよいですか?

FormRequest.from_response() を使用してユーザーログインをシミュレートする 参照。

Scrapyは幅(breadth)優先または深さ(depth)優先でクロールしますか?

デフォルトでは、Scrapyは保留中のリクエストを保存するために LIFO キューを使用します。これは基本的に、DFO順序(DFO order)でクロールすることを意味します。 ほとんどの場合、この順序の方が便利です。

あなたが本当にBFO順(BFO order)でクロールしたい場合は、次の設定を行うことで実行できます:

DEPTH_PRIORITY = 1
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue'

保留中のリクエストが CONCURRENT_REQUESTS または CONCURRENT_REQUESTS_PER_DOMAIN または CONCURRENT_REQUESTS_PER_DOMAIN の設定値を下回っている間、これらのリクエストは同時に送信されます。その結果、クロールの最初のいくつかのリクエストが目的の順序に従うことはほとんどありません。 これらの設定を 1 に下げると、目的の順序が強制されますが、クロール全体が大幅に遅くなります。

Scrapyクローラーにメモリリークがあります。 何か私にできる事がありますか?

メモリ・リークのデバッグ 参照。

また、Pythonには Scrapyではリークしてないのにリークしてるorz で説明されている組み込みのメモリリークの問題があります。

Scrapyが消費するメモリを減らすにはどうすればよいですか?

1つ前の質問を見て下さい。

スパイダーは基本HTTP認証を使用できますか?

はい。 HttpAuthMiddleware 参照。

Scrapyが母国語ではなく英語でページをダウンロードするのはなぜですか?

DEFAULT_REQUEST_HEADERS 設定をオーバーライドして、デフォルトの Accept-Language リクエスト・ヘッダーを変更してみてください。

Scrapyプロジェクトの例はどこにありますか?

参照。

プロジェクトを作成せずにスパイダーを実行できますか?

はい。 runspider コマンドを使用できます。たとえば、 my_spider.py ファイルにスパイダーが記述されている場合は、次のコマンドで実行できます:

scrapy runspider my_spider.py

詳細については runspider を参照してください。

"Filtered offsite request"(フィルターされたオフサイト要求)メッセージが表示されます。 どうすれば修正できますか?

これらのメッセージ(DEBUGレベルでログに記録される)は、必ずしも問題があることを意味するわけではないため、修正する必要はありません。

これらのメッセージは、オフサイト・スパイダー・ミドルウェアによって送出されます。オフサイト・スパイダー・ミドルウェアは、スパイダーの対象外のドメインへのリクエストをフィルター処理することを目的とするスパイダー・ミドルウェア(デフォルトで有効)です。

詳細は OffsiteMiddleware を参照して下さい。

大規模なエクスポートにJSONを使用できますか?

出力の大きさに依存します。 JsonItemExporter 文書の 警告 を参照してください。

シグナルハンドラーから(Twisted)遅延(deferred)を返すことができますか?

ハンドラーからの遅延(deferred)を返すことをサポートするシグナルもあれば、サポートしないシグナルもあります。 組み込みシグナル・リファレンス を参照して、どれがどれか確認してください。

レスポンス・ステータス・コード999の意味は何ですか?

999は、リクエストを抑制するためにYahooサイトで使用されるカスタム・レスポンス・ステータス・コードです。スパイダーで 2 (またはそれ以上)のダウンロード遅延を使用して、クロール速度を遅くしてみてください:

class MySpider(CrawlSpider):

    name = 'myspider'

    download_delay = 2

    # [ ... rest of the spider code ... ]

または、 DOWNLOAD_DELAY 設定でプロジェクトのグローバル・ダウンロード遅延を設定します。

スパイダーから pdb.set_trace() を呼び出してデバッグできますか?

はい。ただし、スパイダーによって処理されているレスポンスをすばやく分析(および変更)できるScrapyシェルを使用することもできます。これは、通常の pdb.set_trace() よりも非常に便利です。

詳細は スパイダーからシェルを呼び出してレスポンスを検査する を参照して下さい。

スクレイピングしたすべてのアイテムをJSON/CSV/XMLファイルにダンプする最も簡単な方法は?

JSONファイルにダンプするには:

scrapy crawl myspider -o items.json

CSVファイルにダンプするには:

scrapy crawl myspider -o items.csv

XMLファイルにダンプするには:

scrapy crawl myspider -o items.xml

詳細は フィード・エクスポート を参照して下さい。

いくつかのフォームで使用されているこの巨大な __VIEWSTATE パラメーターは何ですか?

__VIEWSTATE パラメーターは、ASP.NET/VB.NETで構築されたサイトで使用されます。動作の詳細については、http://search.cpan.org/~ecarroll/HTML-TreeBuilderX-ASP_NET-0.09/lib/HTML/TreeBuilderX/ASP_NET.pm を参照してください。また、これらのサイトの1つをスクレイピングする example spider もあります。

大きなXML/CSVデータ・フィードを解析する最良の方法は何ですか?

XPathセレクターを使用して大きなフィードを解析すると、フィード全体のDOMをメモリに構築する必要があるため問題が発生する可能性があります。これは非常に遅く、大量のメモリを消費する可能性があります。

メモリ内のフィード全体を一度に解析することを避けるために、 scrapy.utils.iterators モジュールの関数 xmlitercsviter を使用できます。 実際、これはフィード・スパイダー( スパイダー 参照)が内部で使用しているものです。

Scrapyはクッキーを自動的に管理しますか?

はい、Scrapyはサーバーから送信されたクッキーを受信して追跡し、通常のWebブラウザーが行うように、後続のリクエストでそれらを送り返します。

詳細は リクエストとレスポンスCookiesMiddleware を参照下さい。

Scrapyとの間で送受信されているCookieを確認するにはどうすればよいですか?

COOKIES_DEBUG 設定を有効にします。

スパイダーに自分自身を止めるように指示するにはどうすればよいですか?

コールバックから CloseSpider 例外を発生させます。 詳細については、 CloseSpider を参照してください。

Scrapyボットがバン(BAN)されるのを防ぐにはどうすればよいですか?

バン(拒否)されるのを避ける 参照。

スパイダーを設定するには、スパイダーの引数または設定を使用する必要がありますか?

スパイダー引数設定 の両方を使用して、スパイダーを設定できます。どちらか一方を使用することを義務付ける厳密なルールはありませんが、設定は一度設定するとあまり変化しないパラメーターに適しています。一方、スパイダーの引数はスパイダーの実行ごとに頻繁に変更されることを意図しており、スパイダーを実行するには(たとえば、スパイダーの開始URLを設定するためなど、)どうせ必要になります。

例で説明するために、データをスクレイピングするためにサイトにログインする必要があるスパイダーがあり、(毎回異なる)サイトの特定のセクションからのみデータをスクレイピングしたいとします。 その場合、ログインする資格情報は設定になり、スクレイピングするセクションのURLはスパイダー引数になります。

XMLドキュメントをスクレイピングしていますが、XPathセレクターはアイテムを返しません

名前空間を削除する必要がある場合があります。 名前空間(namespace)の削除 参照。

アイテム・パイプラインでアイテムを複数のアイテムに分割する方法は?

アイテム・パイプライン は、入力アイテムごとに複数のアイテムを生成できません。 代わりに スパイダー・ミドルウェア を作成し、この目的で process_spider_output() メソッドを使用します。例えば以下です:

from copy import deepcopy

from scrapy.item import BaseItem


class MultiplyItemsMiddleware:

    def process_spider_output(self, response, result, spider):
        for item in result:
            if isinstance(item, (BaseItem, dict)):
                for _ in range(item['multiply_by']):
                    yield deepcopy(item)