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

yukke_longriders

ぼちぼちがんばる

urllib.request と BeautifulSoup を使った Python で ウェブスクレイピング

ウェブスクレイピングをする機会があり、やったことを忘れないように整理しておきます。
環境 Python 3.6.0 |Anaconda 4.3.0 (64-bit)|

気象庁のページから気象情報を抽出しようと思います。

import urllib.request
from bs4 import BeautifulSoup

url = 'http://www.data.jma.go.jp/obd/stats/etrn/view/hourly_s1.php? \
    prec_no=44&block_no=47662&year=2017&month=3&day=30'
with urllib.request.urlopen(url) as response:
    html = response.read()
soup = BeautifulSoup(html, 'lxml')

これで読み込みは完了です。

次に、ページにある表の12時の気温、天気の情報を取り出します。
tableタグから絞っていきます。

table = soup.find_all('table')

tableタグの中身がそれぞれリストに格納されます。正確にはリストオブジェクトではなくとなりますが、出力結果もリストと変わらないのででリストと同じようにとらえています。
オフセットを指定して目的の表を探してもいいのですが、結構大変なのでclassまたはid属性で条件を絞ります。
今回の例ではclass属性値が'data2_s'を持つものが2つあるので`id`の属性値を指定します。

table = soup.find_all('table', id='tablefix1')[0]

注意ですが、classの属性名で絞る場合には、予約語と被るので`class_`とアンダーバーを追加する必要があります。
tr、tdタグも同様に。

tds = table.find_all('tr')[13].find_all('td')
tds = [tds[i] for i in [0, 14, 15]]

これで12時の時間、気温、天気のみのtdタグを選択できました。
確認してみます。

from pprint import pprint
pprint(tds)
[<td style="white-space:nowrap">12</td>,
 <td class="data_0_0">16.5</td>,
 <td class="data_0_0"><img alt="快晴" src="../../data/image/tenki/large/F89F.gif"/></td>]

ページと見比べてみると確かに12時の気温と天気まで絞れています。

タグの要素の中身はインスタンス変数textへのアクセスで取り出せます。

print(tds[1].text)
16.5

天気の'快晴'という情報を得るには、imgタグのaltの属性値を取り出します。
findでimgタグを取り出し辞書型としてアクセスします。

print(tds[2].find('img')['alt'])
快晴

これで簡単なものは大体足りると思います。