Motive
気がついたら家にずっといて夕方になることがよくあるので、明るい時に行動したいっすよね。
てことなので冬季特有のうつ病予防対策として、全国の日の出日の入りの時刻を毎日更新して表示させてみます。
Method
日の出日の入りですが, おはこん番地は!?APIを使っています。
スクリプトですが、、、
-
Qiita記事を作成する
-
Qiita記事をapiを使って更新する
の二つに分割し、cron
を使ってだいたい午前12時くらいにrunさせる設定にします。
Development
Qiita記事を作成するスクリプト
import requests
import datetime
from bs4 import BeautifulSoup
from collections import namedtuple
import asyncio
import os
State = namedtuple('State', ['name', 'id', 'lat', 'lng'])
#dataset
states = [
State("札幌市", 1, 43.06417,141.34694),
State("青森市", 2, 40.82444,140.74),
State("盛岡市", 3, 39.70361,141.1525),
State("仙台市", 4, 38.26889,140.87194),
State("秋田市", 5, 39.71861,140.1025),
State("山形市", 6, 38.24056,140.36333),
State("福島市", 7, 37.75,140.46778),
State("水戸市", 8, 36.34139,140.44667),
State("宇都宮市", 9, 36.56583,139.88361),
State("前橋市", 10, 36.39111,139.06083),
State("さいたま市", 11, 35.85694,139.64889),
State("千葉市", 12, 35.60472,140.12333),
State("新宿区", 13, 35.68944,139.69167),
State("横浜市", 14, 35.44778,139.6425),
State("新潟市", 15, 37.90222,139.02361),
State("富山市", 16, 36.69528,137.21139),
State("金沢市", 17, 36.59444,136.62556),
State("福井市", 18, 36.06528,136.22194),
State("甲府市", 19, 35.66389,138.56833),
State("長野市", 20, 36.65139,138.18111),
State("岐阜市", 21, 35.39111,136.72222),
State("静岡市", 22, 34.97694,138.38306),
State("名古屋市", 23, 35.18028,136.90667),
State("津市", 24, 34.73028,136.50861),
State("大津市", 25, 35.00444,135.86833),
State("京都市", 26,35.02139,135.75556),
State("大阪市", 27,34.68639,135.52),
State("神戸市", 28,34.69139,135.18306),
State("奈良市", 29,34.68528,135.83278),
State("和歌山市", 30, 34.22611,135.1675),
State("鳥取市", 31,35.50361,134.23833),
State("松江市", 32,35.47222,133.05056),
State("岡山市", 33,34.66167,133.935),
State("広島市", 34,34.39639,132.45944),
State("山口市", 35,34.18583,131.47139),
State("徳島市", 36,34.06583,134.55944),
State("高松市", 37,34.34028,134.04333),
State("松山市", 38,33.84167,132.76611),
State("高知市", 39,33.55972,133.53111),
State("福岡市", 40,33.60639,130.41806),
State("佐賀市", 41,33.24944,130.29889),
State("長崎市", 42,32.74472,129.87361),
State("熊本市", 43,32.78972,130.74167),
State("大分市", 44,33.23806,131.6125),
State("宮崎市", 45,31.91111,131.42389),
State("鹿児島市", 46,31.56028,130.55806),
State("那覇市", 47,26.2125,127.68111)
]
async def get_time_sun_rise_set(year, month, day, state):
url = 'http://labs.bitmeister.jp/ohakon/api/?'
payload = {'mode':'sun_moon_rise_set', 'year':year, 'month':month, 'day':day, 'lat':state.lat, 'lng':state.lng}
response = requests.get(url, params=payload)
soup = BeautifulSoup(response.content, "html.parser")
await asyncio.sleep(1)
sunrise = datetime.datetime.strptime(soup.sunrise_hm.text,'%H:%M')
sunset = datetime.datetime.strptime(soup.sunset_hm.text,'%H:%M')
diff_seconds = (sunset - sunrise).total_seconds()
diff_hours = int(diff_seconds // (60 * 60))
diff_minutes = int((diff_seconds - diff_hours * (60 * 60)) / 60)
return state.name, soup.sunrise_hm.text, soup.sunset_hm.text, "{:02d}:{:02d}".format(diff_hours, diff_minutes)
def write_session(foutobj, path):
with open(path, "r", encoding='utf-8') as fin:
foutobj.write(fin.read())
if __name__ == "__main__":
now = datetime.datetime.now()
output = "./article.md"
base_folder = "./templates/"
loop = asyncio.get_event_loop()
cors = [get_time_sun_rise_set(now.year, now.month, now.day, s) for s in states]
result = loop.run_until_complete(
asyncio.gather(*cors)
)
build_parts = ["motive.md", "method.md", "development.md", "contents.md", "future.md", "reference.md"]
with open("./templates/contents.md", "w", encoding='utf-8') as fout:
fout.write("# Sunrize/Sunset\n\n")
fout.write("{}\n\n".format(datetime.datetime.now().strftime("【%Y/%m/%d %H:%M時更新】")))
fout.write("|city|sunrize|sunset|hours of sunlight|\n")
fout.write("|:--|:--|:--|:--|\n")
for r in result:
fout.write("|{}|{}|{}|{}|\n".format(*r))
fout.write("\n\n")
with open(output, "w", encoding='utf-8') as fout:
for p in build_parts:
write_session(fout, os.path.join(base_folder, p))
get_time_sun_rise_set()
でAPIを使って日の出日の入りの時間を出力しています。リクエストを設定するときは payload = {'mode':'sun_moon_rise_set', 'year':year, 'month':month, 'day':day, 'lat':state.lat, 'lng':state.lng}
の通り日付と緯度経度のパラメータを用います。
あと、それぞれのapi取得を安定的に取得するために念のため 非同期処理 asyncio
を使っています。
loop = asyncio.get_event_loop()
cors = [get_time_sun_rise_set(now.year, now.month, now.day, s) for s in states]
result = loop.run_until_complete(
asyncio.gather(*cors)
)
また、あとあとで編集しやすいために各セクションの文章を分割して、最終的に集約させています。
単純にファイルを読み書きするときは open(path, 'r')
でよかったのですが cron
で実行する場合は文字コードでエラーになります。
それで 引数に明示的に encoding='utf-8'
にする必要があります。(ファイルI/O由来でUnicodeDecodeErrorが出た時の対処法 を参照)
build_parts = ["motive.md", "method.md", "development.md", "contents.md", "future.md", "reference.md"]
with open(output, "w", encoding='utf-8') as fout:
for p in build_parts:
write_session(fout, os.path.join(base_folder, p))
Qiita記事をapiを使って更新する
import json
import requests
if __name__ == "__main__":
BASE_URL = "https://qiita.com/api/v2/items/"
TOKEN = "--アクセストークン--"
headers = {"Authorization": f"Bearer {TOKEN}", "Content-Type":"application/json"}
sentence = ""
with open("article.md", "r", encoding='utf-8') as fin:
sentence = fin.read()
contents = {"title": "【LIVE】全国の日の出日の入り時刻を毎日配信してみた",
"tags": [{"name": "Python"},
{"name":"cron"},
{"name":"asyncio"},
{"name":"QiitaAPI"},
{"name":"api"}],
"body": sentence,
"id":"ada82beb3b747b99a05e"
}
res = requests.patch(BASE_URL + contents["id"], headers=headers, json=contents)
print(res)
QiitaAPIを使うにはアクセストークンの発行が必要で、requests
でAPIをリクエストするときに必要です。
requests.patch({コンテンツのURL}, {ヘッダー}, {コンテンツの内容})
で内容を更新することができます。
Sunrize/Sunset
【2023/10/01 01:00時更新】
city | sunrize | sunset | hours of sunlight |
---|---|---|---|
札幌市 | 5:30 | 17:17 | 11:47 |
青森市 | 5:32 | 17:20 | 11:48 |
盛岡市 | 5:30 | 17:19 | 11:49 |
仙台市 | 5:31 | 17:21 | 11:50 |
秋田市 | 5:34 | 17:23 | 11:49 |
山形市 | 5:33 | 17:23 | 11:50 |
福島市 | 5:32 | 17:23 | 11:51 |
水戸市 | 5:32 | 17:23 | 11:51 |
宇都宮市 | 5:34 | 17:25 | 11:51 |
前橋市 | 5:38 | 17:29 | 11:51 |
さいたま市 | 5:35 | 17:26 | 11:51 |
千葉市 | 5:33 | 17:24 | 11:51 |
新宿区 | 5:35 | 17:26 | 11:51 |
横浜市 | 5:35 | 17:26 | 11:51 |
新潟市 | 5:38 | 17:28 | 11:50 |
富山市 | 5:45 | 17:36 | 11:51 |
金沢市 | 5:47 | 17:38 | 11:51 |
福井市 | 5:49 | 17:40 | 11:51 |
甲府市 | 5:39 | 17:31 | 11:52 |
長野市 | 5:41 | 17:32 | 11:51 |
岐阜市 | 5:47 | 17:38 | 11:51 |
静岡市 | 5:40 | 17:32 | 11:52 |
名古屋市 | 5:46 | 17:37 | 11:51 |
津市 | 5:47 | 17:39 | 11:52 |
大津市 | 5:50 | 17:42 | 11:52 |
京都市 | 5:51 | 17:42 | 11:51 |
大阪市 | 5:51 | 17:43 | 11:52 |
神戸市 | 5:53 | 17:44 | 11:51 |
奈良市 | 5:50 | 17:42 | 11:52 |
和歌山市 | 5:53 | 17:45 | 11:52 |
鳥取市 | 5:57 | 17:48 | 11:51 |
松江市 | 6:01 | 17:53 | 11:52 |
岡山市 | 5:58 | 17:49 | 11:51 |
広島市 | 6:04 | 17:55 | 11:51 |
山口市 | 6:07 | 17:59 | 11:52 |
徳島市 | 5:55 | 17:47 | 11:52 |
高松市 | 5:57 | 17:49 | 11:52 |
松山市 | 6:02 | 17:54 | 11:52 |
高知市 | 5:59 | 17:51 | 11:52 |
福岡市 | 6:12 | 18:04 | 11:52 |
佐賀市 | 6:12 | 18:04 | 11:52 |
長崎市 | 6:13 | 18:06 | 11:53 |
熊本市 | 6:10 | 18:03 | 11:53 |
大分市 | 6:07 | 17:59 | 11:52 |
宮崎市 | 6:07 | 18:00 | 11:53 |
鹿児島市 | 6:10 | 18:04 | 11:54 |
那覇市 | 6:21 | 18:17 | 11:56 |
Future
全国の日の出日の入り時間を出力してみると時間差が約30分から約60分くらいあり、日照時間は約30分から60分くらいの差があることがわかります。