今回の実装内容
- Line Notifyで絵文字を送る
- 簡単なスクレイピングを行いグラフ化,画像として送信
😀絵文字.py😇
pythonで絵文字を扱うには,
- 直接打ち込む(osに依存?)
- Unicodeを指定
の2つがあります.前者の方は例えばこちらの絵文字をコピーペーストで完了です.後者の方は同サイト一覧中のUnicodeを利用します.
chr(Unicode)
一つ注意点としては,Unicodeは16進数なのでそれを明記する必要があります.以下の例のように先頭に'0x'をつけることで16進数とみなしてくれます.
message = "Hi! Good Morning!" + chr(0x1F600)
Hi! Good Mornig!😀
簡単にスクレイピングをしてみる
※過度なスクレイピングは相手側のサーバーに負荷をかけます.必ずtime.sleep等を利用して間隔を空けて使用するようにしてください.
新型コロナについてはスマートニュースさんのサイトが簡素で綺麗にまとめてくれているので,今回はこちらをスクレイピングします.
LINEに通知したいのは上の表部分.
都合がいいことに,この部分はhtml内で最初の方に記載されているので,詳細なタグ・クラス属性の指定は必要ありません.ある程度で十分です.
今回は**[感染者数, 回復者数, 志望者数]と,その内部に含まれる[全体, 本日, 昨日]**をリストで指定しています.
import requests
import time
from bs4 import BeautifulSoup
def getFromTag(soup, tag_name, class_name):
content = soup.find(tag_name, class_=class_name)
return content
def getFromList(soup, get_list, isText=False, regular=""):
contents = []
for tag_name, class_name in get_list:
content = getFromTag(soup, tag_name, class_name)
if isText and content:
content = content.text
if regular:
content = re.findall(regular, content)
content = ",".join(content)
contents.append(content)
return contents
if __name__ == '__main__':
prefecture = "osaka"
base_url = "https://coronavirus.smartnews.com/jp/"
japan_html = requests.get(base_url)
japan = BeautifulSoup(japan_html.text, 'html.parser')
time.sleep(1)
local_html = requests.get(base_url + prefecture)
local = BeautifulSoup(local_html.text, 'html.parser')
get_list = [("td", "stat confirmed"), ("td", "stat recovered"), ("td", "stat death")]
child_get_list = [("div", "today"), ("div", "compare today"), ("div", "compare")]
text_japan = []
contents = getFromList(japan, get_list)
for c in contents:
text_japan.append(getFromList(c, child_get_list, isText=True))
text_local = []
contents = getFromList(local, get_list)
for c in contents:
text_local.append(getFromList(c, child_get_list, isText=True))
>>> print(text_japan)
>>> [['771,590', None, '昨日 +1,935'], ['724,049', None, '昨日 +3,538'], ['13,989', None, '昨日 +64']]
画像とは少し異なりますが(執筆中にサイトが更新されたようです)うまく取れてますね!prefectureに都道府県を代入できるのでお住いの県で試してみてください!
表を描画し画像化
先ほど取得したテキストデータを用いてmatplotlibで表をつくり,画像データ化します.
綺麗な表を作ろうとするとどうしてもプログラムが冗長になってしまいますね...
from matplotlib import pyplot as plt
plt.rcParams["figure.subplot.left"] = 0
plt.rcParams["figure.subplot.bottom"] = 0
plt.rcParams["figure.subplot.right"] = 1
plt.rcParams["figure.subplot.top"] = 1
plt.rcParams["font.family"] = "meiryo"
plt.rcParams["font.size"] = 16
def text2table(text, header=None, index=None, color=None, imageTitle=""):
if index:
for t, i in zip(text, index):
t.insert(0, i)
if header:
if index:
header = [imageTitle] + header
text.insert(0, header)
fig, ax = plt.subplots()
ax.axis('off')
tb = ax.table(cellText=text, cellLoc='center', loc='center')
tb.auto_set_font_size(False)
cell_height = 1 / len(text)
for pos, cell in tb.get_celld().items():
cell.set_height(cell_height)
if color:
for i in range(len(text)):
for j in range(len(text[0])):
if color[i][j]:
tb[i, j].set_facecolor(color[i][j])
tb[i, j].set_text_props(weight='bold', color='white')
if imageTitle:
fig.savefig("images/"+ imageTitle + ".png")
if __main__ == '__name__':
header = ["全体", "本日", "昨日"]
index = ["感染者数", "回復者数", "死亡者数"]
color = [
['', 'aqua', 'aqua', 'aqua'],
['red', '', '', ''],
['dodgerblue', '', '', ''],
['black', '', '', '']]
_ = text2table(text_japan, header, index, color, "Japan")
_ = text2table(text_local, header, index, color, "Kochi")
Line Notifyで通知する
まずはnotice.pyを用意しておきましょう
import requests
TOKEN = 'hoge'
url = 'https://notify-api.line.me/api/notify'
TOKEN_dict = {'Authorization': 'Bearer ' + TOKEN}
def notice(message, img_path=None):
message_dict = {'message': message}
if img_path:
files = {'imageFile': open(img_path, 'rb')}
requests.post(url, headers=TOKEN_dict, data=message_dict, files=files)
else:
requests.post(url, headers=TOKEN_dict, data=message_dict)
これでモジュールとして利用できるようになりました.あとは絵文字やスクレイピング,画像を利用して通知内容を華やかにしましょう!!
次回 第-11回は
ラズパイで定期的なpythonファイルの実行をしてみようと思います.温度や動作時間等のラズパイ内部情報も通知するようにする予定です.