愛知県の新型コロナウイルス感染症患者の発生について(日報)をスクレイピング

下記はPDFからテキスト読み取れない

画像?

コード

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

import feedparser
import pandas as pd
import requests
from bs4 import BeautifulSoup
from tabula import read_pdf


def str2date(s):

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

    y = dt_now.year

    if len(n) == 2:
        m, d = map(int, n)
        return datetime.date(y, m, d)

    elif len(n) == 3:
        y, m, d = map(int, n)
        return datetime.date(y, m, d)

    else:
        return pd.NaT


JST = datetime.timezone(datetime.timedelta(hours=+9))
dt_now = datetime.datetime.now(JST)

entries = feedparser.parse("https://www.pref.aichi.jp/rss/10/site-758.xml")["entries"]

dfs = []

for entry in entries:

    if re.match("新型コロナウイルス感染症患者の発生について", entry["title"]):

        url = entry["link"]

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

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

        dt_str = soup.select_one("#main_a > div.text_r").contents[-1].strip()
        dt_update = str2date(dt_str)

        tag = soup.find("a", text=re.compile("^新型コロナウイルス感染症患者"))

        if tag and dt_update > datetime.date(2020, 7, 23):

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

            print(f"{dt_update.isoformat()}: {link}")

            df_tmp = read_pdf(link, pages="all", lattice=True)

            if len(df_tmp) > 0:

                df = pd.concat(df_tmp)
                df.set_index("症例番号", drop=True, inplace=True)

                df["特記事項"] = df["特記事項"].str.replace("\s", "")

                df["発症日"] = df["発症日"].apply(str2date)
                df["陽性確定日"] = df["陽性確定日"].apply(str2date)

                df.to_csv(f"{dt_update.isoformat()}.csv")

                dfs.append(df)

            else:
                print(f"{dt_update.isoformat()}: テーブルが見つかりません")

        time.sleep(3)

df_all = pd.concat(dfs).sort_index()
df_all.to_csv("all.tsv")

愛媛県の食中毒の発生情報をスクレイピング

import pandas as pd
import requests
from bs4 import BeautifulSoup

url = "https://www.pref.ehime.jp/h25300/4793/shokuchuudoku/hassei.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")

data = []

for trs in soup.select("table.datatable > tbody > tr")[1:]:

    tmp = {}

    tds = [td for td in trs.select("td")]

    tmp["発生年月日"] = tds[0].get_text(strip=True)

    ps = tds[1].select("p")

    for p in ps[:-1]:
        t, c = p.get_text(strip=True).split(":", 1)
        tmp[t] = c
    
    tmp["プレスリリース"] = ps[-1].a.get("href")

    data.append(tmp)


df = pd.DataFrame(data)

df.to_csv("data.tsv", sep="\t")

PythonでCJK部首/康熙部首を置換

CJK部首/康熙部首の範囲外の「戶黑」は追加

8/3 23:50 複数該当する部首を一部除外していましたので分解して追加しました

tbl = str.maketrans(
    "⺃⺅⺉⺋⺎⺏⺐⺒⺓⺔⺖⺘⺙⺛⺟⺠⺡⺢⺣⺦⺨⺫⺬⺭⺱⺲⺹⺾⻁⻂⻃⻄⻍⻏⻑⻒⻖⻘⻟⻤⻨⻩⻫⻭⻯⻲⼀⼁⼂⼃⼄⼅⼆⼇⼈⼉⼊⼋⼌⼍⼎⼏⼐⼑⼒⼓⼔⼕⼖⼗⼘⼙⼚⼛⼜⼝⼞⼟⼠⼡⼢⼣⼤⼥⼦⼧⼨⼩⼪⼫⼬⼭⼮⼯⼰⼱⼲⼳⼴⼵⼶⼷⼸⼹⼺⼻⼼⼽⼾⼿⽀⽁⽂⽃⽄⽅⽆⽇⽈⽉⽊⽋⽌⽍⽎⽏⽐⽑⽒⽓⽔⽕⽖⽗⽘⽙⽚⽛⽜⽝⽞⽟⽠⽡⽢⽣⽤⽥⽦⽧⽨⽩⽪⽫⽬⽭⽮⽯⽰⽱⽲⽳⽴⽵⽶⽷⽸⽹⽺⽻⽼⽽⽾⽿⾀⾁⾂⾃⾄⾅⾆⾇⾈⾉⾊⾋⾌⾍⾎⾏⾐⾑⾒⾓⾔⾕⾖⾗⾘⾙⾚⾛⾜⾝⾞⾟⾠⾡⾢⾣⾤⾥⾦⾧⾨⾩⾪⾫⾬⾭⾮⾯⾰⾱⾲⾳⾴⾵⾶⾷⾸⾹⾺⾻⾼⾽⾾⾿⿀⿁⿂⿃⿄⿅⿆⿇⿈⿉⿊⿋⿌⿍⿎⿏⿐⿑⿒⿓⿔⿕戶黑",
    "乚亻刂㔾兀尣尢巳幺彑忄扌攵旡母民氵氺灬丬犭罒示礻罓罒耂艹虎衤覀西辶阝長镸阝青飠鬼麦黄斉歯竜亀一丨丶丿乙亅二亠人儿入八冂冖冫几凵刀力勹匕匚匸十卜卩厂厶又口囗土士夂夊夕大女子宀寸小尢尸屮山巛工己巾干幺广廴廾弋弓彐彡彳心戈戸手支攴文斗斤方无日曰月木欠止歹殳毋比毛氏气水火爪父爻爿片牙牛犬玄玉瓜瓦甘生用田疋疒癶白皮皿目矛矢石示禸禾穴立竹米糸缶网羊羽老而耒耳聿肉臣自至臼舌舛舟艮色艸虍虫血行衣襾見角言谷豆豕豸貝赤走足身車辛辰辵邑酉釆里金長門阜隶隹雨靑非面革韋韭音頁風飛食首香馬骨高髟鬥鬯鬲鬼魚鳥鹵鹿麥麻黃黍黒黹黽鼎鼓鼠鼻齊齒龍龜龠戸黒",
)

line = "⺟⺠⻁⻄⻑⻘⻝⻤⻨⻩⻫⻭⻯⻲戶黑"

line.translate(tbl)

「⻝」b'\u2edd'はcmapの変換表にはなかったので削除したほうがよさそう

!wget https://raw.githubusercontent.com/pdfminer/pdfminer.six/develop/cmaprsrc/cid2code_Adobe_Japan1.txt -O japan.txt

import pandas as pd

df = pd.read_csv("japan.txt", sep="\t", skiprows=451, index_col=0, na_values="*")

df1 = df["UniJIS-UCS2"].dropna().str.split(",", expand=True)
df1.sort_values(0, inplace=True)

df1.to_csv("data.csv")

で抽出したものをCJK部首2E80..2E99, 2E9B..2EF3/康熙部首2F00..2FD5の範囲を文字化しました

docs.google.com

PDF cmap

ja.wikipedia.org

github.com

https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5078.Adobe-Japan1-6.pdf

!wget https://github.com/pdfminer/pdfminer.six/archive/develop.zip
!unzip develop.zip

!cd pdfminer.six-develop/

cid2code_Adobe_Japan1.txtを書き換えてビルドしなおしてから実行

  • 1921「戸」2f3e,6238→6238、e2bcbe,e688b8→e688b8に変更したけど変わらない
  • 13757「戶」6236→6238、e688b6→e688b8に変更したけど変わらない
!python tools/conv_cmap.py -c B5=cp950 -c UniCNS-UTF8=utf-8 pdfminer/cmap Adobe-CNS1 cmaprsrc/cid2code_Adobe_CNS1.txt
!python tools/conv_cmap.py -c GBK-EUC=cp936 -c UniGB-UTF8=utf-8 pdfminer/cmap Adobe-GB1 cmaprsrc/cid2code_Adobe_GB1.txt
!python tools/conv_cmap.py -c RKSJ=cp932 -c EUC=euc-jp -c UniJIS-UTF8=utf-8 pdfminer/cmap Adobe-Japan1 cmaprsrc/cid2code_Adobe_Japan1.txt
!python tools/conv_cmap.py -c KSC-EUC=euc-kr -c KSC-Johab=johab -c KSCms-UHC=cp949 -c UniKS-UTF8=utf-8 pdfminer/cmap Adobe-Korea1 cmaprsrc/cid2code_Adobe_Korea1.txt
!python setup.py install

qiita.com

www.unixuser.org

text.baldanders.info

github.com

blog.antenna.co.jp

blog.antenna.co.jp

www.antenna.co.jp

全国地方公共団体コードに郵便番号データの住所から郡名を追加

docs.google.com

import copy
import re

import pandas as pd


def checkdigit(n):

    c = copy.deepcopy(n)
    t = 0

    for i in range(2, 7):

        c, m = divmod(c, 10)
        t += i * m

    result = (n * 10) + ((11 - (t % 11)) % 10)

    return result


# 全国地方公共団体コード
df_code = pd.read_excel(
    "https://www.soumu.go.jp/main_content/000618153.xls", usecols=[0, 1, 2]
)
df_code.rename(columns={"都道府県名\n(漢字)": "都道府県名", "市区町村名\n(漢字)": "市区町村名"}, inplace=True)

# 都道府県は削除
df_code.dropna(inplace=True)
df_code.reset_index(inplace=True, drop=True)

# 郵便番号データ
df = pd.read_csv(
    "https://www.post.japanpost.jp/zipcode/dl/oogaki/zip/ken_all.zip",
    encoding="cp932",
    header=None,
    usecols=[0, 6, 7],
    names=["コード", "都道府県名", "市区町村名"],
)

# 重複の最初以外は削除
df.drop_duplicates(keep="first", inplace=True)

# 郵便番号データのコードに検査数字を付与
df["団体コード"] = df["コード"].apply(checkdigit)

# コード列を削除
df.drop(columns="コード", inplace=True)

# 結合
df1 = pd.merge(df_code, df, on=["団体コード"], how="left", suffixes=("", "郵便"))

df1.fillna("", inplace=True)

# 全国地方公共団体コードの「梼原町」を「檮原町」に修正
df1["市区町村名"] = df1["市区町村名"].mask(
    (df1["都道府県名"] == "高知県") & (df1["市区町村名"] == "梼原町"), "檮原町"
)

# 郵便番号データの「糟屋郡須惠町」を「糟屋郡須恵町」に修正
df1["市区町村名郵便"] = df1["市区町村名郵便"].mask(
    (df1["都道府県名"] == "福岡県") & (df1["市区町村名郵便"] == "糟屋郡須惠町"), "糟屋郡須恵町"
)

# 郡名を抽出
df1["郡名"] = df1.apply(lambda x: re.sub(f'{x["市区町村名"]}$', "", x["市区町村名郵便"]), axis=1)

# 抽出失敗確認
df1[(df1["郡名"] == df1["市区町村名郵便"]) & (df1["市区町村名郵便"] != "")]

df2 = df1.loc[:, ["団体コード", "都道府県名", "郡名", "市区町村名"]].copy()
df2.to_csv("code.csv", index=None, encoding="utf_8_sig")