はじめに

今回は『スクレイピングって、どんな動きをしているの?』と中の動きがサッパリだったので、構築を交えながらスクレイピングについて学習していきたいと思いたち、下記参考資料を読みながら手を動かして構築してみました

参考資料

参考リンクにはcronで自動化や、お天気の地方コードなどの記述もあり、どちらもハンズオンを進める中で大変理解が捗りました

LINE Notify + Pythonで天気情報を取得する方法
【Python】Yahoo天気予報をスクレイピングしてデータを入手する
データ収集を大幅に効率化する「スクレイピング」とは?
手法やルール・注意点を解説!

構成図

スクリーンショット 2021-12-04 10.06.09.png

ハンズオン

1:LINE Notifyでアクセストークンを発行する

1:ログインをする

スクリーンショット 2021-12-04 10.13.09.png

2:アクセストークンの発行を押下

スクリーンショット 2021-12-04 10.15.09.png

3:トークンを発行する

LINE Notifyから送られてくるメッセージのタイトルみたいな形で毎回表示されます。
送信先(今回は製作者宛に選択しています)
スクリーンショット 2021-12-04 9.28.44.png

4:トークンが発行されたのを確認する(要保存)

要保存と書きましたが、忘れたら気軽に再発行すれば構いません。
スクリーンショット 2021-12-04 9.09.26.png

5:画面から連携されていることを確認する

スクリーンショット 2021-12-04 9.29.53.png

以上でLINE Notifyの設定は終了です

2:コードの記述

1:サンプルコード

import requests
from bs4 import BeautifulSoup

#LINE Notifyと連携するためのtoken
line_notify_token = 'XXXXXXXXX'
line_notify_api = 'https://notify-api.line.me/api/notify'

#requests.getでHTMLを取得
r = requests.get('https://weather.yahoo.co.jp/weather/jp/11/4310.html')
#BeautifulSoupを使用してパース
soup = BeautifulSoup(r.content, "html.parser")

wc = soup.find(class_="forecastCity")
#print(wc)

#.strip():前後の空白文字の削除・.splitlines():改行コードで分割
ws = [i.strip() for i in wc.text.splitlines()]
#print(ws)

#リスト内包表記で""でないものをリスト化
wl = [i for i in ws if i != ""]
#print(wl)

message = ("\n" + "埼玉さいたま市:" + wl[0] + "\n" + wl[1] + "\n"  + "最高気温:" + wl[2] + "\n"+ "最低気温:" + wl[3] + "\n" + "\n" + wl[18] + "\n" + wl[19] + "\n" + "最高気温:" + wl[20] + "\n" + "最低気温:" + wl[21] )

#LINENotifyへ通知の記述
payload = {'message': message}
headers = {'Authorization': 'Bearer ' + line_notify_token} 
line_notify = requests.post(line_notify_api, data=payload, headers=headers)

3:コードの解説

1:事前準備としてrequestsとBeauifulSoupをインストールする

フォルダの作成

tetutetu214@mbp mkdir 20211204_weather      
tetutetu214@mbp cd 20211204_weather
tetutetu214@mbp 20211204_weather touch weather.py
pip install requests 
pip install beautifulsoup4
import requests
from bs4 import BeautifulSoup

requestsはHPを開くことが出来て、requests.getとすることでGETメソッドに相当します。
BeautifuSoupは、HTMLファイル・XMLファイルからデータを抽出するためのライブラリで、これらを組み合わせて今回は情報を取得します

2:Yahoo天気予報ページのURLからHTML取得・パース

今回は埼玉県の天気予報を取得していきます→https://weather.yahoo.co.jp/weather/jp/11/4310.html

スクリーンショット 2021-12-04 10.36.30.png

#requests.getでHTMLを取得
r = requests.get('https://weather.yahoo.co.jp/weather/jp/11/4310.html')
#BeautifulSoupを使用してパース
soup = BeautifulSoup(r.content, "html.parser")

requests.getを利用してURLにアクセスしてHTML情報を取得して、BeautifulSoupで取得した情報からパースの作成をしています。

パース(parser)とは?
WebブラウザがHTMLファイルを表示するためにタグなどの構造・属性を解析して、表示可能なデータ構造に変換させるプログラムのこと。
requestsでHTML情報を取得しても解析しないと表示ができないため、BeautifulSoupで表示可能な情報に変換させている。

3:データの抽出

wc = soup.find(class_="forecastCity")

上記のコード部分は、HPの「forecastCity」というクラスの該当部分をリストで格納している動きとなります。
スクリーンショット 2021-12-04 11.37.42.png

<div class="forecastCity">
<table>
<tr>
<td>
<div>
<p class="date">
<span>12月4日</span>(<span class="daySat">土</span>)

        </p>
________________________________________________________
省略
________________________________________________________
</dl>
</div>
</td>
</tr>
</table>
</div>

4:リストの加工

取得したwcのテキストデータの改行コード毎に分割をして、分割した文字の前後に空白文字であれば削除として加工をしていきます

#.strip():前後の空白文字の削除・.splitlines():改行コードで分割
ws = [i.strip() for i in wc.text.splitlines()]
['', '', '', '', '', '', '12月4日(土)', '', '', '', '晴れ', '', '', '15℃[0]', '3℃[+1]', '', '', '', '時間', '0-6', '6-12', '12-18', '18-24', '', '', '降水', '---', '---', '10%', '0%', '', '', '', '風:', '北の風', '波:', '---', '', '', '', '', '', '', '12月5日(日)', '', '', '', '晴れ', '', '', '11℃[-4]', '3℃[0]', '', '', '', '時間', '0-6', '6-12', '12-18', '18-24', '', '', '降水', '0%', '0%', '0%', '0%', '', '', '', '風:', '北の風後東の風', '波:', '---', '', '', '', '', '']

上記コードの空白要素を消していく加工をします
if文で""でない部分を表示します

#リスト内包表記
wl = [i for i in ws if i != ""]
['12月4日(土)', '晴れ', '15℃[0]', '3℃[+1]', '時間', '0-6', '6-12', '12-18', '18-24', '降水', '---', '---', '10%', '0%', '風:', '北の風', '波:', '---', '12月5日(日)', '晴れ', '11℃[-4]', '3℃[0]', '時間', '0-6', '6-12', '12-18', '18-24', '降水', '0%', '0%', '0%', '0%', '風:', '北の風後東の風', '波:', '---']

【リスト対応表】
スクリーンショット 2021-12-04 12.16.02.png

5:リストからデータの出力

message = ("\n" + "埼玉さいたま市:" + wl[0] + "\n" + wl[1] + "\n"  + "最高気温:" + wl[2] + "\n"+ "最低気温:" + wl[3] + "\n" + "\n" + wl[18] + "\n" + wl[19] + "\n" + "最高気温:" + wl[20] + "\n" + "最低気温:" + wl[21] )
埼玉さいたま市:12月4日(土)
晴れ
最高気温:15℃[0]
最低気温:3℃[+1]

12月5日(日)
晴れ
最高気温:11℃[-4]
最低気温:3℃[0]

6:出力をLINE Notifyで出力をする

#LINE Notifyと連携するためのtoken
line_notify_token = 'XXXXXXXXXXX'
line_notify_api = 'https://notify-api.line.me/api/notify'

_______________________________________
省略
_______________________________________

#LINENotifyへ通知の記述
payload = {'message': message}
headers = {'Authorization': 'Bearer ' + line_notify_token} 
line_notify = requests.post(line_notify_api, data=payload, headers=headers)

LINE Notifyドキュメントより通知系のドキュメントを確認してAPIの形はPOSTと確認出来、requests.postを利用することでPOST送信の形をとる。

スクリーンショット 2021-12-04 9.12.47.png

ここまででコードの解説は終了です

4:挙動の確認

tetutetu214@mbp 20211204_weather python weather.py

上記打刻後LINEに下記通知がされました。
cronを利用すれば決まった時間に通知を送ることも可能です。
スクリーンショット 2021-12-04 10.45.34.png

さいごに

スクレイピングの知識も乏しく、なんとなく「情報をとってこれるんだよね!便利だが知らん」からの知識から、ある程度の書き方を理解して書けるようになりました。 また別のサイトからの情報を取得しながら理解を深めていきたいと思うのでした。
地味にLINE Notifyの通知も応用が効きやすい技術で、いろいろ掛け合わせながら師走も学習をしていきます。

Last modified: 2021-12-04

Author