Python Scrapy でウェブサイトからデータを抽出する際の、xpathまとめ


Python のモジュール、Scrapyを用いれば、ウェブサイトのデータを、リンクを巡回しながら順次自動的に取得できます。

ウェブサイトから所望のデータを抽出するには、欲しいデータの場所 を指定してあげなければなりません。

指定するものをセレクタと呼びます。Scrapyではcssと、xpathの指定方法がありますが、今回はxpathのして方法について説明します。

準備

Scrapyをpipでインストールします。

commandline
$ pip install scrapy

Scrapy Shell

Scrapy には、Scrapy shellと呼ばれる、インタラクティブにデータ抽出を検証できるツールがあります。

commandline
scrapy shell "http://hogehoge.com/hoge/page1"

のように指定すると、指定したページの情報が入ったresponseというインスタンスを受け取った状態でpythonのインタラクティブシェルが立ち上がります。実際にスパイダー(クローラー)を開発する際も、このresponseインスタンスからデータを抽出していきます。

実践

responseのxpathメソッド

基本的に、このような構文でデータを抽出していきます。

shell
>>> response.xpath('//title/text()')
    [<Selector (text) xpath=//title/text()>]

この例では、受け取ったhtml文章の中の、全てのtitleタグ(//title)の、本文(text())を抽出しています。ただし、このままですと上記のように、返り値はセレクタです。文字を得るには.extract()を用います。

shell
>>> response.xpath('//title/text()').extract()
    [u'exsample title']
抽出データの文字列化

抽出データはリストですので、配列指定などで文字列にします。

shell
>>> response.xpath('//title/text()').extract()[0]
    u'exsample title'

ちなみにこのu'文字列'はユニコードという意味です。pythonでは文字列をユニコードで扱います。

複数のウェブサイトを巡回していると、指定したxpathがどこにも該当しない場合があります。その状態で上記のように配列の0番目 response.xpath(hoge).extract[0] を指定するとエラーとなりますので、これを回避するために

shell
>>> item['hoge'] = response.xpath('//title/text()').extract_first()

などします。

また、得られた配列[u'hoge1', u'hoge2', u'hoge3']などを全て連結して文字列として得たければ

shell
>>> extract_list = [u'hoge1', u'hoge2', u'hoge3']
>>> ''.join(extract_list)
    u'hoge1hoge2hoge3'

とやればできます。

xpath集

xpath 内容
//div 全てのdivタグ
//div[@class='aaa'] 全ての、classに'aaa'を持つdivタグ
//div[@id='aaa']/text() 全ての、idが'aaa'のdivタグ -> の本文
//a[text()='aaa']/@href 全ての、本文が'aaa'のaタグ -> のhref属性値
//div/tr 全てのdiv -> 子要素のtrタグ
//table/tr/th[text()='price']/following-sibling::td[1]/text() 全てのテーブル -> その行 -> priceというフィールド -> そのデータ要素のうち1番目 -> の本文

最後のtableに関するxpathは、ウェブページの表から、フィールドを指定(上記の場合はprice、金額の部分)して値を取ってこれるので便利です。
tdの指定ですと、同じ行のtd要素をどんどんとってしまうので、td[1]として1番目を抜き出しています。[1]です。[0]じゃないです。