Scrapyチュートリアル
17187 ワード
Scrapyをインストールしたとしますが、インストールガイドを参照してください.
捕まえるぞtoscrape.comサイト.
このチュートリアルでは、次のタスクを実行します.新規Scrapyエンジニアリング spiderサイト抽出データ を作成コマンド・ラインでフェッチするデータ を導出する. spider再帰爬行リンク を変更する spiderパラメータ を使用
プロジェクトの作成
キャプチャする前に、Scrapyプロジェクトを構築します:
最初の爬虫類
Spiderは、Webサイト情報を取得するクラスとして定義されています.
これは私たちの最初のSpiderのコードで、
以上のようにspiderはscrapyから継承する.Spiderはいくつかの属性と方法を定義した.
クモをどう動かすか
プロジェクトの最上位ディレクトリで実行:
このコマンドは、私たちが追加した
現在のディレクトリを確認します.2つの新しいファイルquotes-1が作成されたことに気づきます.htmlとquotes-2.htmlにはurlsの応答データが含まれています.
内部メカニズムとは
Scrapyはクモの
start_requests関数の概要
urlsのリクエストのたびに
データの抽出
最も良い学習はScrapyのセレクタを使う方法はScrapy shellを使うことです.
ヒント
単一引用符でアドレスをラップすることを忘れないでください.そうしないと、&文字などのパラメータが含まれています.
Windowsで二重引用符を使う
次のようになります.
shellではresponseオブジェクトのCSS関数を使用して要素を選択できます.
titleのテキストをエクスポートするには、次のようにします.
ここで注意しなければならない点は2つあります.1つは、
二、
pythonのリスト書き方も使用できます.
しかし、
適切なCSSセレクタを見つけるには、shellからview(response)を使用して応答インタフェースを参照します.Firebugなどのブラウザ開発ツールやプラグインを使用できます(ここではFirebugを使用してキャプチャし、FireFoxを使用してキャプチャするを参照してください).
セレクタウィジェットもCSSセレクタを検索するのに良いツールで、要素を可視化することができ、多くのブラウザで作業することができます.
XPATH:概要
cssに加えて、ScrapyセレクタもXPath式をサポートします.
XPATH式は強力で、Scrapyセレクタの基礎です.実際、CSSセレクタは内部でXpathに変換されます.shellでテキストセレクタのオブジェクトタイプを表示できます.
CSSセレクタほど流行していないにもかかわらず、Xpath式はもっと強い.構造にナビゲートするだけでなく、コンテンツを検索することもできます.xpathを使用すると、次のように選択できます.Next Pageを含むテキスト接続を選択します.これにより、xpathはキャプチャに非常に適しており、CSSセレクタをどのように構築するかを知っていても、Xpathを学ぶことを奨励します.
私たちはここでXPathにあまり触れません.XPathを読むことができます.Xpathを学ぶために、例を通してXPathチュートリアルを学ぶことと、XPathを使って考える方法をお勧めします.
quotesとauthorsの抽出
選択と抽出に関する知識を少し知っています.私たちのspiderを改善し、コードを書いてウェブサイトのページからquotesを抽出しましょう.
http://quotes.toscrape.comの各quoteのHTML形式は次のようになります.
scrapy shellを開いて、私たちが望んでいるデータを抽出しようとします.
次の構文を使用して、一連のquote要素のセレクタを得ます.
各セレクタは、サブ要素をクエリーできます.最初のセレクタを変数に割り当て、指定したquoteセレクタを直接実行できます.
次に、quoteから
ラベルが文字列リストであることを考慮すると、
各エクスポート方法を解決し、すべてのquotes要素を反復してPython辞書に保存できます.
spiderを使用してデータをエクスポートする
spiderに戻りましょう.今でもデータはエクスポートされず、HTMLページをローカルファイルに保存するだけです.導出ロジックをspiderに統合した.
1つのScrapyクモには、通常、複数のページでデータをキャプチャする辞書が含まれます.これにより、コールバック関数で
このクモを実行すると、エクスポートデータがログに出力されます.
取得したデータの保存
最も簡単なキャプチャデータの保存はFeed exportsを使用し、次のコマンドラインを使用します.
これによりquotesが生成されますjsonファイルには、すべてのキャプチャイメージがjsonにシーケンス化されています.
履歴上の理由で、Scrapyは上書きではなく追加を使用します.このコマンドを2回実行して2回目の削除前のファイルがなければ、破損したJSONファイルが得られます.
Json Linesのような他のフォーマットも使用できます
Json Linesフォーマットはstream-likeなので役に立ちます.新しい記録を簡単に追加することができます.彼は上のJSONファイルの問題を持っていません.あなたが2回実行したとき.また、各レコードは1行なので、メモリの問題を心配することなく、大きなファイルを処理できます.JQのようなツールはコマンドラインで処理できます.
小さなプロジェクト(例のようにチュートリアル)では、これで十分です.しかし、より複雑なキャプチャ項目を処理したい場合は、[Itemパイプ]を作成することができます.プロジェクトが作成されると、
次の接続
捕まえたいだけじゃなくhttp://quotes.toscrape.comサイトの中の2つのページではなく、すべてのサイトのページをキャプチャしたいと思っています.
ページからデータをキャプチャする方法を知っています.次の接続を見てみましょう.
まずページから目的の接続を抽出します.ページを表示すると、次のページに次のフラグが接続されています.
shellから抽出してみます.
これはanchor要素全体を得たが、
次のページを追跡してデータをエクスポートできるようにspiderが変更されました.
次に、データをエクスポートした後、
これはScrapyがページを追跡するメカニズムです.コールバックで要求オブジェクトを生成すると、要求の送信とコールバック関数の登録が要求の終了時に実行されます.
これらを使用すると、複雑な爬虫類システムを構築したり、リンクルールをカスタマイズしたり、アクセスページに基づいてさまざまなデータをエクスポートしたりすることができます.
私たちの例では、ブログ、フォーラム、または他のナビゲーションサイトを簡単にアクセスできるように、すべてのリンクを次のページに追跡する一連のループを作成します.
その他の例とモード
これは別のクモがコールバックと追跡接続を説明するために使用され、今回は著者の情報をキャプチャします.
クモはホームページから始まり、
もう一つのクモに関する興味深いことは、同じ著者から多くの名言が出ても、同じ著者のページに何度もアクセスする心配はありません.デフォルトでは、Scrapyは重複したアクセス済みリクエストアドレスをフィルタリングし、プログラムがサーバをクリックしすぎる問題を回避します.これはDUPEFILTERでCLASS構成.
Scrapyがページとコールバックを追跡するメカニズムを理解してほしい.
このプログラムは追跡リンクメカニズムを利用して実現され、CrawlSpiderクラスを表示します.それは共通のクモで小さなルールエンジンを実現し、それ以上に自分の爬虫類を書くことができます.
https://doc.scrapy.org/en/latest/intro/tutorial.html
捕まえるぞtoscrape.comサイト.
このチュートリアルでは、次のタスクを実行します.
プロジェクトの作成
キャプチャする前に、Scrapyプロジェクトを構築します:
scrapy startproject tutorial
このコマンドは、次のtutorial
ディレクトリを作成します.tutorial/
scrapy.cfg # deploy configuration file
tutorial/ # project's Python module, you'll import your code from here
__init__.py
items.py # project items definition file
pipelines.py # project pipelines file
settings.py # project settings file
spiders/ # a directory where you'll later put your spiders
__init__.py
最初の爬虫類
Spiderは、Webサイト情報を取得するクラスとして定義されています.
scrapy.Spider
から継承し、初期要求を定義し、urlをページから抽出する方法、およびページコンテンツ抽出データを解析する方法を選択する必要があります.これは私たちの最初のSpiderのコードで、
tutorial/spiders
ディレクトリのquotes_spider.py
にファイルを保存します.import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
def start_requests(self):
urls = [
'http://quotes.toscrape.com/page/1/',
'http://quotes.toscrape.com/page/2/',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
page = response.url.split("/")[-2]
filename = 'quotes-%s.html' % page
with open(filename, 'wb') as f:
f.write(response.body)
self.log('Saved file %s' % filename)
以上のようにspiderはscrapyから継承する.Spiderはいくつかの属性と方法を定義した.
name
:spiderを識別します.プロジェクトで一意である必要があります.異なるspiderに同じ名前を設定することはできません.start_requests()
:リクエストの反復(リクエストのリストを返すかジェネレータ関数を書くことができる)を返さなければなりません.spiderはここから登り始めます.サブシーケンス要求は、これらの初期要求から自動的に生成されます.parse()
:各リクエストの完了時にメソッドを破棄します.responseパラメータは、ページコンテンツやセレクタなどの関数操作を含むTextResponse
クラスの例である.parse()
関数は通常htmlを解析し、取得したデータをdictsとして抽出し、その後、新しいURLSを検索して新しい要求を作成する.クモをどう動かすか
プロジェクトの最上位ディレクトリで実行:
scrapy crawl quotes
このコマンドは、私たちが追加した
quotes
というクモを実行します.quotes.toscrape.com
にいくつかのリクエストを送信します.次のような出力が得られます.... (omitted for brevity)
2016-12-16 21:24:05 [scrapy.core.engine] INFO: Spider opened
2016-12-16 21:24:05 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2016-12-16 21:24:05 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2016-12-16 21:24:05 [scrapy.core.engine] DEBUG: Crawled (404) (referer: None)
2016-12-16 21:24:05 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)
2016-12-16 21:24:05 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)
2016-12-16 21:24:05 [quotes] DEBUG: Saved file quotes-1.html
2016-12-16 21:24:05 [quotes] DEBUG: Saved file quotes-2.html
2016-12-16 21:24:05 [scrapy.core.engine] INFO: Closing spider (finished)
...
現在のディレクトリを確認します.2つの新しいファイルquotes-1が作成されたことに気づきます.htmlとquotes-2.htmlにはurlsの応答データが含まれています.
内部メカニズムとは
Scrapyはクモの
start_requests
メソッドを呼び出し、応答を受信するとすぐにResponseオブジェクトを初期化し、要求された戻り関数(この例では、時parse()
関数)を呼び出してresponseオブジェクトをパラメータとする.start_requests関数の概要
start_requests
関数の代わりに、start_urls
のシードリストを定義することができる.デフォルトのstart_requests()
関数インプリメンテーションでは、start_urls
を使用して初期要求が作成されます.import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'http://quotes.toscrape.com/page/1/',
'http://quotes.toscrape.com/page/2/',
]
def parse(self, response):
page = response.url.split("/")[-2]
filename = 'quotes-%s.html' % page
with open(filename, 'wb') as f:
f.write(response.body)
urlsのリクエストのたびに
parse()
が呼び出されます.これはparse()がScrapyが明示的に戻り関数に値を与えていない場合のデフォルトの戻り関数であるためである.データの抽出
最も良い学習はScrapyのセレクタを使う方法はScrapy shellを使うことです.
scrapy shell 'http://quotes.toscrape.com/page/1/'
ヒント
単一引用符でアドレスをラップすることを忘れないでください.そうしないと、&文字などのパラメータが含まれています.
Windowsで二重引用符を使う
次のようになります.
[ ... Scrapy log here ... ]
2016-09-19 12:09:27 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)
[s] Available Scrapy objects:
[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s] crawler
[s] item {}
[s] request
[s] response <200 http://quotes.toscrape.com/page/1/>
[s] settings
[s] spider
[s] Useful shortcuts:
[s] shelp() Shell help (print this help)
[s] fetch(req_or_url) Fetch request (or URL) and update local objects
[s] view(response) View response in a browser
>>>
shellではresponseオブジェクトのCSS関数を使用して要素を選択できます.
>>> response.css('title')
[]
response.css('title')
の実行結果は、XML/HTML要素を含むSelectorListというlist-likeオブジェクトであり、選択とデータの抽出をさらに問い合わせることができます.titleのテキストをエクスポートするには、次のようにします.
>>> response.css('title::text').extract()
['Quotes to Scrape']
ここで注意しなければならない点は2つあります.1つは、
::text
をCSSクエリに追加しました.つまり、</code> text 。 <code>::text</code>, title 。</p>
<pre><code>>>> response.css('title').extract()
['<title>Quotes to Scrape ']
のみを選択したことを意味します.二、
.extract()
は、SelectorList
のテキストリストを返す.最初の要素のテキストのみを取得します.>>> response.css('title::text').extract_first()
'Quotes to Scrape'
pythonのリスト書き方も使用できます.
>>> response.css('title::text')[0].extract()
'Quotes to Scrape'
しかし、
extract()
およびextract_first()
の方法を使用すると、一致する要素が見つからないときにNone
に戻り、IndexError
を回避することができる.extract()
メソッドとextract_first()
メソッドに加えて、re()
の正規表現メソッドを使用することもできます.>>> response.css('title::text').re(r'Quotes.*')
['Quotes to Scrape']
>>> response.css('title::text').re(r'Q\w+')
['Quotes']
>>> response.css('title::text').re(r'(\w+) to (\w+)')
['Quotes', 'Scrape']
適切なCSSセレクタを見つけるには、shellからview(response)を使用して応答インタフェースを参照します.Firebugなどのブラウザ開発ツールやプラグインを使用できます(ここではFirebugを使用してキャプチャし、FireFoxを使用してキャプチャするを参照してください).
セレクタウィジェットもCSSセレクタを検索するのに良いツールで、要素を可視化することができ、多くのブラウザで作業することができます.
XPATH:概要
cssに加えて、ScrapyセレクタもXPath式をサポートします.
>>> response.xpath('//title')
[]
>>> response.xpath('//title/text()').extract_first()
'Quotes to Scrape'
XPATH式は強力で、Scrapyセレクタの基礎です.実際、CSSセレクタは内部でXpathに変換されます.shellでテキストセレクタのオブジェクトタイプを表示できます.
CSSセレクタほど流行していないにもかかわらず、Xpath式はもっと強い.構造にナビゲートするだけでなく、コンテンツを検索することもできます.xpathを使用すると、次のように選択できます.Next Pageを含むテキスト接続を選択します.これにより、xpathはキャプチャに非常に適しており、CSSセレクタをどのように構築するかを知っていても、Xpathを学ぶことを奨励します.
私たちはここでXPathにあまり触れません.XPathを読むことができます.Xpathを学ぶために、例を通してXPathチュートリアルを学ぶことと、XPathを使って考える方法をお勧めします.
quotesとauthorsの抽出
選択と抽出に関する知識を少し知っています.私たちのspiderを改善し、コードを書いてウェブサイトのページからquotesを抽出しましょう.
http://quotes.toscrape.comの各quoteのHTML形式は次のようになります.
“The world as we have created it is a process of our
thinking. It cannot be changed without changing our thinking.”
by Albert Einstein
(about)
scrapy shellを開いて、私たちが望んでいるデータを抽出しようとします.
$ scrapy shell 'http://quotes.toscrape.com'
次の構文を使用して、一連のquote要素のセレクタを得ます.
>>> response.css("div.quote")
各セレクタは、サブ要素をクエリーできます.最初のセレクタを変数に割り当て、指定したquoteセレクタを直接実行できます.
quote = response.css("div.quote")[0]
次に、quoteから
title
、author
、およびtags
をエクスポートし、作成したばかりのquote
オブジェクトを使用します.最初の結果だけが必要だと知ったら、次のことができます.>>> title = quote.css("span.text::text").extract_first()
>>> title
'“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”'
>>> author = quote.css("small.author::text").extract_first()
>>> author
'Albert Einstein'
ラベルが文字列リストであることを考慮すると、
.extract()
メソッドを使用して取得できます.>>> tags = quote.css("div.tags a.tag::text").extract()
>>> tags
['change', 'deep-thoughts', 'thinking', 'world']
各エクスポート方法を解決し、すべてのquotes要素を反復してPython辞書に保存できます.
>>> for quote in response.css("div.quote"):
... text = quote.css("span.text::text").extract_first()
... author = quote.css("small.author::text").extract_first()
... tags = quote.css("div.tags a.tag::text").extract()
... print(dict(text=text, author=author, tags=tags))
{'tags': ['change', 'deep-thoughts', 'thinking', 'world'], 'author': 'Albert Einstein', 'text': '“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”'}
{'tags': ['abilities', 'choices'], 'author': 'J.K. Rowling', 'text': '“It is our choices, Harry, that show what we truly are, far more than our abilities.”'}
... a few more of these, omitted for brevity
>>>
spiderを使用してデータをエクスポートする
spiderに戻りましょう.今でもデータはエクスポートされず、HTMLページをローカルファイルに保存するだけです.導出ロジックをspiderに統合した.
1つのScrapyクモには、通常、複数のページでデータをキャプチャする辞書が含まれます.これにより、コールバック関数で
yield
Pythonキーワードを使用することができます.以下に示します.import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'http://quotes.toscrape.com/page/1/',
'http://quotes.toscrape.com/page/2/',
]
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').extract_first(),
'author': quote.css('span small::text').extract_first(),
'tags': quote.css('div.tags a.tag::text').extract(),
}
このクモを実行すると、エクスポートデータがログに出力されます.
2016-09-19 18:57:19 [scrapy.core.scraper] DEBUG: Scraped from <200 http://quotes.toscrape.com/page/1/>
{'tags': ['life', 'love'], 'author': 'André Gide', 'text': '“It is better to be hated for what you are than to be loved for what you are not.”'}
2016-09-19 18:57:19 [scrapy.core.scraper] DEBUG: Scraped from <200 http://quotes.toscrape.com/page/1/>
{'tags': ['edison', 'failure', 'inspirational', 'paraphrased'], 'author': 'Thomas A. Edison', 'text': "“I have not failed. I've just found 10,000 ways that won't work.”"}
取得したデータの保存
最も簡単なキャプチャデータの保存はFeed exportsを使用し、次のコマンドラインを使用します.
scrapy crawl quotes -o quotes.json
これによりquotesが生成されますjsonファイルには、すべてのキャプチャイメージがjsonにシーケンス化されています.
履歴上の理由で、Scrapyは上書きではなく追加を使用します.このコマンドを2回実行して2回目の削除前のファイルがなければ、破損したJSONファイルが得られます.
Json Linesのような他のフォーマットも使用できます
scrapy crawl quotes -o quotes.jl
Json Linesフォーマットはstream-likeなので役に立ちます.新しい記録を簡単に追加することができます.彼は上のJSONファイルの問題を持っていません.あなたが2回実行したとき.また、各レコードは1行なので、メモリの問題を心配することなく、大きなファイルを処理できます.JQのようなツールはコマンドラインで処理できます.
小さなプロジェクト(例のようにチュートリアル)では、これで十分です.しかし、より複雑なキャプチャ項目を処理したい場合は、[Itemパイプ]を作成することができます.プロジェクトが作成されると、
tutorial/pipelines.py
にItemパイプファイルが構築されます.これにより、キャプチャしたアイテムを保存したいだけであれば、Itemパイプを実装する必要はありません.次の接続
捕まえたいだけじゃなくhttp://quotes.toscrape.comサイトの中の2つのページではなく、すべてのサイトのページをキャプチャしたいと思っています.
ページからデータをキャプチャする方法を知っています.次の接続を見てみましょう.
まずページから目的の接続を抽出します.ページを表示すると、次のページに次のフラグが接続されています.
shellから抽出してみます.
>>> response.css('li.next a').extract_first()
'Next →'
これはanchor要素全体を得たが、
href
属性がほしい.そのため、ScrapuはCSSの拡張機能を提供し、以下のように属性の内容を選択することができます.>>> response.css('li.next a::attr(href)').extract_first()
'/page/2/'
次のページを追跡してデータをエクスポートできるようにspiderが変更されました.
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'http://quotes.toscrape.com/page/1/',
]
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').extract_first(),
'author': quote.css('span small::text').extract_first(),
'tags': quote.css('div.tags a.tag::text').extract(),
}
next_page = response.css('li.next a::attr(href)').extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.Request(next_page, callback=self.parse)
次に、データをエクスポートした後、
parse()
関数は次のページを検索し、urljoin
を使用して絶対パスURLを構築し、次のページへの新しいリクエストを生成し、次のページのリクエストをコールバックとして登録してクモがすべてのページに登ることができるようにします.これはScrapyがページを追跡するメカニズムです.コールバックで要求オブジェクトを生成すると、要求の送信とコールバック関数の登録が要求の終了時に実行されます.
これらを使用すると、複雑な爬虫類システムを構築したり、リンクルールをカスタマイズしたり、アクセスページに基づいてさまざまなデータをエクスポートしたりすることができます.
私たちの例では、ブログ、フォーラム、または他のナビゲーションサイトを簡単にアクセスできるように、すべてのリンクを次のページに追跡する一連のループを作成します.
その他の例とモード
これは別のクモがコールバックと追跡接続を説明するために使用され、今回は著者の情報をキャプチャします.
import scrapy
class AuthorSpider(scrapy.Spider):
name = 'author'
start_urls = ['http://quotes.toscrape.com/']
def parse(self, response):
# follow links to author pages
for href in response.css('.author+a::attr(href)').extract():
yield scrapy.Request(response.urljoin(href),
callback=self.parse_author)
# follow pagination links
next_page = response.css('li.next a::attr(href)').extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.Request(next_page, callback=self.parse)
def parse_author(self, response):
def extract_with_css(query):
return response.css(query).extract_first().strip()
yield {
'name': extract_with_css('h3.author-title::text'),
'birthdate': extract_with_css('.author-born-date::text'),
'bio': extract_with_css('.author-description::text'),
}
クモはホームページから始まり、
parse_author
コールバック関数を使用してすべての作成者のページ接続を追跡し、parse
コールバック関数を使用してナビゲーション接続を追跡します.parse_author
コールバック関数は、CSSクエリからPython dictを抽出してクリーンアップし、作成者データを使用して生成するヘルプメソッドを定義します.もう一つのクモに関する興味深いことは、同じ著者から多くの名言が出ても、同じ著者のページに何度もアクセスする心配はありません.デフォルトでは、Scrapyは重複したアクセス済みリクエストアドレスをフィルタリングし、プログラムがサーバをクリックしすぎる問題を回避します.これはDUPEFILTERでCLASS構成.
Scrapyがページとコールバックを追跡するメカニズムを理解してほしい.
このプログラムは追跡リンクメカニズムを利用して実現され、CrawlSpiderクラスを表示します.それは共通のクモで小さなルールエンジンを実現し、それ以上に自分の爬虫類を書くことができます.
https://doc.scrapy.org/en/latest/intro/tutorial.html