#前回のおさらい
前回まではこちらの記事で「LINEでyahoo天気から好きな地域の天気を通知してもらおう!」にもあるように
yahoo天気から全国地域のURLを取得するところまでを説明しました。
#今回
今回このPART2では全国地域のURLから詳細な地域(市区町村)のURLを取得するまでを簡単に説明しようと
思います。
このURLの中の、例えば1つ目のから得られるページの情報としてはこのようになっています。
地方に属している主な市区町村の天気が簡単にわかります。
この画面の「稚内」などをクリックすると「稚内」の詳しい天気や降水確率が表示されます。
ここからやることは
・「地域と市区町村の名前とURLを取得すること」
・「市区町村のURLから天気情報を取得すること」
の2つです。
#プログラム実装編
ここからは実際にどうやって情報を取ってくるかを説明していきます。
まずは、「地域と市区町村の名前とURLを取得すること」を説明します。
プログラムとしては次の通りです。
with open("yahooChiku.csv", "r", encoding="utf-8") as readChikuNum:
reader = csv.reader(readChikuNum)
with open("shosaiChiku.csv", "w", encoding="cp932", newline="") as schiku:
writer = csv.writer(schiku)
column = ["地方", "市区町村", "URL"]
writer.writerow(column)
for target_url in reader:
res = requests.get(target_url[0])
soup = BeautifulSoup(res.text, 'lxml')
chiku = re.search(r".*の", str(soup.find("title").text)).group().strip("の")
elems = soup.find_all("a")
chikuList, shosaiNumList = [], []
chikuNameList = [chikuName.get_text() for chikuName in soup.find_all(class_= "name")]
for e in elems:
if re.search(r'data-ylk="slk:prefctr', str(e)):
if re.search(r'"https://.*html"', str(e)):
row = re.search(r'"https://.*html"', str(e)).group().strip('"')
chikuList.append(chiku)
shosaiNumList.append(row)
for p, e, c in zip(chikuList, chikuNameList, shosaiNumList):
writeList = [p, e, c]
writer.writerow(writeList)
初めのwith openでURLファイルの読み込み、2つ目のwith openでは地方と市区町村そしてそれぞれのURLを書き込むファイルを開きます。
次にsoupにhtmlの情報を格納して順次必要な情報を取得していきます。chikuには取得先の地方名を正規表現で地方の名前だけになるように調整して代入します。
elemsには市区町村先のURLを取得するためにhtmlのaタグをfind_allで取っておきます。
ここからファイルに書き込まれる変数が登場します。chikuNameListでは地方のhtmlからタグが「name」であるものを内包表記を使って取得しています。
運が良いことに市区町村の名前は「name」タグにすべてあります。
for文についてですが、こちらは「data-ylk="slk:prefctr」タグに市区町村のURLがあるので1つ目のif文で条件を設定しておきます。
「data-ylk="slk:prefctr」タグには市区町村のURL以外にもデータがあるのでその中でもURLの形式に一致するものだけを正規表現のsearchで判定します。
そしてchikuListには地区名をshosaiNumListには市区町村のURLを追加します。
最後のfor文でリストに格納された地方名、市区町村、URLを1行ずつ「shosaiChiku.csv」に書き込んでいきます。
このままでも市区町村ごとのURLにアクセスし、正規表現やスクレイピングでも欲しいデータを持ってくることは可能ですが、RSSがあることに気づいたためそちらもファイルに追加することにしました。
df = pd.read_csv("shosaiChiku.csv", encoding="cp932")
with open("dataBase.csv", "w", encoding="cp932", newline="") as DBcsv:
writer = csv.writer(DBcsv)
#ヘッダ書き込み
columns = ["地方", "市区町村", "URL", "RSS"]
writer.writerow(columns)
#データ(地区名、市区町村、URL、RSS)を一行ずつ書きこみ
for place, city, url in zip(df["地方"], df["市区町村"], df["URL"]):
row = [place, city, url]
rssURL = "https://rss-weather.yahoo.co.jp/rss/days/"
#URLから「数字.html」を取得>「数字.rss」に成形
url_pattern = re.search(r"\d*\.html", url).group()
url_pattern = url_pattern.replace("html", "xml")
rssURL = rssURL + url_pattern
row.append(rssURL)
writer.writerow(row)
ほぼやることは先ほどのソースと同様です。shosaiChikuにほとんどデータは入っているのでRSSのURLを
ちょちょいと追加するだけです。(趣向を変えてpandasのread_csvを使ってみました。)
RSSのベースとなるURLは、rssURLにある文字列「https://rss-weather.yahoo.co.jp/rss/days/
」です。
プログラムでは何を行っているかというと、まずはshosaiChikuを1行ずつ読み込み「地方」「市区町村」、「URL」取得します。
RSSの「days/」以降のURLが市区町村のURLの数字部と同じということに気づいたので、
次は正規表現で市区町村のURLの数字部だけを抜き出します。
また、RSSは「.html」ではなく「.xml」となっているので変換しておきます。
こうしてRSSのURLがわかったため、リストにappendして書き込むという流れです。
こうして出来上がったファイルがこちら。
直接開いて使用することがないので、見えにくくなっていますがこれでやりたいことを実現するためのデータが揃いました。(時間があるときにsqliteとか使ってdatabeseらしくする予定)
#おわりに
いろいろ書きましたが、長くなってしまったので2つあるうちの「地域と市区町村の名前とURLを取得すること」でいったん止めます。
また次の更新で、天気情報を取得してLINEで送るところまで説明できるといいなぁ。。。
ということで、また次回。