Python에서 Slack에 기압 정보 (BeautifulSoup에서 취득)를 그래프 첨부로 보내고 싶다 (+Google Spread Sheet로 관리하고 싶다)
우선 Github
소스 코드(Github)
배경
저기압 혹은 기압이 급강하할 때에는, 이하의 증상이 나타나는 사람이 많다고 합니다.
내 타임 라인을 보면 기압이 내려 왔을 때 경고를 내주는 사람도 있습니다.
기사도 꽤 있습니다.
과학적 근거가 있는지 몰라
일단 내 컨디션과 기압이 관련되는지 알아보고 싶어졌습니다.
목적
해결 방법 · 이번 일
(
tree
명령은 win에서도 사용할 수 있네요)root/
│ .env
│ .env.sample
│ .gitignore
│ app.py
│ ---.json
│ README.md
│ requirements.txt
│
├─api_packages/
│ │ googleItem.py
│ │ slackItem.py
│ │ __init__.py
│
├─data_packages/
│ │ fetchHtml.py
│ │ generateGraph.py
│ │ __init__.py
│
├─imgs/
python=3.8
pip install beautifulsoup4
pip install requests
pip install numpy
pip install matplotlib
pip install python-dotenv
pip install gspread
pip install oauth2client
기압 획득
API로 취득하는 것도 생각했습니다만, 기상청이 공개하고 있는 도쿄의 데이터를 사용하게 하기로 했습니다.
htps //w w. j. . jp / jp / 아메다 s_h / 토다 y-44132. HTML
그냥
BeautifulSoup
공부도하고 싶었기 때문에 그것도 겸하고 있습니다.fetchHtml.py
import requests
from bs4 import BeautifulSoup
import datetime
import re
class HtmlFetcher:
url = None
def __init__(self, url):
self.url = url # 可変にしようとしたが、止めた…
def fetch_pressure_from_jma(self, search_time = datetime.datetime.now()): # デフォルト引数を取っていますがこれやるとだめ
url = "調べたいURL"
try:
res = requests.get(url)
soup = BeautifulSoup(res.text, 'html.parser')
trs = soup.select("div#div_table > table > tr")
list_time_pressure = []
for tr in trs:
tds = tr.select("td")
if tds[0].get_text().isdigit() and tds[8].get_text().replace('\xa0', ''):
list_time_pressure.append(
{
'time': int(tds[0].get_text()),
'pressure': tds[8].get_text()
}
)
if len(list_time_pressure) == 0:
return None
else:
date_place_title = soup.select("table#tbl_title td.td_title")[0].get_text()
year = re.search(r'\d{4}年', date_place_title).group()[0:4]
month = re.search(r'\d{2}月', date_place_title).group()[0:2]
day = re.search(r'\d{2}日', date_place_title).group()[0:2]
place = re.search(r'\s+\D+\Z', date_place_title).group()[1:]
result = {}
# if search_time:
# 指定した時刻に最も近いデータを取得したかった…
# sorted_time_pressures = sorted(list_time_pressure, key=lambda x: abs(int(search_time.hour - x['time'])))
# もっとも時間が最近のものを取得
sorted_time_pressures = sorted(list_time_pressure, key=lambda x:-x['time'])
result = {
'data': sorted_time_pressures,
'info': {'day': day, 'month': month, 'year': year, 'place': place}
}
return result
except Exception as e:
print(e)
return False
어쩐지 분위기에서 읽을 수 있을까 생각합니다만
trs = soup.select("div#div_table > table > tr")
jQuery
이나 SCSS
를 익숙한 사람이라면 비교적 직관적인 기법이라고 생각합니다.위의 페이지는 단순한 구성이었지만, 반대로
Class
가 별로 없거나 해서 깊은 취득 방법을 해야 했습니다.해당 페이지에서 2020년 03월 01일에 인용
if tds[0].get_text().isdigit() and tds[8].get_text().replace('\xa0', ''):
여기서 그 행이 기압을 표시하고 있는지를 판정하고 있습니다.
시간
기온
강수량
...
시간
℃
mm
...
1
8.5
0.5
...
「시간」의 행과 「시」의 행은 기압 데이터가 없습니다.
그래서 정수로 변환할 수 있는 데이터라면 기압이 9번째는 열에는 기압이 들어가 있다고 합니다.
또 기압이 미기입이라면 취득해도 어쩔 수 없기 때문에 나중의 조건을 넣고 있습니다.
수수께끼의 문자가 들어 있기 때문에 대체했습니다.
여기 제대로 움직이고 있는지 기사 쓰고 있으면 불안해져 왔습니다.
list_time_pressure = []
예를 들어 오전 1시에 얻으면 이 목록은 길이 1이라는 느낌이 됩니다.
date_place_title = soup.select("table#tbl_title td.td_title")[0].get_text()
최초의 지명과 날짜가 들어가는 무렵의 정보를 취득하고 있습니다.
td_title
라고 Class명을 붙이는 것 같습니다.이것을 정규 표현을 사용해 분할해 갑니다.
# 最初の整数4桁は年
# 大化の改新があった645年や未来20000年のデータを取得できないんですが、まあ…
year = re.search(r'\d{4}年', date_place_title).group()[0:4]
month = re.search(r'\d{2}月', date_place_title).group()[0:2]
day = re.search(r'\d{2}日', date_place_title).group()[0:2]
# 一番最後は土地名のようです
place = re.search(r'\s+\D+\Z', date_place_title).group()[1:]
sorted(list_time_pressure, key=lambda x:-x['time'])
가장 시간이 가까운 순서로 정렬하고 있습니다.
날짜 변경하면 대응할 수 없을까~라고 생각하면, 전날의 데이터는 날짜가 바뀐 타이밍에 리셋 되는 것은 아니었기 때문에, 이것으로 말하고 있습니다.
여담
여기서 피곤해서 기사를 나누기로 결정했습니다.
Reference
이 문제에 관하여(Python에서 Slack에 기압 정보 (BeautifulSoup에서 취득)를 그래프 첨부로 보내고 싶다 (+Google Spread Sheet로 관리하고 싶다)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/hungrykirby/items/a4b945ed5770aea223c0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)