熊本県の新型コロナウイルス感染症対策に係る状況のPDFをスクレイピング

camelot・pdfminer.sixはテキスト抽出できない

tabulaはできた

pdftotextかpdfboxでテキスト抽出してから正規表現の方がよさそう

www.pref.kumamoto.jp

stop-covid19-kumamoto.netlify.com

!wget "https://www.pref.kumamoto.jp/common/UploadFileOutput.ashx?c_id=3&id=31611&sub_id=1&flid=227167" -O data.pdf

!apt install poppler-utils poppler-data

!pdftotext -layout data.pdf
import re

with open("data.txt") as fr:
    text = fr.read()

# テキスト確認

result = []

for line in text.splitlines():

    s = line.strip()

    m = re.match("(検査件数|陽性|陰性).+\d$", s)

    if m:
        result.append(s.split())

result

兵庫県の新型コロナウイルスに感染した患者の状況のExcelファイルをデータラングリング

# -*- coding: utf-8 -*-

import datetime
import json
import re
from urllib.parse import urljoin

import pandas as pd
import requests
from bs4 import BeautifulSoup

url = "https://web.pref.hyogo.lg.jp/kk03/corona_kanjyajyokyo.html"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
}

days = ["月", "火", "水", "木", "金", "土", "日"]

r = requests.get(url, headers=headers)

r.raise_for_status()

soup = BeautifulSoup(r.content, "html.parser")

# スクレイピング

tag = soup.select_one("a.icon_excel")

s = tag.get_text(strip=True)

link = urljoin(url, tag.get("href"))

# 最終更新日

ms = re.match(r"新型コロナウイルスに感染した患者の状況[((](\d+)月(\d+)日\s(\d+)時現在[))]", s)

m, d, h = map(int, ms.groups())

last_update = datetime.datetime(datetime.datetime.now().year, m, d, 0, 0) + datetime.timedelta(hours=h)

# データラングリング

my_parser = lambda date: pd.to_datetime(
    date, unit="D", origin=pd.Timestamp("1899/12/30")
)


df = pd.read_excel("data.xlsx", skiprows=3, skipfooter=2, parse_dates=[2], date_parser=my_parser)

df

# 欠損列を削除
df.dropna(how='all', axis=1, inplace=True)

df["リリース日"] = df["確認日"].dt.strftime("%Y-%m-%dT%H:%M:%S+09:00")

df["date"] = df["確認日"].dt.strftime("%Y-%m-%d")

df["年代"] = df["年代"].astype(str) + "代"

df["week"] = df["確認日"].dt.dayofweek

df["曜日"] = df["week"].apply(lambda x: days[x])


df.rename(columns={"番号": "No", "備考欄": "備考"}, inplace=True)
df.set_index("No", inplace=True)
df.sort_index(inplace=True)

df1 = df.loc[:, ["リリース日", "曜日", "居住地", "年代", "性別", "備考", "date"]].copy()

df1

patients = {
    "data": df1.to_dict(orient="records"),
    "last_update": last_update.strftime("%Y/%m/%d %H:%M"),
}

patients


with open("patients.json", "w") as fw:
    json.dump(patients, fw, ensure_ascii=False, indent=4)

# df1.to_csv("patients.csv", encoding="utf_8_sig")
続きを読む

兵庫県の新型コロナウイルス感染症の県内検査状況をスクレイピング

github.com

pdfのスクレイピングのプログラムすごいな

めちゃくちゃ勉強になった

グラフ表示用のJavascriptのデータからスクレイピング

import datetime
import json
import re

import pandas as pd
import requests
from bs4 import BeautifulSoup


def dumps_json(file_name, json_data):

    with open(file_name, "w") as fw:
        json.dump(json_data, fw, ensure_ascii=False, indent=4)


url = "https://web.pref.hyogo.lg.jp/kf16/singatakoronakensa.html"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko",
}

r = requests.get(url, headers=headers)

r.raise_for_status()

soup = BeautifulSoup(r.content, "html.parser")

# スクレイピング

tag = soup.find("script", text=re.compile("var dataset"))

t = tag.find_next("center").get_text(strip=True)

# 最終更新日

mt = re.match(r"※(\d+)/(\d+)\s(\d+)時", t)

m, d, h = map(int, mt.groups())

last_update = datetime.datetime(2020, m, d, h, 0)

# データ

s = tag.get_text(strip=True)

ms = re.match(r"var dataset=(.*?);", s, re.DOTALL)

if ms:

    dataset = json.loads(ms.group(1))

    df = pd.DataFrame(dataset, columns=["labels", "検査検体数", "検査累計", "陽性確認", "陽性累計"])

    df["date"] = pd.to_datetime("2020/" + df["labels"], format="%Y/%m/%d")

    """
    # inspections_summary
    + 日付(2/01)
    + 検査検体数
    + 陽性人数
    """

    df1 = df.loc[:, ["labels", "検査検体数", "陽性確認"]].copy()

    df1

    inspections_summary = {
        "data": df1.to_dict(orient="list"),
        "last_update": last_update.strftime("%Y/%m/%d %H:%M"),
    }

    dumps_json("inspections_summary.json", inspections_summary)

    """
    # parent_summary
    + 日付(2020-02-01T00:00:00+09:00)
    + 陽性人数
    """

    df["日付"] = df["date"].dt.strftime("%Y-%m-%dT%H:%M:%S+09:00")

    df2 = df.loc[:, ["日付", "陽性確認"]].copy()

    df2.rename(columns={"陽性確認": "小計"}, inplace=True)

    df2

    patients_summary = {
        "data": df2.to_dict(orient="records"),
        "last_update": last_update.strftime("%Y/%m/%d %H:%M"),
    }

    dumps_json("patients_summary.json", patients_summary)

    """
    # inspections
    + 日付(31/01/2020)
    + 検査検体数
    + 陽性人数
    """

    df["判明日"] = df["date"].dt.strftime("%d/%m/%Y")

    df3 = df.loc[:, ["判明日", "検査検体数", "陽性確認"]].copy()

    inspections = {
        "data": df3.to_dict(orient="records"),
        "last_update": last_update.strftime("%Y/%m/%d %H:%M"),
    }

    dumps_json("inspections.json", inspections)
続きを読む

三重県の新型コロナウイルス感染症検査実施件数をスクレイピング2

北海道オープンデータポータル www.harp.lg.jp

と同じ書式のCSVを作成

CSVからdata.jsonへ変換

qiita.com

github.com

スクレイピング

import requests
from bs4 import BeautifulSoup

import jaconv
import datetime
import csv


def daterange(_start, _end):
    for n in range((_end - _start).days):
        yield _start + datetime.timedelta(n)


url = "https://www.pref.mie.lg.jp/YAKUMUS/HP/m0068000071_00005.htm"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko",
}

r = requests.get(url, headers=headers)

r.raise_for_status()

soup = BeautifulSoup(r.content, "html5lib")


# スクレイピング
table = []

for tr in soup.find("table").find_all("tr"):

    if "月" in tr.td.text:

        tds = [
            jaconv.z2h(td.get_text(strip=True).rstrip("日件"), digit=True)
            for td in tr.find_all("td")
        ]

        m, d = [int(td.strip()) for td in tds[0].split("月")]
        dt = datetime.datetime(2020, m, d, 18, 0)

        tmp = list(map(int, tds[1:]))

        table.append([dt] + tmp)

table


# データ初期化
result = {}

for i in daterange(table[0][0], table[-1][0]):
    result[i.isoformat(timespec="minutes")] = [0, 0, 0]

result


# 上書き
for k, *v in table:
    result[k.isoformat(timespec="minutes")] = v

result


# ソート
data = sorted(result.items(), key=lambda x: x[0])
# 検査数
data_inspections = [{"日付": k, "日検査数": v[0]} for k, v in data]

with open("inspections.csv", "w", newline="", encoding="shift_jis") as fw:

    fieldnames = list(data_inspections[0].keys())

    writer = csv.DictWriter(fw, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(data_inspections)
# 陽性患者数
data_patients = [{"日付": k, "日陽性数": v[1]} for k, v in data]

with open("patients_summary.csv", "w", newline="", encoding="shift_jis") as fw:

    fieldnames = list(data_patients[0].keys())

    writer = csv.DictWriter(fw, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(data_patients)

三重県の新型コロナウイルス感染症検査実施件数をスクレイピング

こちらの方がよさそう

imabari.hateblo.jp

qiita.com

!pip install jaconv
import requests
from bs4 import BeautifulSoup

import jaconv
import datetime


def daterange(_start, _end):
    for n in range((_end - _start).days):
        yield _start + datetime.timedelta(n)


url = "https://www.pref.mie.lg.jp/YAKUMUS/HP/m0068000071_00005.htm"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko",
}

r = requests.get(url, headers=headers)

r.raise_for_status()

soup = BeautifulSoup(r.content, "html5lib")

JST = datetime.timezone(datetime.timedelta(hours=+9), 'JST')

# スクレイピング
table = []

for tr in soup.find("table").find_all("tr"):

    # 1列目に月を含む行のみ抽出
    if "月" in tr.td.text:

        # 日、件を除去し半角数字に変換
        tds = [
            jaconv.z2h(td.get_text(strip=True).rstrip("日件"), digit=True)
            for td in tr.find_all("td")
        ]

        # 月で分割し、月・日を数字に変換
        m, d = [int(td.strip()) for td in tds[0].split("月")]

        # 月・日からdatetimeを作成
        dt = datetime.datetime(2020, m, d, 18, 0).astimezone(JST)

        tmp = list(map(int, tds[1:]))

        table.append([dt] + tmp)

table

# 日付データ初期化
result = {}

for i in daterange(table[0][0], table[-1][0]):
    result[i.isoformat(timespec="milliseconds")] = [0, 0, 0]

result

# 日付をKeyに上書き
for k, *v in table:
    result[k.isoformat(timespec="milliseconds")] = v

result

# ソート、辞書リストに変換
data = [{"日付": k, "小計": v[0]} for k, v in sorted(result.items(), key=lambda x: x[0])]

data

※日付データ初期化は最終日の前日までになっていますがそのあとの上書きで最終日は追記されるため+1日は省略しています

愛媛県の新型コロナウイルス感染症に関する情報から検査結果をスクレイピング

www.pref.ehime.jp

import pandas as pd

import re
import datetime

# 和暦から西暦のdateに変換
def wareki2date(s):

    m = re.match("(昭和|平成|令和)(\d{1,2})年(\d{1,2})月(\d{1,2})日", s)

    year = int(m.group(2))
    month = int(m.group(3))
    day = int(m.group(4))

    if m.group(1) == "昭和":
        year += 1925
    elif m.group(1) == "平成":
        year += 1988
    elif m.group(1) == "令和":
        year += 2018

    result = datetime.date(year, month, day)

    return result


df1 = pd.read_html("https://www.pref.ehime.jp/h25500/kansen/covid19.html")[0]

# (人)を除去
df1.rename(columns={"検査数(人)": "検査数", "陰性(人)": "陰性", "陽性(人)": "陽性"}, inplace=True)

# 期間を開始日と終了日に分割
df_tmp = df1["期間"].str.split("~", expand=True)

# 列名変更
df_tmp.rename(columns={0: "開始日", 1: "終了日"}, inplace=True)

# 確認
df_tmp

# 日付を変換
df2 = df_tmp.applymap(wareki2date)

# 日付を結合
df = pd.concat([df1, df2], axis=1)
df

# 期間を削除
df.drop("期間", axis=1, inplace=True)

# 集計
s1 = df.sum()

s1