取得した一覧をExcelで渡したい場合は、必要な列を決めて新しいブックへ保存できます。既存の業務ブックを直接編集する前に、見出しとURLだけの表で、抽出から保存・読み直しまでをつなぎます。
Web上の文字列には、先頭が=の値なども含まれ得ます。取得した表示文字を、意図しない数式として保存しないことも、表へ出すときの確認点です。
抽出する列を二つに決める
この例の入力は次の架空HTMLです。リンクの文字を見出し、hrefを絶対URLへ変換した値をURL列にします。HTMLを文字列として用意するため、実サイトへはアクセスしません。
<main>
<a class="report" href="reports/april.html">4月報告</a>
<a class="report" href="reports/test.html">=1+1</a>
</main>
二行目の見出しは計算させずに文字列として保存する確認用です。実績や実在する資料を表したものではありません。
新しいブックへ書く
beautifulsoup4とopenpyxlが使える環境で、次のコードを実行します。保存先のreports.xlsxが既にあれば停止します。練習用フォルダーを使ってください。
from pathlib import Path
from urllib.parse import urljoin
from bs4 import BeautifulSoup
from openpyxl import Workbook, load_workbook
markup = """<main>
<a class="report" href="reports/april.html">4月報告</a>
<a class="report" href="reports/test.html">=1+1</a>
</main>"""
base_url = "https://example.test/"
soup = BeautifulSoup(markup, "html.parser")
rows = [
(link.get_text(strip=True), urljoin(base_url, link["href"]))
for link in soup.select("a.report[href]")
]
if not rows:
raise ValueError("保存する行がありません")
output = Path("reports.xlsx")
if output.exists():
raise FileExistsError(output)
wb = Workbook()
ws = wb.active
ws.title = "資料一覧"
for row in [("見出し", "URL"), *rows]:
ws.append(row)
for cell in ws[ws.max_row]:
cell.data_type = "s"
wb.save(output)
check = load_workbook(output, data_only=False, read_only=True)
try:
saved = list(check["資料一覧"].values)
assert saved[1:] == rows
print(saved)
finally:
check.close()
openpyxlは、=で始まる文字列を値として渡すと数式型にする場合があります。この表は二列とも文字列という仕様なので、書き込んだセルのdata_typeをsにしています。計算する列が必要な表へ、そのまま一律に適用する設定ではありません。
保存後に読み直す
コードではブックを保存してから読み直し、ヘッダーを除く二行が抽出結果と一致するかを確かめます。=1+1が式として保存されていないかは、読み直したセルの型も確認対象にできます。
この例はPython 3.12.10とopenpyxl 3.1.5で保存・読み直しを試し、=1+1のセルが文字列型であることも確認しました。シート名、行数、見出し、URLの一致を確認する範囲で、Excelアプリの画面は未確認です。ただし、ライブラリで読めたことだけでは、Excelアプリ上の幅、折り返し、警告などまで確認したことにはなりません。配布する前には、実際に使うアプリでも開きます。
実ページを入力にするとき
通信部分を追加する場合は、HTTPの取得失敗と抽出件数ゼロを分けます。失敗した応答やログイン画面を、資料一覧として保存しないためです。URLの結合結果も、期待するホストと方式かを確認します。
この例は新規ブックの保存に限っています。画像や図形、複雑な既存数式を持つブックを開いて保存し直すと、同じ内容を保てない場合があるため、別の検証が必要です。また、保存前の存在確認は複数プロセスからの同時書き込みを排他制御する仕組みではありません。
一覧として渡す用途なら、取得元と取得日を別列へ追加する設計もできます。列を増やす際は、日付や数値として扱う列と、外部から取得した文字列として扱う列を分けて決めます。
関連する作業
Excelブックの基本操作と、CSVで受け渡す場合の違いも合わせて確認できます。
