scrapyでよく使うxpath, cssのセレクタ

scrapyでxpath, cssを使って要素を抽出するときに、よく使うセレクタをチートシート的にまとめておく。

抽出の元となるHTMLはこんな感じとする。

from scrapy.http import HtmlResponse

res = HtmlResponse(url="http://example.com", body=b"""
    <html>
    <body>
        <div id="main">
            <ul>
                <li data="1">list1</li>
                <li data="2" class="even">list2</li>
                <li data="3">list3</li>
            </ul>
            <div>aaa<div>bbb</div></div>
        </div>
        <div id="sub">
            <ul>
                <li data="1">list4</li>
                <li data="2" class="even">list5</li>
                <li data="3">list6</li>
            </ul>
            <div>ccc<div>ddd</div></div></div>
    </body>
    </html>
""")

xpath, cssチートシート

xpath css 説明
//li/text() li::text text要素
//div[@id="main"] div#main id指定フィルタ
//li[@class="even"] li.even class指定フィルタ
//li[@data="3"] li[data="3"] 属性指定フィルタ
//div[@id="main"]/div div#main>div 直下の子取得
//li/@data li::attr(data) 属性取得

text要素をextract

res.xpath('//li/text()').extract()
res.css('li::text').extract()

→ [‘list1’, ‘list2’, ‘list3’, ‘list4’, ‘list5’, ‘list6’]

最初の要素をextract

res.xpath('//li/text()').extract_first()     # extract_first
res.xpath('//li/text()')[0].extract()     # selectorの1要素目からextract
res.css('li::text').extract_first()
res.css('li::text')[0].extract()

→ ‘list1’

id指定でフィルタ

res.xpath('//div[@id="main"]//li/text()').extract()  # [@id="main"]
res.css('div#main li::text').extract()               # #main

→ [‘list1’, ‘list2’, ‘list3’]

class指定でフィルタ

res.xpath('//div[@id="main"]//li[@class="even"]/text()').extract()  # [@class="even"]
res.css('div#main li.even::text').extract()               # .even

→ [‘list2’]

属性指定でフィルタ

res.xpath('//div[@id="main"]//li[@data="3"]/text()').extract()  # [@data="3"]
res.css('div#main li[data="3"]::text').extract()               # [data="3"]

→ [‘list2’]

直下の子要素指定でフィルタ

res.xpath('//div[@id="main"]/div/text()').extract()  #  //divなら["aa", "bb"]になる
res.css('div#main>div::text').extract()  # div#main divなら["aa", "bb"]になる 

→ [‘aaa’]

属性取得

res.xpath('//li/@data').extract()
res.css('li::attr(data)').extract()

→ [‘1’, ‘2’, ‘3’, ‘1’, ‘2’, ‘3’]

Elementを取得してループ

# xpath
for elm in res.xpath("//li"):
    #liの要素まで取得してからさらにそこからxpathで取得 
    data = elm.xpath('@data').get()
    text = elm.xpath('text()').get()
    print("{}\t{}".format(data, text))
#css
for elm in res.css("li"):
    #liの要素まで取得してからさらにそこからcssで取得 
    data = elm.css('::attr(data)').get()
    text = elm.css('::text').get()
    print("{}\t{}".format(data, text))


1 list1
2 list2
3 list3
1 list4
2 list5
3 list6

全体的に、xpathの冗長ですが理論的である気がしますね。xpathはhtmlのためだけのものではないのでそうですね。
一方cssの方はjqueryやcssを書くことに慣れていれば、簡潔に(id指定やclass指定など)書けますが、選択ではなく取得になると「あれ?どうやるの?」って気になります。

関連記事:

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)