【Python】Webスクレイピングの実践:ECサイトの商品一覧から情報を抽出する

Webページから特定のデータを収集する「スクレイピング」の基本フローは、requests でHTMLを取得し、BeautifulSoup で構造解析(パース)を行い、必要なタグを特定してデータを抜き出すという手順になります。

ここでは、スクレイピングの練習用に公開されているサンドボックスサイト(Books to Scrape)を対象に、商品タイトルと詳細ページへのURLを一覧で取得するコードを作成します。

目次

実行可能なサンプルコード

このコードは、架空の書店サイトから「商品名」と「リンクURL」を抽出し、コンソールに出力します。 入れ子構造(article > h3 > a)になっているタグの階層を正しく辿る方法に注目してください。

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

def scrape_product_list():
    # スクレイピング練習用サイト(書籍一覧)
    target_url = "http://books.toscrape.com/"

    print(f"Fetching: {target_url} ...")

    try:
        # 1. HTMLの取得
        response = requests.get(target_url, timeout=10)
        response.raise_for_status()

        # 2. BeautifulSoupオブジェクトの生成
        # パーサーには標準的で扱いやすい html.parser を使用(html5libでも可)
        soup = BeautifulSoup(response.text, "html.parser")

        # 3. 商品リストの特定
        # サイトの構造に合わせて親要素や繰り返し要素を特定します
        # ここでは <article class="product_pod"> が各商品のコンテナです
        products = soup.find_all("article", class_="product_pod")
        
        print(f"Found {len(products)} products.\n")

        # 4. ループ処理で各商品の情報を抽出
        for product in products:
            # articleタグの中から、さらに h3 > a タグを探します
            h3_tag = product.find("h3")
            
            if h3_tag:
                link_tag = h3_tag.find("a")
                
                # aタグが見つかった場合、テキストとhref属性を取得
                if link_tag:
                    title = link_tag.get("title")  # ツールチップ用のtitle属性を取得(省略なしの正式名称)
                    href = link_tag.get("href")    # 相対パスを取得
                    
                    # 相対パスを絶対パスに変換(実用的な処理)
                    full_url = urljoin(target_url, href)

                    print(f"Title: {title}")
                    print(f"URL:   {full_url}")
                    print("-" * 40)

    except requests.RequestException as e:
        print(f"通信エラーが発生しました: {e}")
    except Exception as e:
        print(f"予期せぬエラーが発生しました: {e}")

if __name__ == "__main__":
    scrape_product_list()

解説:スクレイピングの重要ポイント

1. findfind_all の使い分け

  • soup.find_all(...): ページ内に複数存在する要素(例:商品リスト、ニュース記事一覧)をすべて取得し、リスト形式で返します。これを for 文で回して一つずつ処理します。
  • tag.find(...): 特定した要素(親要素)の中から、さらに特定の子要素(例:その商品の中のタイトル)を1つだけ探します。

2. 属性値の取得 (.get)

リンクURLなどの属性情報は、タグのテキスト(.text)ではなく、HTMLタグの中に埋め込まれています。 <a href="catalogue/..." ...> のようなタグから href の値を取り出すには、link_tag.get("href") メソッドを使用します。

3. URLの結合 (urljoin)

取得したリンクが catalogue/page-1.html のような「相対パス」である場合、そのままではブラウザで開けません。urllib.parse.urljoin を使用して、ベースとなるURLと結合し、「絶対パス」に変換するのが一般的な処理パターンです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次