PythonのスクレイピングとWeb APIの利用方法をある程度理解したので、Webサイトへの活用方法を考えてみました。
主婦目線で考えると、やはり常に気になるのはお天気!ということで、お天気情報を自分のサイトに表示することに。
まずは、無料Web APIの利用を検討するも、下記のような問題点が↓
OpenWeatherMap・・・日本のお天気情報の精度が悪い(あまりにも天気予報と違いすぎる)
livedoor天気情報・・・サイトが常時SSL化されていないため、画像リンクさせたら、自分のサイトもSSL化されなくなってしまう
ということで、結局、二次利用OKの気象庁のホームページからスクレイピングさせて頂くことにしました。
まずはPythonですが、ログインも不要なので、urllib.requestとBeautifulSoupで、セレクタを指定してスクレイピングします。
なおPythonファイルは、プログラムの最初にパスを入れたシェバン(例えば「#!/user/bin/python」)を記述し、任意の場所に設置します。
#!/user/bin/python
from bs4 import BeautifulSoup
import urllib.request as req
from urllib.parse import urljoin
url = “https://www.jma.go.jp/jp/yoho/329.html”
res = req.urlopen(url)
soup = BeautifulSoup(res, “html.parser”)
# 今日の天気
today_title = soup.select_one(“table#forecasttablefont > tr:nth-of-type(2) > th”).text
t_img = soup.select_one(“table#forecasttablefont > tr:nth-of-type(2) > th > img”)[‘src’]
t_img_src = urljoin(url, t_img)
t_img_alt = soup.select_one(“table#forecasttablefont > tr:nth-of-type(2) > th > img”)[‘alt’]
:
ここではまったのが、Chromeの開発者ツールでコピーしたセレクタだと、例えばtoday_title部分は下記のようになってしまいます。
#forecasttablefont > tbody > tr:nth-child(2) > th
これをそのまま入れてしまうと、エラーになってスクレイピングできません。
ググってみると、Chromeの自動機能で”tbody”を入れてしまっているので、これをとっぱらうのと、”nth-child”という書き方はだめで、”nth-of-type”としないとだめとのこと。修正して無事スクレイピングできました。
参考:https://ameblo.jp/matometa-daizu/entry-12379204248.html
あと、もう1つはまったのが、時間帯によって最高気温や最低気温の部分の表示がなくなること。
ここもtable使っているんですが、気温表示がなくなるときにtable要素(th,td)自体もなくなってるんですよね。
なので、指定するセレクタの存在自体がなくなるので、そこで分岐させる必要があります。
if soup.select_one(“table#forecasttablefont > tr:nth-of-type(2) > td.temp > div > table > tr:nth-of-type(2) > td.min”):
t_low_temp = soup.select_one(“table#forecasttablefont > tr:nth-of-type(2) > td.temp > div > table > tr:nth-of-type(2) > td.min”).text
else:
t_low_temp = “–“
if soup.select_one(“table#forecasttablefont > tr:nth-of-type(2) > td.temp > div > table > tr:nth-of-type(2) > td.max”):
t_high_temp = soup.select_one(“table#forecasttablefont > tr:nth-of-type(2) > td.temp > div > table > tr:nth-of-type(2) > td.max”).text
else:
t_high_temp = “–“
最初は、例えばt_low_temp(最低気温)のありなしで分岐させていたのですが、夕方5時以降になると、このセレクタ自体がなくなりエラーになってしまう(こんな仕様やめてほしい。。。)ので、textを抽出する前で分岐させると、ちゃんと”–“を表示するようになりました。
表示部分は以下です。
.strip()で改行を削除しています。
※改行が入るとPHPに渡す際に別々の配列要素になるため、とっておいた方がよいです。
print(t_img_src)
print(t_img_alt)
print(t_low_temp.strip())
print(t_high_temp.strip())
次に、PHP側ですが、Wordpressサイトなので、まずテスト用のページテンプレートを作って表示確認します。
テンプレート内に以下を記述し、Pythonプログラムをexec()関数から呼び出します。
exec()は、第一引数の指定コマンドを実行し,その出力の各行を第二引数の配列要素とします。
ですので、下記では、Pythonでprint()で出力した順番に、その中身が$output[]に入ることになります。
<?php
$command=”/home/user/・・・/weather-info.py”;
exec($command, $output); ?>
<div class=”weather_info”>
<div class=”w_date”><?php echo $output[0]; ?></div>
<div class=”weather”>
<div class=”weather-img”><img src=”<?php echo $output[1]; ?>”>
<div class=”weather-text”><?php echo $output[2]; ?></div></div>
<div class=”temp”><p>最低気温 <?php echo $output[3]; ?></p>
<p>最高気温 <?php echo $output[4]; ?></p></div>
</div>
:
後は、降水確率なんかも同様にスクレイピングして、CSSで表示を整えると、こんな感じになりました。
明日の天気も知りたいので、同様にコードを追加し、PHPで出力して、「sidebar.php」に追加しました。
PCなら、このページの右サイドバー、スマホならタップして下部を見て下さいね。
他にもPythonのWebサイトへの活用方法を考えていきたいです。