急遽クローラーが必要なことに
何でする!何でする!とキャッキャッヾ(*´∀`*)ノ ウフフしていたところ
久々にPythonを打ちたくなったので、Pythonを選定。
んで、便利なライブラリないかなーって探索していたら
「scrapy」という、フレームワークに出会った。
フレームワークかよ。と思いきや、結構便利そう。
せっかくなんで試してみることに!
環境は
インストール
$ sudo pip install scrapy
おし!入った。
ちな、easy_installでも入れられるっぽい
$ easy_install Scrapy
では、次にどれどれ・・・
あれ・・・?
プロジェクトを作成しなきゃいけないっぽい。Djangoみたいだ。。。
ちなみに、ドキュメントはこちら
Scrapy 0.22 documentation
全くではないが、読めへん。夜間にはキツイ
プロジェクトを作成
$ scrapy startproject aipa-commander Error: Project names must begin with a letter and contain only letters, numbers and underscores
ふぁっ!!?
エラーがでた。。。
どうやら、
「プロジェクトの名前には英数字とアンダースコアだけ使っておくれ」
ということらしい
何よ!ケチ!(#`Д’)
まぁ、そんなに困っていないんで、従います。
$ scrapy startproject aipa_commnander
うむ。
んで、ディレクトリ構造を移したいんだけど
どうやら「tree」コマンドがインストールされていなかったようなので
ついで、インストール
$ brew install tree
$ tree aipa_commander/ aipa_commander/ ├── aipa_commander │ ├── __init__.py │ ├── items.py │ ├── pipelines.py │ ├── settings.py │ └── spiders │ └── __init__.py └── scrapy.cfg
できたできた。
なんか、色々できた。
それぞれのディレクトリ構造はこういう意味があるらしい
※ドキュメントは英語だったので、じゃっくばうわー風に訳しました。
間違ってたら指摘ちょーだい。m(_ _ )m
scrapy.cfg:
作成したプロジェクトの設定ファイルだ。
aipa_commander/:
プロジェクトのモジュールディレクトリだ。
後からモジュールを追加したい場合は、ここに追加してくれ。
aipa_commander/items.py:
わかるだろう?このプロジェクトのアイテムファイルだ。
aipa_commander/pipelines.py:
piplinesファイルだ。
イマイチピンときていない俺は、まだまだってことさ。
(ごめんなさい、マジでわからん)
aipa_commander/settings.py:
settingファイルだ。
たぶんだが、プロジェクトの環境変数はここで追加するんだ(そうなるはずだ)
aipa_commander/spiders/:
spidersディレクトリだ。
今後作成するクローラーのスクリプトはここにおいてくれ。
ちなみに俺はクモが大嫌いだ。
(´・ω・)つ今後、運用して理解でき次第、
上記内容が間違っていたら修正致します。ご了承くださいませ。
さて、ディレクトリ構造をなんとなく理解した上で、次のチュートリアル
Defining our Item
Items are containers that will be loaded with the scraped data; they work like simple python dicts but provide additional protecting against populating undeclared fields, to prevent typos.
(´・ω・)
We begin by modeling the item that we will use to hold the sites data obtained from dmoz.org, as we want to capture the name, url and description of the sites, we define fields for each of these three attributes. To do that, we edit items.py, found in the tutorial directory. Our Item class looks like this:
(´・ωゞ)グシグシグシグシ
This may seem complicated at first, but defining the item allows you to use other handy components of Scrapy that need to know how your item looks like.
なるほど・・・、わからん!!
(`・ω・)クワッ!
よくわからないので、ここからは隊長・ザ・オリジン・翻訳で進めます。
- aipa_commander/items.py
from scrapy.item import Item, Field class DmozItem(Item): title = Field() link = Field() desc = Field()
クローラが取得したデータは、デフォルトではJsonのデータ形式で取ってくるとか
んで、それぞれ取得したいデータの形はdictに近い形式で取得することができます。
それをitems.pyに記述します。
今回はチュートリアルの形式をまずは試したいので
そのままコピペで持ってきています。
- aipa_commander/aipa_commander/spiders/dmoz_spider.py
from scrapy.spider import Spider class DmozSpider(Spider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): filename = response.url.split("/")[-2] open(filename, 'wb').write(response.body)
dmoz_spider.pyというファイルを
aipa_commander/aipa_commander/spiders/ディレクトリに作成しました。
「start_urls」にクロールしたい、urlを複数代入
んで、「parse」関数で、urlをsplitしたあとに
書き込みを実施、って感じですかね。
それではクローラーを動かしたいと思います。
# format: scrapy crawl ${classでnameに入れた値} $ scrapy crawl dmoz [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> (referer: None) xxxx-xx-xx xx:xx:xx+xxxx [dmoz] ERROR: Spider error processing <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> Traceback (most recent call last): File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/base.py", line 1178, in mainLoop self.runUntilCurrent() File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/base.py", line 800, in runUntilCurrent call.func(*call.args, **call.kw) File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/defer.py", line 368, in callback self._startRunCallbacks(result) File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/defer.py", line 464, in _startRunCallbacks self._runCallbacks() --- <exception caught here> --- File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/defer.py", line 551, in _runCallbacks current.result = callback(current.result, *args, **kw) File "/Library/Python/2.7/site-packages/scrapy/spider.py", line 56, in parse raise NotImplementedError exceptions.NotImplementedError:
ゴフッ( ゚∀゚)・∵.
ナンデや。
と、思った瞬間でしたよ。
どうやら、「aipa_commander/aipa_commander/spiders/dmoz_spider.py」の
「def parse()」がインデントされていないもよう。
from scrapy.spider import Spider class DmozSpider(Spider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] # インデント def parse(self, response): filename = response.url.split("/")[-2] open(filename, 'wb').write(response.body)
もっかい。
$ scrapy crawl dmoz xxxx-xx-xx xx:xx:xx+xxxx [dmoz] INFO: Dumping Scrapy stats: {'downloader/request_bytes': 516, 'downloader/request_count': 2, 'downloader/request_method_count/GET': 2, 'downloader/response_bytes': 16515, 'downloader/response_count': 2, 'downloader/response_status_count/200': 2, 'finish_reason': 'finished', 'finish_time': datetime.datetime(xxxx, x, xx, xx, xx, xx, xxxxx), 'log_count/DEBUG': 4, 'log_count/INFO': 7, 'response_received_count': 2, 'scheduler/dequeued': 2, 'scheduler/dequeued/memory': 2, 'scheduler/enqueued': 2, 'scheduler/enqueued/memory': 2, 'start_time': datetime.datetime(xxxx, x, xx, xx, xx, xx, xxxxx)} xxxx-xx-xx xx:xx:xx+xxxx [dmoz] INFO: Spider closed (finished)
おおっ!できたっぽいお!
やったぜ!
で・・・?
$ tree aipa_commander/ aipa_commander/ ├── Books ├── Resources ├── __init__.py ├── __init__.pyc ├── items.py ├── pipelines.py ├── settings.py ├── settings.pyc └── spiders ├── __init__.py ├── __init__.pyc ├── dmoz_spider.py └── dmoz_spider.pyc
BooksとResourcesができあがったとさ。
しかし、これでは、パースした値をどうこうすることはまだできません。
ので、チュートリアルはまだ続きます。
と、、、言いたいところですが、文字数制限に引っかかったようなので
続きは次の記事で。