【業務自動化】Chapter4-3:動的ページをスクレイピングしよう

ながみえ

一つ前のページでは 静的ページのスクレイピング について学習しました。

今回は 動的ページのスクレイピング について見ていきましょう。

Chapter1:PythonによるExcel自動化の基本を身につけよう
Chapter2:自動化ツールを.exe化して配布しよう
Chapter3:現場で使える便利な自動化ツールを4つ作ろう
Chapter4:Webスクレイピングでデータを自動で集めよう
 ・Chapter4-1:Webスクレイピングとは何か
 ・Chapter4-2:静的ページをスクレイピングしよう
 ・Chapter4-3:動的ページをスクレイピングしよう ◁今回はここ
Chapter5:自動化ツールを作ってお金を稼ごう

動的ページとは、JavaScriptによって表示内容が後から生成されたり、ボタン操作やスクロールで新しい情報が読み込まれたりするページのことです。

このタイプのページは、前回学習した requestsBeautifulSoup だけでは正しく情報を取得できません。

この記事では、Pythonのライブラリ Selenium を使い、実際に動的ページからニュース見出しを収集し、さらに「新しい見出しだけをExcelに追加する差分更新処理」を実装します。

最終的な目標は「動的に変化するWebページから必要なデータを効率的に収集・管理する」ことです。

<<前のページ

業務自動化の記事一覧

次のページ>>

動的ページとは|スクレイピングで注意すべきページの種類

Webサイトには大きく分けて「静的ページ」と「動的ページ」があります。

静的ページはサーバーから送られたHTMLがそのまま表示されるため、requestsとBeautifulSoupだけで簡単に情報を収集できます。

一方で 動的ページ は、JavaScriptによってHTMLの内容が後から書き換えられたり、ユーザー操作によって新しい情報が読み込まれたりする仕組みを持っています。

例えば、ニュースサイトで「もっと見る」をクリックすると記事一覧が追加表示される場合や、株価・天気のようにページを開いた後に情報が更新されるケースが典型です。

このようなページでは、ソースコードを直接取得しても必要な情報が含まれていないことが多く、Seleniumのようにブラウザを自動操作できるツール を利用する必要があります。

あわせて読みたい
openpyxl使える関数・メソッド・クラス一覧【Excel自動化の基本リファレンス】
openpyxl使える関数・メソッド・クラス一覧【Excel自動化の基本リファレンス】
【Python】勉強猫がノートパソコンを前にして学習を始める様子。記事内の学習スタート用イラスト

Seleniumとは|動的ページを自動操作して情報を取得する仕組み

Selenium(セレニウム) は、Pythonをはじめ多くのプログラミング言語で利用できる「ブラウザ自動操作ライブラリ」です。

Seleniumの概要|ブラウザ自動操作・待機・要素取得の基本

通常のスクレイピングではrequestsでHTMLを取得し、BeautifulSoupで解析しますが、動的ページではJavaScriptによって後から生成される要素があるため、それだけでは情報を取り出せません。

Seleniumは実際のブラウザ(ChromeやEdgeなど)をプログラムで操作し、人間がブラウザで見ているのと同じ状態のページ を取得できるのが大きな特徴です。

Seleniumを使うと次のようなことが可能になります。

  • JavaScriptで生成された情報を含めて取得できる
  • ボタンのクリックやスクロールなどの操作を自動化できる
  • ログインが必要なページで、フォーム入力やログイン処理を再現できる

このようにSeleniumは「人間の操作をそのままPythonに任せる」イメージで使えるため、動的ページのスクレイピングでは必須のツールとなります。

Seleniumの代表的な機能一覧

Seleniumを使うときによく利用するクラスや関数を整理しておきましょう。

これらを押さえておくと、動的ページのスクレイピングがスムーズに進みます。

クラス / 関数説明
webdriver.Chrome(options=...)Chromeブラウザを起動する。
options を指定することで「画面を表示しない(ヘッドレスモード)」などの設定が可能。
driver.get(url)指定したURLにアクセスする。
driver.implicitly_wait(seconds)ページ内の要素が出てくるまで最大で指定秒数待機する。
動的ページの読み込みに便利。
driver.find_element(By.XXX, "値")ページ内から最初に一致する要素を取得。
By.IDBy.TAG_NAME などを指定できる。
driver.find_elements(By.XXX, "値")条件に合うすべての要素をリストで取得。
ニュース記事のリンク一覧などを収集する場合に利用。
element.text取得した要素からテキストを取り出す。
element.get_attribute("href")要素の属性値(例:リンク先URL)を取得する。
driver.quit()ブラウザを閉じる。処理終了時には必ず呼び出す。

これらの基本操作を組み合わせることで、「ページを開く → 要素を探す → 情報を取り出す → 結果を保存する」という流れを自動化できます。

サンプルスクリプトの紹介|取得データをopenpyxlでExcelに保存

ここからは、実際に動的ページを対象にしたサンプルスクリプトを紹介します。

今回の例では、ニュースサイト(Yahoo!ニュース)を対象に、Seleniumを使って最新の見出しを収集し、Excelに保存する仕組みを作ります。

このスクリプトでは、前回の静的ページ版に加えて 差分更新機能 を取り入れており、既に保存済みの見出しと照合して新しい記事だけを追加保存できるようになっています。

このコードでできること|ニュース見出し取得と重複回避・差分追加

サンプルスクリプトを実行すると、次のような処理が自動的に行われます。

  1. 動的ページにアクセス
    SeleniumでChromeブラウザを起動し、ニュースサイトのトップページにアクセスします。
  2. JavaScriptで生成された要素を含めて取得
    ページ読み込みを待機し、ニュース見出しのリンクやテキストを抽出します。
  3. 差分チェック
    既にExcelに保存されている記事タイトルと比較し、新しいものだけをリストアップします。
  4. Excelに保存
    openpyxl を使って新しい記事をExcelに追加します。
  5. 通知
    追加された件数をポップアップで知らせ、保存先も表示します。

このように「動的に変化するページ」からでも効率的に情報を収集でき、さらに差分更新で重複を防げるのがポイントです。

サンプルスクリプトの紹介

以下が、動的ページからニュース見出しを収集し、Excelに差分更新して保存するサンプルスクリプトです。

import openpyxl, pathlib, sys
from tkinter import messagebox
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
# openpyxl: Excelファイルの操作
# pathlib: ファイルやフォルダのパス操作
# sys: 実行環境の判定や終了処理
# tkinter.messagebox: エラーや完了メッセージをポップアップで表示
# selenium: ブラウザを自動操作して、動的ページを扱うためのライブラリ

# === 実行環境に応じた基準ディレクトリ ===
if getattr(sys, 'frozen', False):
    BASE_DIR = pathlib.Path(sys.executable).parent
else:
    BASE_DIR = pathlib.Path(__file__).parent

file_path = BASE_DIR / "workbooks"
file_path.mkdir(exist_ok=True)

output_file = file_path / "news_dynamic.xlsx"

# === Seleniumの設定 ===
options = Options()
options.add_argument("--headless")  # ブラウザ画面を表示せずに処理(ヘッドレスモード)
driver = webdriver.Chrome(options=options)  # Chromeブラウザを起動

# === 動的ページのURL ===
url = "https://news.yahoo.co.jp/"  # サンプルとしてYahoo!ニュースを使用
try:
    # 指定したページを開く
    driver.get(url)
    # 要素が出るまで最大5秒間待機(ページ読み込みが遅い場合の対策)
    driver.implicitly_wait(5)
except Exception as e:
    # ページが開けなかった場合はエラーメッセージを表示して終了
    messagebox.showerror("エラー", f"ニュースページを開けませんでした\n{e}")
    driver.quit()
    sys.exit(1)

# === ニュース見出しを取得 ===
# ページ内のリンク(<a>タグ)をすべて取得
news_elements = driver.find_elements(By.TAG_NAME, "a")
new_data = []
for elem in news_elements:
    # <a>タグのテキスト部分(リンク文字列)を取得
    title = elem.text.strip()
    # リンク先のURLを取得
    link = elem.get_attribute("href")

    # タイトルとリンクが存在し、かつYahooニュース内の記事のみを抽出
    if title and link and "news.yahoo.co.jp" in link:
        new_data.append((title, link))

# 使い終わったブラウザを閉じる
driver.quit()

# ニュースが1つも取得できなかった場合はエラーメッセージを出して終了
if not new_data:
    messagebox.showerror("エラー", "ニュース見出しが取得できませんでした")
    sys.exit(1)

# === 既存ファイルの読み込み(差分更新用) ===
existing_titles = set()  # すでに保存済みの見出しタイトルを格納する集合

if output_file.exists():
    # 既存のExcelファイルを開く
    book = openpyxl.load_workbook(output_file)
    sheet = book.active
    # 2行目以降(データ部分)の「タイトル列」を読み込み、重複判定用に格納
    for row in sheet.iter_rows(min_row=2, values_only=True):
        if row[0]:
            existing_titles.add(row[0])
else:
    # Excelファイルが存在しない場合は新しく作成
    book = openpyxl.Workbook()
    sheet = book.active
    sheet.title = "ニュース一覧"
    # 1行目にヘッダーを追加
    sheet.append(["タイトル", "リンク"])

# === 新しいニュースのみを追加 ===
added_count = 0  # 新しく追加された件数をカウント
for title, link in new_data:
    # すでに存在するタイトルは追加しない(差分更新)
    if title not in existing_titles:
        sheet.append([title, link])
        added_count += 1

# === 保存 ===
book.save(output_file)

# === 完了メッセージ ===
if added_count > 0:
    # 新しいニュースが追加された場合は件数と保存先を通知
    messagebox.showinfo("完了", f"{added_count} 件の新しいニュースを追加しました\n保存先: {output_file}")
else:
    # 新しいニュースがなかった場合の通知
    messagebox.showinfo("完了", "新しいニュースはありませんでした")

このコードを実行することで、最新ニュースを自動的に収集し、すでに保存済みのものと重複しないようにExcelに追記できます。

コード解説|Seleniumの待機・要素取得とopenpyxlでのExcel
書き込み

このサンプルスクリプトは「Seleniumでニュース見出しを取得 → 既存Excelと比較して差分を追加 → 保存」という流れで動作します。

特に重要なポイントを分解して説明します。

Seleniumで動的ページを操作する

options = Options()
options.add_argument("--headless")  # 画面を表示せず実行
driver = webdriver.Chrome(options=options)

driver.get(url)
driver.implicitly_wait(5)
  • webdriver.Chrome でChromeブラウザを自動起動します。
  • --headless オプションを指定しているため、ブラウザの画面を表示せずバックグラウンドで処理できます。
  • driver.get(url) で対象ページにアクセス。
  • implicitly_wait(5) は要素が読み込まれるまで最大5秒待機する設定です。
    動的ページはJavaScriptで要素が後から生成されるため、この待機がないと情報を取りこぼす可能性があります。
news_elements = driver.find_elements(By.TAG_NAME, "a")
for elem in news_elements:
    title = elem.text.strip()
    link = elem.get_attribute("href")
  • find_elements を使って <a> タグをすべて取得します。
  • elem.text でリンクテキスト(ニュース見出し)を、elem.get_attribute("href") でリンク先URLを取得できます。

この流れにより、JavaScriptで生成された要素を含めて確実に取得できる のがSeleniumの強みです。

差分更新で重複を防ぐ

existing_titles = set()
if output_file.exists():
    book = openpyxl.load_workbook(output_file)
    sheet = book.active
    for row in sheet.iter_rows(min_row=2, values_only=True):
        if row[0]:
            existing_titles.add(row[0])
  • すでにExcelファイルが存在する場合、1行目のヘッダーを除いて「タイトル列」をすべて読み込みます。
  • その結果を set(集合型) に格納し、すでに保存済みの見出し一覧として保持します。
for title, link in new_data:
    if title not in existing_titles:
        sheet.append([title, link])
  • 新しく取得したニュース見出しをループし、既存タイトルに含まれていない場合だけ追加 します。
  • これにより、毎回スクレイピングしても「新しい記事のみExcelに追加」され、重複保存を防げます。

完了メッセージ

if added_count > 0:
    messagebox.showinfo("完了", f"{added_count} 件の新しいニュースを追加しました\n保存先: {output_file}")
else:
    messagebox.showinfo("完了", "新しいニュースはありませんでした")
  • 新しく追加した件数をユーザーに通知します。
  • 新しい記事がなければ「新しいニュースはありませんでした」と表示され、毎日の実行でも状況がわかりやすくなります。

まとめ

この記事では、動的ページのスクレイピング をテーマに、Seleniumを使ってニュース見出しを収集し、Excelに差分更新する方法を学びました。

この仕組みによって、毎日ニュースサイトを開いて手作業でコピーしていた作業を自動化し、しかも「新しい情報だけを追記する」形で効率よく管理できるようになりました。

ここまで学んだことで、スクレイピングを「使えるスキル」として実務に応用する準備が整いました。手作業を自動化できるようになったのは、大きな一歩です。

ぜひ「自分の業務や日常の情報収集に応用できないか?」を考えながら、今回のコードをアレンジしてみてください。

もっと分かりやすい学習サイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいExcel自動化学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

業務自動化の記事一覧

次のページ>>

記事URLをコピーしました