Selenium 4で表示したページから、ブログカードのタイトルとリンクを取得してCSVへ保存する手順です。
対象は現在のページにあるカードで、全記事の巡回やログインは行いません。
練習データと期待するCSV
練習ZIPを新しいフォルダーに展開します。
card_extract.pyとarticle-21996.pyを同じ場所に置き、CSVをExcelで開く場合に文字化けしにくいUTF-8 BOM付きで保存します。
| 入力 | 処理 | 期待する結果 |
|---|---|---|
| 6件の練習カード | URL重複と欠けたリンクを除外 | データ3行+見出し1行 |
| 相対URL b | 基準URLから絶対URLへ変換 | https://example.invalid/list/b |
| タイトル中の日本語・カンマ・絵文字 | 文字を削らずCSVの引用処理を使う | 元の文字列を保持 |
| =SUM(1,2)から始まる題名 | 先頭にアポストロフィを付ける | 表計算で数式として扱わせない |
このページの公開HTMLではmain_content内のカードを確認しました。
別テーマではクラス名が異なるので、空のCSVで成功扱いにせずセレクターを変更します。
Selenium 4の環境を用意する
2026年10月3日時点のSelenium配布要件はPython 3.10以上です。
サポートされているPythonとChromeを用意し、プロジェクト専用の仮想環境にseleniumとbeautifulsoup4をインストールします。
WindowsのPowerShellでは「py -m venv .venv」の後に「.venv/Scripts/python.exe -m pip install selenium beautifulsoup4」を実行します。
仮想環境の有効化は必須ではなく、以後もそのpython.exeを指定できます。
現行のSelenium Managerは、ドライバーを明示しない場合に必要なドライバーの管理を補助します。
初回取得に通信が必要な場合があり、会社のプロキシや古いPATH内のドライバーが原因で失敗することもあります。
カード抽出とCSV保存の共通コード
次をcard_extract.pyとして保存します。
リンクのないカードとHTTP/HTTPS以外のURLを除外し、同じURLは最初の1件だけ残します。
import csv
from pathlib import Path
from urllib.parse import urljoin, urlparse
from bs4 import BeautifulSoup
def extract_cards(source, base_url):
soup = BeautifulSoup(source, "html.parser")
rows, seen = [], set()
for card in soup.select("#main_content .p-postList__item"):
title = card.select_one(".p-postList__title")
link = card.select_one("a.p-postList__link[href]")
if title is None or link is None:
continue
label = " ".join(title.get_text(" ", strip=True).split())
target = urljoin(base_url, link["href"])
parsed = urlparse(target)
if not label or parsed.scheme not in ("http", "https") or not parsed.netloc:
continue
if target not in seen:
rows.append((label, target))
seen.add(target)
return rows
def csv_text(value):
value = str(value)
# Avoid spreadsheet formula evaluation when a title begins with =,+,-,@.
if value.lstrip().startswith(("=", "+", "-", "@")):
return "'" + value
return value
def write_csv(rows, output):
if not rows:
raise ValueError("No cards found; check the page and selector before writing.")
with Path(output).open("x", encoding="utf-8-sig", newline="") as stream:
writer = csv.writer(stream)
writer.writerow(("ID", "TITLE", "URL"))
for number, (title, target) in enumerate(rows, 1):
writer.writerow((number, csv_text(title), csv_text(target)))
待機と終了を含めたSeleniumコード
次をarticle-21996.pyとして保存し、「.venv/Scripts/python.exe article-21996.py --output cards-01.csv」で実行します。
固定秒数のsleepではなく対象要素の出現を待ち、例外でもfinallyで今回起動したブラウザーの終了を試みます。
import argparse
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from card_extract import extract_cards, write_csv
def collect(url, output):
driver = webdriver.Chrome()
try:
driver.set_page_load_timeout(30)
driver.get(url)
WebDriverWait(driver, 15).until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, "#main_content .p-postList__item")
)
)
rows = extract_cards(driver.page_source, driver.current_url)
write_csv(rows, output)
print(f"Saved {len(rows)} unique visible-page links: {output}")
finally:
driver.quit()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--url", default="https://cg-method.com/work-tools/")
parser.add_argument("--output", default="cards.csv")
args = parser.parse_args()
collect(args.url, args.output)
結果の確認とエラーの切り分け
CSVの見出しがID・TITLE・URLで、タイトルとURLが元ページの同じカードに対応しているか確認します。
再実行時は新しい出力名を指定し、既存ファイルは自動で上書きしません。
| 条件 | 結果 |
|---|---|
| TypeErrorで起動しない | webdriver.Chromeにパスを位置引数で渡していないか確認 |
| SessionNotCreatedException | Chrome・ドライバーの組合せとPATHを確認 |
| 要素待機がタイムアウト | 対象ページ・セレクター・読み込み状態を確認 |
| FileExistsError | 別の出力名を指定し元CSVを保持 |
確認済みなのはPythonによる練習HTMLの抽出・CSV保存と、明示的な模擬ドライバーによる例外時の終了処理です。
実際のSeleniumでChromeを起動する確認は未実施です。
元のサイトと入力HTMLは変更しません。
練習を戻すときは出力CSVを別名で保管し、今回の仮想環境と練習フォルダーを使わない状態に戻します。
APIの基本操作はSelenium公式の最初のスクリプトを参照してください。
最終確認:2026年10月3日。
関連する情報取得・自動化の記事
関連記事のサービス操作は、各記事で示す確認範囲と現行の仕様を確認してください。




