スクレイピングをやってみよう

の記事でスクレイピングしてデータ集めて見たらと投げていたので
pythonを使って藤沢市のゴミ回収日程の情報を取得して見ましょう。

集めるデータは、各月の
年月、ゴミの種類、曜日、日にちを集めたいとおもいます。
(下の画像のような感じ)

必要なライブラリを追加する


pip install requests==2.22.0 beautifulsoup4==4.8.1

ほんとざっくりしたことですが、

  • requestsは、HTTP通信用のPythonのライブラリ

  • beautifulsoup4は、htmlをパース(解析)してくれるライブラリ

htmlを取得する

htmlをパースするためにrequestsライブラリでhtmlを読み込みます。

import requests
from bs4 import BeautifulSoup

# 藤沢のゴミ収集日程
url = "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r41b.html"
response = requests.get(url) #URLを読み込む
response.encoding = response.apparent_encoding  #文字化けしてる可能性があるのでエンコードを指定
html = response.text #読み込んだhtmlをテキスト化
print(html)

これでhtmlが読み込めたことを確認できました。

注意
今回は大丈夫ですが、
短時間で連続してリクエストをしないでください。Dos攻撃になってしまいます。目安としては、一秒間隔開けて1リクエストぐらいにしてください。

htmlをパースする

上記のコードの一番下に

parser = BeautifulSoup(html, "html.parser")

を追加する。
これでパース初期化されたので、バシバシ取得していきます。

大体やることは、
パーサーしたもの(parser)をselectメソッドを使って欲しいタグをcssセレクタで取得する。

各月の年月を取得する

developerツールで藤沢市のゴミ回収日程のページを確認すると
クラス属性がdatatableのtableタグでまとめているのでこのタグを取得し、
その直下にあるcaptionタグのテキストを取得します。

for table in parser.select("table.datatable"): # cssセレクタで上記のtableタグを取得する
    # 年月
    year_month = table.find("caption").text.strip() # テキスト化し不要な文字列を除く
    print(year_month)

これで年月のラベルを取得しました。

ゴミの種類を取得する

ゴミの種類は、各table.datatableタグの
「tbody > tr > td:nth-child(1)」にあるのでここを取得します。
また「 , 」で区切ってあるので整型して出力させます。

for table in parser.select("table.datatable"):
    for tr in table.select("tbody tr"):
        # ゴミの種類(不要な文字列などが入っているので整型しています。)
        garbage_text_arry = [text.strip() for text in tr.select_one("td").text.split("、") if not text.strip() == "" ]
        for garbage_text in garbage_text_arry:
            print(garbage_text)

曜日を取得する

曜日は、各table.datatableタグの
「tbody > tr > td:nth-child(2)」にあるのでここを取得します。

for table in parser.select("table.datatable"):
    for tr in table.select("tbody tr"):
        # 曜日
        weekly = tr.select("td")[1].text #曜日
        print(weekly)

日にちを取得

ゴミの種類は、各table.datatableタグの
「tbody > tr > td:nth-child(2)」にあるのでここを取得します。
また「 , 」で区切ってあるので整型して出力させます。

for table in parser.select("table.datatable"):
    for tr in table.select("tbody tr"):
        days = tr.select("td")[2].get_text() #日にち
        molded_days = [text.strip() for text in days.strip().split("、")]
        for day in molded_days:
            print(day)

以上で欲しい部分のデータを出力できました。

ちょいと応用(csvファイルに吐き出す)

上記のことを使えば、cssにまとめることもできます。
そして、藤沢市のごみ回収方法は地区によって変わるので地区ごとの回収方法も取得して見ましょう。
以下のコードは、csvファイルを作成する
「ブロック、年月、ゴミの種類、曜日、日にち」の順に並べてます。

import re
import csv
import time
import requests
from bs4 import BeautifulSoup

url_arry = [
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r41b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r42b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r43b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r44b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r45b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r46b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r47b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r48b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r49b.html",
    "https://www.city.fujisawa.kanagawa.jp/kankyo-j/kurashi/gomi/shushubi/nittei/r410b.html",
]

if __name__=="__main__":
    try:
        with open("令和4年度_藤沢市_ゴミ回収日程.csv", "w") as f:
            writer = csv.writer(f)
            writer.writerow([
                "ブロック",
                "年月",
                "ゴミの種類",
                "曜日",
                "日にち",
            ])

            for url in url_arry:
                time.sleep(1.5)
                response = requests.get(url)
                response.encoding = response.apparent_encoding
                html = response.text
                parser = BeautifulSoup(html, "html.parser")
                block = re.search(r"\d+ブロック" ,parser.find("h1").text).group() # ブロック
                print("{}: スクレイピング開始".format(block))

                for table in parser.select("table.datatable"):
                    year_month = table.find("caption").text.strip() # 年月

                    for tr in table.select("tbody tr"):
                        garbage_text_arry = [text.strip() for text in tr.select_one("td").text.split("、") if not text.strip() == "" ]

                        for garbage_text in garbage_text_arry:
                            garbage_name = garbage_text #ゴミの種類
                            weekly = tr.select("td")[1].text #曜日
                            days = tr.select("td")[2].get_text() #日にち
                            days_arry = [text.replace("\n", "") for text in days.strip().split("、")]
                            writer.writerow([block, year_month, garbage_name, weekly] + days_arry)

                print("{}: スクレイピング終了".format(block))
    except Exception as e:
        print(e)

スクレイピングができると簡単に情報を集めることができますのでやって見てください。

この記事が気に入ったらサポートをしてみませんか?