読者です 読者をやめる 読者になる 読者になる

ITの隊長のブログ

ITの隊長のブログです。いや、まだ隊長と呼べるほどには至っていないけど、日々がんばります。CakePHPとPlayFrameworkを使って仕事しています。最近はAngular2をさわりはじめたお(^ω^ = ^ω^)

pythonのフレームワークの「scrapy」を使ってみた。その2

Python scrapy

スポンサードリンク

前回の記事からの続き。

セレクターを指定の仕方はチュートリアルに乗っています。


/html/head/title:

<html>から、<head>と指定してで、最後に<title>を取得する方法さ。

※前回の記事はこのタグの指定がダメだったようで
だから途中で切れているようにみえたんですね。
文字数制限じゃなかったのか。別途記事で書きます。

/html/head/title/text():

<title>の中にある、textを取得するのさ。

//td:

<td>をぜ~んぶ取得します。

//div[@class="mine"]:

全<div>を選択するんだけど、class="mine"を選別して取得してくるよ。


(´・ω・)つ繰り返えしとなりますが。
今後、運用して理解でき次第
上記内容が間違っていたら修正致します。
ご了承くださいませ。


あんましイメージつかない人には、Shellがオススメです。
なんと!scarpyにはShellが用意されています。便利ですねー。

GigazinのURLで、試してみました。

$ scrapy shell "http://gigazine.net/"

>>> sel.xpath('///title')
[<Selector xpath='///title' data=u'<title>GIGAZINE\uff08\u30ae\u30ac\u30b8\u30f3\uff09 - 144\u30ab\u56fd\u30671\u4f4d\u306e\u300c\u30af\u30e9\u30c3\u30b7\u30e5\u30fb'>]

>>> sel.xpath('//h3[@class="sidetitle"]')
[<Selector xpath='//h3[@class="sidetitle"]' data=u'<h3 class="sidetitle"><span>\u6700\u65b0\u30cb\u30e5\u30fc\u30b930\u4ef6</s'>, <Selector xpath='//h3[@class="sidetitle"]' data=u'<h3 class="sidetitle"><span>\u7d71\u8a08</span></h'>]

>>> sel.xpath('//h3[@class="sidetitle"]//text()')
[<Selector xpath='//h3[@class="sidetitle"]//text()' data=u'\u6700\u65b0\u30cb\u30e5\u30fc\u30b930\u4ef6'>, <Selector xpath='//h3[@class="sidetitle"]//text()' data=u'\u7d71\u8a08'>]


すごぉーーーーーーーーーい(°Д° )
こいつとは、あと3年早く出会いたかったぜ。

ちなみに、Shellからは「Ctrl + D」で、抜けられます。

引き続きチュートリアル

sel.xpath('//ul/li')

<ul>から<li>とつないで、すべての<li>を取得します.

sel.xpath('//ul/li/text()').extract()

<ul>から<li>の中に入っている、textを取得。
後ろについている、.extract()ってのが、いまいちよくわかっていませんが
直訳して、「抜き出す」って意味なので
多分そういうことなのでしょう。(どゆことだよ)

通常 sel.xpath('//ul/li/') だけだと
セレクターの情報しか取得しませんが
.extract()をつけることで、そのセレクターの中を出力します。

sel.xpath('//ul/li/a/@href').extract()

取得したセレクターの中の
<a href="http://www~">の「http://www~」を取得してくれます。
むっちゃ便利!

では、これをspiderスクリプトに書き込みましょう。

  • 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):
        sel = Selector(response)
        sites = sel.xpath('//ul/li')
        for site in sites:
            title = site.xpath('a/text()').extract()
            link = site.xpath('a/@href').extract()
            desc = site.xpath('text()').extract()
            print title, link, desc


はい。実行ー

$ scrapy crawl dmoz
 ERROR: [dmoz] ERROR: Spider error processing <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
	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 "/aipa_commander/aipa_commander/spiders/dmoz_spider.py", line 15, in parse
	    sel = Selector(response)
	exceptions.NameError: global name 'Selector' is not defined


はい。エラー orz


sel = Selector(... の Selectorってなんだよ!って怒られております。
どうやらimportが足りなかったようだ
修正

from scrapy.spider import Spider
from scrapy.selector import Selector # 追加

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):
        sel = Selector(response)
        sites = sel.xpath('//ul/li')
        for site in sites:
            title = site.xpath('a/text()').extract()
            link = site.xpath('a/@href').extract()
            desc = site.xpath('text()').extract()
            print title, link, desc

それでは、再度実行
色々マトリックスになったが、問題ないようです。
やったね!!


んで、今度はItemを使いましょうか。ってチュートリアル

from scrapy.spider import Spider
from scrapy.selector import Selector

from aipa.commander.items import AipaCommanderItem

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):
        sel = Selector(response)
        sites = sel.xpath('//ul/li')
        items = []
        for site in sites:
            # この辺に注目
            item = AipaCommanderItem()
            item['title'] = site.xpath('a/text()').extract()
            item['link'] = site.xpath('a/@href').extract()
            item['desc'] = site.xpath('text()').extract()
            items.append(item)
        return items

こうすることにより、クロールした値をItemに代入して
返り値で受け取ることができます。

では、これをコマンドで受け取りましょう。

$ scrapy crawl dmoz -o items.json -t json
$ cat items.json 
~多すぎてヤバイので省略~

イマイチよくわからない、ファイルができ上がったとさ。
とりあえず、ここまでが、scrapyのチュートリアルです。

お疲れ様。