pythonによるスクレイピングを楽しむ小技集

開発
Johnson MartinによるPixabayからの画像

※この記事にはプロモーションが含まれています。

今回は、pythonを使ったスクレイピングの実践的な方法を紹介します。実際にスクレイピングする機会があり、調査した情報をまとめたものです。これくらい覚えておけば、ある程度のスクレイピングは実行できると思います。

スポンサーリンク
スポンサーリンク

環境構築

python3をインストールし、スクレイピングに必要なモジュールを導入します。

pip install requests beautifulsoup4 lxml

pythonファイルの先頭には以下を記述し、モジュールをロードすればライブラリを呼び出すことができます。

import requests
from bs4 import BeautifulSoup

小技集

HTMLを丸ごと保存する

HTMLファイルを丸ごと保存する場合、requestsのcontent属性をバイナリ形式で保存すると、エンコードの影響を考慮しなくて委もよいため便利です。

s = requests.get('http://sample.local')
with open('filename', mode='wb') as f:
    f.write(s.content)

エンコードを調整する

HTMLデータのテキストを使用する場合、requestの属性に対して、エンコードを指定しておきます。これは、requestsがたまにエンコードを誤判定している場合があるため、HTMLの指定型を再指定しておきます。EUC-JPで謎のエラーに困ったときに対策したものです。

s = requests.get('http://sample.local')
s.encoding = s.apparent_encoding 
html_data = s.text

ノードを抽出する

ノード抽出にはBeautifulSoupのselect関数でCSSセレクタを使うと便利です。条件に指定できるのは、タグや属性のみでテキスト等の値はできません。下記の例だと、classに”xx yy”を持つdlタグ子孫のddタグ直下にあるaタグを収集します。

s = requests.get('http://sample.local')
soup = BeautifulSoup(s.text, 'lxml')
mynode = soup.select('dl[class="xx yy"] dd>a')

属性値を取得する

属性値は、下記attrsで取得可能です。下記では、aタグからhrefの値を取得しています。

for x in mynode:
    href_value = x.attrs['href']

ノードの値を取得する

ノードが複雑で値を取り出しづらい場合、文字列関数で加工した方が早いとおもいます。replace, splitや正規表現を用います。下記の例では、’30’という部分を取り出しています。

text = '<a href="/xxxx/yyyy">30日</a>'
y = text.replace(u'<a href="/xxxx/yyyy">', '').split(u'日')[0]

CSSセレクタについて

よく使いそうなCSSセレクタを取り上げます。

基本形

div何もつけないと、タグ名で指定する
.classname‘.’をつけると、クラス名で指定する
#idname‘#’をつけると、id名で指定する

要素探索

直下の子要素div>adivの1階層したのみにあるa要素を収集します。
子孫要素div adiv要素の下階層全てにあるa要素を収集します。
テキストフォームinput[type=”text”]input要素のtype=textである要素を収集します。
最初の子要素p:first-of-type同一階層のp要素の中で最初の要素を収集します。
最後の子要素p:last-of-type同一階層のp要素の中で最後の要素を収集します。
奇数の子要素p:nth-of-type(odd)同一階層のp要素の中で奇数順の要素を収集します。
偶数の子要素p:nth-of-type(even)同一階層のp要素の中で偶数順の要素を収集します。
属性が完全一致する要素p[class=”xxx”]p要素の中でclass=”xxx”属性を持つ要素を収集します。
属性の一部が一致する要素p[class*=”xxx”]p要素の中でclassの一部に”xxx”をもつ要素を収集します。
属性の開始が一致する要素p[class^=”xxx”]p要素の中でclassの開始に”xxx”をもつ要素を収集します。
属性の最後が一致する要素p[class$=”xxx”]p要素の中でclassの最後に”xxx”をもつ要素を収集します。
n番目の子要素p:nth-of-type(n)p要素の中でn(1~)番目に登場する要素を収集します。
後ろからn番目の子要素p:nth-last-of-type(n)p要素の中で後ろからn(1~)番目に登場する要素を収集します。

スクレイピングサンプル

スレイピング用テストサイトWeb Scraper Test Sitesを用いて、サンプルを記載します。

下記の例では、リンク先と値段を取得しています。

import requests
from bs4 import BeautifulSoup

s = requests.get('https://www.webscraper.io/test-sites/e-commerce/allinone/computers')
s.encoding = s.apparent_encoding 
soup = BeautifulSoup(s.text, 'lxml')

# get href.
node_link = soup.select('div[class="thumbnail"] h4>a')
for x in node_link:
    print('href = {0}'.format(x.attrs['href']))

# get price.
node_price = soup.select('h4[class="pull-right price"]')
for y in node_price:
    print('price = {0}'.format(y.text.replace('$','')))
href = /test-sites/e-commerce/allinone/product/578
href = /test-sites/e-commerce/allinone/product/621
href = /test-sites/e-commerce/allinone/product/611
price = 498.23
price = 1310.39
price = 1221.58

まとめ

今更ではありますが、pythonによるするクレイピングは非常に強力です。CSSセレクタを覚えれば、活用場所がぐんと広がります。これからスクレイピングを始める方の参考になれば幸いです。

以上、pythonによるスクレイピングの紹介でした。

コメント