成分と薬品名対応表

成分と薬品名対応表
ここから対応表を作ってみた。100近い分類でendは20ぐらいで分けてスクレーピングするのがいいかと。

ほかにも以下の点に注意

前のコードには厚労省のサイトに負荷をかけすぎないように以下の注意が必要。
「アクセス間隔を空けること」
「robots.txt や利用規約を確認すること」
「大量アクセスで負荷をかけないこと」
サンプルコード側に最低限の制御を入れる
time.sleep(1) などの簡単なウェイトが必要
これは検証用であり、実運用ではさらに制御を入れてください


import requests
from bs4 import BeautifulSoup
import csv
from pathlib import Path

base = Path(__file__).parent

BASE = "https://shinryohoshu.mhlw.go.jp"

session = requests.Session()

# 2ページURL生成
def second_page_input(code):
    return f"{BASE}/shinryohoshu/yakuzaiMenu/doYakuzaiBunruiSearchInput&{code}"

# 2ページから Sayoリンク抽出
def extract_sayo_links(html):
    soup = BeautifulSoup(html, "html.parser")
    links = []

    for a in soup.find_all("a", href=True):
        href = a["href"]
        if "doYakuzaiBunruiSearchResultlistSayo" in href:
            full_url = BASE + href
            links.append(full_url)

    return links

# 3ページから成分・薬品名・薬価を抽出
def extract_drug_table(html):
    soup = BeautifulSoup(html, "html.parser")
    rows = []

    # 3ページの薬理作用テーブルは <tr> の連続
    for tr in soup.find_all("tr"):
        tds = [td.get_text(strip=True) for td in tr.find_all("td")]
        if len(tds) >= 9:  # 必要な列数がある行だけ採用
            rows.append(tds)

    return rows

# 成分名の空欄を補完して成分・薬品名だけ抽出
def clean_rows(rows):
    cleaned = []
    current_seibun = ""

    for row in rows:
        seibun = row[4].strip()  # 成分名
        hinmei = row[6].strip()  # 薬品名

        # 成分名が空欄なら直前の成分を使う
        if seibun == "":
            seibun = current_seibun
        else:
            current_seibun = seibun

        cleaned.append([seibun, hinmei])
        # cleaned.append([seibun, hinmei, yakka])

    return cleaned

# ————————-
# メイン処理
# ————————-

start = 10
end   = 980

codes = [f"{i:03d}" for i in range(start, end + 1)]

all_results = []

for code in codes:
    print(f"\n=== カテゴリー {code} ===")

    # 2ページ取得
    url2 = second_page_input(code)
    r2 = session.get(url2)

    if r2.status_code != 200:
        print("  2ページ取得失敗:", r2.status_code)
        continue

    # Sayoリンク抽出
    sayo_links = extract_sayo_links(r2.text)

    print(f"  Sayoリンク数: {len(sayo_links)}")

    # 3ページ取得 → 成分・薬品名抽出
    for url3 in sayo_links:
        print("    GET:", url3)
        r3 = session.get(url3)

        if r3.status_code != 200:
            print("      NG:", r3.status_code)
            continue

        rows = extract_drug_table(r3.text)
        cleaned = clean_rows(rows)

        # カテゴリーコードを付けて保存
        for seibun, hinmei in cleaned:
            all_results.append([code, seibun, hinmei])
        
        # for seibun, hinmei, yakka in cleaned:
            # all_results.append([code, seibun, hinmei, yakka])

# ————————-
# CSV 出力
# ————————-

with open(base/"薬理作用_成分_品目対応表.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["カテゴリー", "成分名", "薬品名"])
    writer.writerows(all_results)

print("\nCSV 出力完了: 薬理作用_成分_品目対応表.csv")