愛知県内の発生事例のPDFをCSVに変換

  • camelotはすごく遅いのでpdfplumberに変更しています
  • 5185と5206とが入れ替わってたのでソートで並び替え
  • 12/30から未満が未満代になっている文字の重なりでcamelotは「代」を結合、pdfplumberは「代」を除去されている
pip install pdfplumber

github.com

import pathlib
import re
from urllib.parse import urljoin

import pandas as pd
import pdfplumber
import requests
from bs4 import BeautifulSoup


def fetch_file(url, dir="."):

    r = requests.get(url)
    r.raise_for_status()

    p = pathlib.Path(dir, pathlib.PurePath(url).name)
    p.parent.mkdir(parents=True, exist_ok=True)

    with p.open(mode="wb") as fw:
        fw.write(r.content)
    return p


def days2date(s):

    # No.16577以降は2021年
    y = 2021 if s.name > 16576 else 2020

    days = re.findall("[0-9]{1,2}", s["発表日"])

    if len(days) == 2:
        m, d = map(int, days)
        return pd.Timestamp(year=y, month=m, day=d)
    else:
        return pd.NaT

# スクレイピング

url = "https://www.pref.aichi.jp/site/covid19-aichi/"

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")

dfs = []

for tag in soup.find("span", text="▶ 愛知県内の発生事例").parent.find_all(
    "a", href=re.compile(".pdf$")
)[::-1]:

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

    path_pdf = fetch_file(link)

    with pdfplumber.open(path_pdf) as pdf:

        for page in pdf.pages:

            table = page.extract_table()

            df_tmp = pd.DataFrame(table[1:], columns=table[0])

            dfs.append(df_tmp)

df = pd.concat(dfs).set_index("No")

# 発表日が欠損を削除
df.dropna(subset=["発表日"], inplace=True)

# Noを数値に変換
df.index = df.index.astype(int)

# Noでソート
df.sort_index(inplace=True)

# 月日から年月日に変換
df["発表日"] = df.apply(days2date, axis=1)

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

df["w"] = (df["発表日"].dt.dayofweek + 1) % 7
df["w"] = df["w"].astype(str)

df["short_date"] = df["発表日"].dt.strftime("%m\\/%d")

df["発表日"] = df["発表日"].dt.strftime("%Y/%m/%d %H:%M")

p = pathlib.Path("./data/patients.csv")
p.parent.mkdir(parents=True, exist_ok=True)

df.to_csv(p, encoding="utf_8_sig")

tableをcsvに変換、csvを標準出力

pip install requests
pip install beaufifulsoup4
import requests
from bs4 import BeautifulSoup

import sys
import csv

# argv test

"""
del sys.argv[1:]

sys.argv.append("https://www.pref.saga.lg.jp/kiji00373220/")
sys.argv.append("3")

print(sys.argv)
"""

args = sys.argv

if len(args) > 1:

    url = args[1]
    n = 0

    if len(args) > 2:
        # 数値判定
        if args[2].isdigit():
            n = int(args[2])

    r = requests.get(url)

    # エラーの時は終了
    r.raise_for_status()

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

    tables = soup.find_all("table")

    if len(tables) > n:

        data = [
            [td.get_text(strip=True) for td in trs.find_all(["th", "td"])]
            for trs in tables[n].find_all("tr")
        ]

        writer = csv.writer(sys.stdout)
        writer.writerows(data)

佐賀県のコロナ日付変換

import datetime
import re

import pandas as pd

def days2date(s: str) -> pd.Timestamp:

    y = dt_now.year

    days = re.findall("[0-9]{1,2}", s)

    if len(days) == 2:
        m, d = map(int, days)

        if dt_now.month < m:

            y -= 1

        return pd.Timestamp(year=y, month=m, day=d)
    else:
        return pd.NaT


# 現在の日付
JST = datetime.timezone(datetime.timedelta(hours=+9), "JST")
dt_now = datetime.datetime.now(JST)

df = pd.DataFrame(data[1:], columns=data[0])

df["結果判明日"] = df["結果判明日"].apply(days2date).fillna(method="ffill")

df.to_csv(sys.stdout, index=False, header=False)

既存のau IDに「UQ mobile契約をau IDに登録」をしようとすると「CCAE1018」のエラーがでる

既存のau IDに「UQ mobile契約をau IDに登録」をしようとすると「CCAE1018」のエラーがでる

チャットで質問したらこちらからしてくださいと言われたので

UQ mobile契約をau IDに登録する faq.uqwimax.jp

またエラーこれだけで昨日一日損した


既存のau IDに「UQ mobile契約」で追加できないのでauのサポートに電話

新規にUQ mobile契約のau IDを作成して統合するように説明を受けるが

自分で統合できないのでau側で統合する必要があるとのこと

京都府の発生状況のPDFをスクレイピング

!apt install ghostscript
!pip install camelot-py[cv]
import re
from urllib.parse import urljoin
import datetime

import camelot
import pandas as pd
import requests
from bs4 import BeautifulSoup

# 月日をdatetimeに変換
def days2date(s):

    y = dt_now.year

    days = re.findall("[0-9]{1,2}", s)

    if len(days) == 2:
        m, d = map(int, days)

        if dt_now.month < m:

            y -= 1

        return pd.Timestamp(year=y, month=m, day=d)
    else:
        return pd.NaT

# 和暦をdatetimeに変換
def era2date(s):

    days = re.findall("[0-9]{1,2}", s)

    if len(days) == 3:
        y, m, d = map(int, days)

        y += 2018

        return pd.Timestamp(year=y, month=m, day=d)
    else:
        return pd.NaT

url = "https://www.pref.kyoto.jp/kentai/corona/hassei1-50.html"

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

# 現在の日付
JST = datetime.timezone(datetime.timedelta(hours=+9), "JST")
dt_now = datetime.datetime.now(JST)

サイトの一覧表を取得

tmp = pd.read_html(url)

# 入院・療養中
df1 = tmp[0].rename(columns={"Unnamed: 0": "府番号"})
df1["状態"] = "入院"

# 退院等(死亡退院・転院を含む)
df2 = tmp[1].rename(columns={"Unnamed: 0": "府番号"})
df2["状態"] = "退院"

# 入院・療養中と退院等(死亡退院・転院を含む)を結合
df_html = pd.concat([df1, df2])

# 府番号から例目を除去
df_html["府番号"] = df_html["府番号"].str.replace("例目", "").astype(int)

# 府番号をindexにセット
df_html.set_index("府番号", inplace=True)

# ソート
df_html.sort_index(inplace=True)

府番号と京都府京都市別のPDFのURLを抽出

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

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

pref_links = set()
city_links = set()

data = []

for i in soup.select("table.datatable > tbody > tr > td:nth-of-type(6) > a"):

    id = int(i.find_parent("tr").td.get_text(strip=True).replace("例目", ""))

    s = i.get_text(strip=True)

    pdf_link = urljoin(url, i.get("href"))

    data.append({"id":id, "url": pdf_link})

    if re.match("府報道発表資料", s):

        pref_links.add(pdf_link)

    elif re.match("京都市報道発表資料", s):

        city_links.add(pdf_link)

df_id = pd.DataFrame(data).sort_values(by="id").reset_index(drop=True)

# URLを基準に連番を付与
df_id["index"] = df_id.groupby("url").cumcount()

df_id

京都府のPDFから表を抽出

dfs_pref = []

# 直近30件
for link in sorted(pref_links, reverse=True)[:30]:

    tables = camelot.read_pdf(link, pages="all", split_text=True, strip_text=" \n")

    for table in tables:

        r, c = table.shape

        if (r > 1) and (c == 7):

            tmp = pd.DataFrame(table.data[1:], columns=table.data[0])

            tmp["url"] = link

            dfs_pref.append(tmp)

# PDFを結合
df_pref = pd.concat(dfs_pref).reset_index()

# 府番号と在住地域等に分割
pref_number = df_pref["府番号在住地域等"].str.extract("(\d+)(.+)").rename(columns={0: "府番号", 1:"在住地域等"})

# 発症日と症状に分割
pref_onset = df_pref["発症日症状"].str.normalize("NFKC").str.extract("(\d{1,2}月\d{1,2}日)?(.+)").rename(columns={0: "発症日", 1:"症状"})

# 検査日を抽出
pref_inspection = df_pref["現在判明している概要"].str.normalize("NFKC").str.extract("・検査日:(\d{1,2}月\d{1,2}日)(.+)?").rename(columns={0: "検査日", 1:"概要"})

# 上記を結合
df_pref = df_pref.join([pref_number, pref_onset, pref_inspection])

# 不要の列を削除
df_pref.drop(["府番号在住地域等", "発症日症状", "現在判明している概要"], axis=1, inplace=True)

# 月日からdatetimeに変換
df_pref["発症日"] = df_pref["発症日"].fillna("").apply(days2date)
df_pref["検査日"] = df_pref["検査日"].fillna("").apply(days2date)

# 府番号を整数に変換
df_pref["府番号"] = df_pref["府番号"].astype(int)

# 府番号をindexにセット
df_pref.set_index("府番号", inplace=True)

# サイトの表と結合
df_pref = df_pref.join(df_html, rsuffix="_HTML")

# CSVに出力
df_pref.to_csv("kyoto_pref.csv", encoding="utf_8_sig")

京都市のPDFから表を抽出

dfs_city = []

# 直近30件
for link in sorted(city_links, reverse=True)[:30]:

    tables = camelot.read_pdf(link, pages="2-end", split_text=True, strip_text=" \n")

    for table in tables:

        r, c = table.shape

        if (r > 2) and (c == 8):

            tmp = pd.DataFrame(
                table.data[2:],
                columns=[
                    "番号",
                    "年代",
                    "性別",
                    "居住地",
                    "発症日",
                    "症状",
                    "現在の症状程度",
                    "その他特記事項",
                ],
            )

            tmp["url"] = link

            dfs_city.append(tmp)

# PDFを結合
df_city = pd.concat(dfs_city).reset_index()

# 和暦からdatetimeに変換
df_city["発症日"] = df_city["発症日"].apply(era2date)

# 市番号を基準に府番号を結合
df_city = pd.merge(df_city, df_id)

# 不要の列を削除
df_city.drop("index", axis=1, inplace=True)

# 府番号をindexにセット
df_city.set_index("id", inplace=True)

# サイトの表と結合
df_city = df_city.join(df_html, rsuffix="_HTML")

# CSVに出力
df_city.to_csv("kyoto_city.csv", encoding="utf_8_sig")