【Webスクレイピング入門 第2回】実践!ニュースサイトの見出しとリンクを自動収集してCSVに保存しよう 💻

「Webページの基本的な情報の抜き出し方は分かったけど、もっと複雑なサイトではどうすればいいの?」
「Webサイトのどの部分がどのHTMLタグなのか、簡単に見分ける方法はないの?」
「スクレイピングで集めたデータを、Excelで開けるようにファイルとして保存したい!」

こんにちは! Webスクレイピング探検隊、隊長のPythonistaです! 前回の第1回では、requestsBeautifulSoup4を使って、Webページから情報を取得する基本的な3ステップ(取得→解析→抽出)と、最も重要なマナーについて学びましたね。

シリーズ第2回となる今回は、いよいよ**より実践的なスクレイピング**に挑戦します! 架空のニュースサイトを題材に、プロのエンジニアも使う「ブラウザの開発者ツール」を駆使してHTMLの構造を分析し、複数の記事の見出しとリンクを一括で抽出し、その結果をCSVファイルに保存するまでの一連のワークフローをマスターします。この記事を終える頃には、あなたは単にデータを抽出するだけでなく、それを整理・保存するまでの流れを自動化できるようになっていますよ!


1. 準備:モジュールのインポートと今回のターゲット

まずは、今回使用するモジュールをインポートしておきましょう。データをCSVファイルに保存するために、これまでのシリーズで学んだcsvモジュールも使います。

import requests
from bs4 import BeautifulSoup
import csv
import os

今回のターゲット:架空のニュースサイト「TechTrend Today」

実際のニュースサイトをスクレイピングの対象にすると、サイトの構造が急に変わったり、利用規約で禁止されていたりする場合があります。そこで今回は、練習用に以下のようなシンプルなHTMLを用意しました。この内容を、お使いのテキストエディタでmock_news.htmlという名前で保存し、Pythonスクリプトと同じディレクトリに置いてください。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>TechTrend Today</title>
</head>
<body>
    <h1>TechTrend Today - 最新技術ニュース</h1>
    <div class="article-list">
        <div class="article-entry">
            <h2 class="article-title"><a href="/news/001">Python、次期バージョンで画期的な新機能を追加か</a></h2>
            <p class="article-meta">2025年6月15日</p>
        </div>
        <div class="article-entry">
            <h2 class="article-title"><a href="/news/002">AIが描く未来の都市デザインとは</a></h2>
            <p class="article-meta">2025年6月14日</p>
        </div>
        <div class="article-entry">
            <h2 class="article-title"><a href="/news/003">量子コンピュータ、実用化への大きな一歩</a></h2>
            <p class="article-meta">2025年6月14日</p>
        </div>
    </div>
</body>
</html>

このHTMLファイルをブラウザで開くと、ニュースサイトのように見えるはずです。私たちの目標は、この中から3つの記事の「タイトル」と「リンク先URL」を抜き出すことです。


2. ステップ1:ターゲットの分析(ブラウザ開発者ツールの使い方)

スクレイピングを成功させるための最も重要なスキルが、この**ターゲット分析**です。コードを書き始める前に、まずブラウザで目的のページのHTML構造を調査します。

  1. 先ほど作成したmock_news.htmlファイルを、お使いのWebブラウザ(ChromeやFirefoxなど)で開きます。
  2. ページに表示されている最初の記事タイトル(例: 「Python、次期バージョンで...」)の上で**右クリック**し、メニューから**「検証」**または**「要素を調査」**を選択します。
  3. 画面の右側または下側に、Webサイトの裏側(HTMLコード)を表示する「開発者ツール」が開きます。右クリックした部分に対応するHTMLコードがハイライトされているはずです。


ハイライトされた部分をよく見てみましょう。

<h2 class="article-title"><a href="/news/001">Python、次期バージョンで画期的な新機能を追加か</a></h2>

この構造から、以下のことが分かります。

  • 記事のタイトルは、タグの中にテキストとして含まれている。
  • そのタグは、

    タグの中にあり、そのh2タグにはarticle-titleというクラス名が付いている。
  • 記事のリンク先URLは、タグのhref属性の値である。

この情報をもとに、目的のデータを抽出するための「CSSセレクタ」を組み立てることができます。今回の場合、目的のタグを指定するCSSセレクタは**h2.article-title a** となります。これは「article-titleというクラスを持つh2タグの**中にある**aタグ」という意味です。

この「CSSセレクタを見つけ出す」作業が、スクレイピングの成否を分ける鍵となります。


3. ステップ2:スクリプトの実装とデータの構造化

分析が終われば、あとはコードを書くだけです。今回は、処理を関数に分けて整理してみましょう。

import requests
from bs4 import BeautifulSoup
import csv

def extract_articles_from_html(html_content):
    """HTMLコンテンツを受け取り、記事のタイトルとURLのリストを返す"""
    soup = BeautifulSoup(html_content, 'lxml')
    
    # CSSセレクタを使って、目的のaタグを全て見つけ出す
    article_links = soup.select('h2.article-title a')
    
    extracted_data = []
    if not article_links:
        print("記事が見つかりませんでした。")
        return extracted_data

    for link in article_links:
        title = link.text.strip() # テキストを取得し、前後の空白を削除
        url = link.get('href')   # href属性の値を取得
        
        # データを辞書としてまとめる
        article_info = {
            'title': title,
            'url': url
        }
        extracted_data.append(article_info)
        
    return extracted_data

def save_to_csv(data_list, filename):
    """辞書のリストを受け取り、CSVファイルに保存する"""
    if not data_list:
        return # データがなければ何もしない

    # ヘッダー行(CSVの1行目)をデータのキーから取得
    fieldnames = data_list[0].keys()
    
    try:
        with open(filename, mode='w', encoding='utf-8-sig', newline='') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            
            writer.writeheader() # ヘッダー行を書き込む
            writer.writerows(data_list) # 全てのデータ行を書き込む
            
        print(f"データが '{filename}' に保存されました。")
    except Exception as e:
        print(f"ファイル保存中にエラーが発生しました: {e}")


# --- メインの処理 ---
if __name__ == '__main__':
    html_file_path = 'mock_news.html'
    output_csv_path = 'news_headlines.csv'
    
    try:
        # ローカルのHTMLファイルを読み込む
        with open(html_file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # HTMLから記事データを抽出
        articles = extract_articles_from_html(content)
        
        # 抽出したデータをCSVに保存
        save_to_csv(articles, output_csv_path)

    except FileNotFoundError:
        print(f"エラー: ファイル '{html_file_path}' が見つかりません。")
    except Exception as e:
        print(f"予期せぬエラーが発生しました: {e}")

このスクリプトを実行すると、同じディレクトリにnews_headlines.csvというファイルが作成され、中には抽出した記事のタイトルとURLが保存されているはずです。Excelなどで開いて確認してみてください!


4. まとめと次回予告

今回は、Webスクレイピング入門の第2回として、より実践的な内容に挑戦しました。

  • ブラウザの開発者ツールを使って、目的のデータがHTMLのどの部分にあるかを特定する方法。
  • 見つけた情報をもとにCSSセレクタを組み立て、BeautifulSoupで目的の要素群を正確に抜き出すテクニック。
  • 抽出した複数のデータを、扱いやすい辞書のリストとして構造化する方法。
  • これまでのシリーズで学んだcsvモジュールを使って、収集したデータをファイルとして保存する一連の流れ。

これで、あなたは単一のWebページから体系的に情報を収集し、再利用可能な形で保存するスキルを身につけました。これは、データ収集の自動化における非常に大きな一歩です。

さて、1ページ分の記事は収集できるようになりました。しかし、実際のニュースサイトには何十、何百ものページがありますよね。「次のページへ」のリンクをたどって、全てのページの情報を自動で集めることはできないのでしょうか?

次回、第3回(応用・完結編)では、複数ページを自動で巡回する「クローリング」のテクニックを学びます。そして、クローリングで収集した大量のデータを、今度はPandasとMatplotlibを使って分析・可視化する、というデータサイエンスプロジェクトの全工程を体験します!お楽しみに!

その他の投稿はこちら

コメント

このブログの人気の投稿

タイトルまとめ

これで迷わない!WindowsでPython環境構築する一番やさしい方法 #0

【Python標準ライブラリ完結!】11の冒険をありがとう!君のPython力が飛躍する「次の一歩」とは? 🚀