【Pythonスクレイピング実践】Amazonの商品情報を自動収集するツールの作り方(※学習・研究目的限定)

「複数のAmazon商品の価格や在庫状況を、自動でチェックしたい…」
「Webスクレイピングの基本は学んだけど、Amazonみたいな複雑なサイトから情報を抜き出すにはどうすればいいの?」
「Pythonで実用的なデータ収集ツールを作ってみたい!」

こんにちは! Pythonプログラミング探検隊、隊長のPythonistaです! これまでWebスクレイピング入門シリーズなどで、requestsBeautifulSoup4を使った基本的な情報収集の方法を学んできましたね。

今回は、その集大成となる実践プロジェクトとして、Amazonの商品ページから「商品名」「価格」「在庫情報」「プライム対象か」といった情報を自動で抽出し、CSVファイルにまとめるツールの作り方を、ステップバイステップで徹底解説します。より複雑なWebサイトに対応するための、ヘッダー情報の書き換えや、特定の属性を持つHTML要素の探し方など、一歩進んだテクニックも登場します。このプロジェクトを通して、あなたのスクレイピングスキルを次のレベルへと引き上げましょう!


【超重要】Amazonの利用規約とスクレイピングに関する注意点

本題に入る前に、非常に重要な注意点があります。

Amazonの利用規約では、プログラムによる自動的なデータ収集(スクレイピング)は明確に禁止されています。

したがって、この記事で紹介するスクリプトを、Amazonの利用規約に違反する形で無断かつ継続的に実行することは絶対に避けてください。この記事の目的は、あくまで教育・研究目的であり、現代の複雑なWebサイトがどのようなHTMLで構成されているか、そしてそこから情報を抽出するためのプログラミング技術(特にHTMLの解析、CSSセレクタ、エラーハンドリング)を学ぶことにあります。

ここで学ぶ技術を、利用が許可されているサイトや、ご自身が管理するサイト、あるいはAPIが提供されているサービスなどで、ルールとマナーを守って活用してください。


1. プロジェクトの概要と準備

1.1. 今回作るツールの機能

このツールは、以下の機能を持つことを目標とします。

  1. urls.csvというファイルに記載された、複数のAmazon商品ページのURLを読み込む。
  2. 各URLにアクセスし、「商品名」「価格」「在庫」「プライム対象か」の情報を抽出する。
  3. 抽出した全商品の情報を、output.csvという新しいCSVファイルに書き出す。

1.2. 必要なライブラリの準備

これまでのシリーズでもおなじみのライブラリを使います。インストールがまだの場合は、ターミナルやコマンドプロンプトで実行してください。

pip install requests beautifulsoup4 lxml

1.3. 入力ファイルの準備 (urls.csv)

まず、スクレイピングしたいAmazon商品ページのURLをリストアップしたCSVファイルを作成します。以下の内容でurls.csvという名前のファイルを作成し、これから作るPythonスクリプトと同じディレクトリに保存してください。

url
https://www.amazon.co.jp/dp/XXXXXXXXXX
https://www.amazon.co.jp/dp/YYYYYYYYYY
https://www.amazon.co.jp/dp/ZZZZZZZZZZ

XXXXXXXXXXの部分は、実際の商品ページのURLにあるASIN(Amazon Standard Identification Number)などに置き換えてください。


2. スクリプトの全体像(完成コード)

まずは、今回作成するスクリプトの全体像を見てみましょう。各部分の詳しい解説はこの後でじっくり行います。

import csv
import requests
from bs4 import BeautifulSoup
import time
import os

def get_product_info(url):
    """指定されたAmazonのURLから商品情報を取得する関数"""
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Accept-Language': 'ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7'
    }

    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'lxml')

        # --- 情報の抽出 ---
        title_element = soup.find(id='productTitle')
        title = title_element.get_text(strip=True) if title_element else '取得不可'

        price_element = soup.select_one('.a-price-whole')
        price = price_element.get_text(strip=True) if price_element else '取得不可'
        
        availability_element = soup.find(id='availability')
        availability = availability_element.get_text(strip=True) if availability_element else '取得不可'
        
        prime_element = soup.select_one('[aria-label="Amazon Prime"]')
        is_prime = 'はい' if prime_element else 'いいえ'
        
        return {
            'title': title,
            'price': price,
            'availability': availability,
            'is_prime': is_prime
        }
    except requests.exceptions.RequestException as e:
        print(f"エラー: {url} へのアクセスに失敗しました。 {e}")
        return None
    except Exception as e:
        print(f"エラー: {url} の情報解析中に予期せぬエラーが発生しました。 {e}")
        return None

def main():
    """メイン処理。CSVを読み込み、スクレイピングを実行し、結果を新しいCSVに書き出す。"""
    input_csv_path = 'urls.csv'
    output_csv_path = 'output.csv'

    print(f"'{input_csv_path}' からURLを読み込んでいます...")
    try:
        with open(input_csv_path, mode='r', encoding='utf-8') as infile:
            reader = csv.DictReader(infile)
            urls = [row['url'] for row in reader]
    except FileNotFoundError:
        print(f"エラー: '{input_csv_path}' が見つかりません。ファイルを作成してください。")
        return

    print(f"{len(urls)}件のURLを処理します...")
    results = []
    for i, url in enumerate(urls):
        print(f"[{i+1}/{len(urls)}] 処理中: {url}")
        info = get_product_info(url)
        if info:
            results.append({
                '商品名': info['title'],
                '価格': info['price'],
                '在庫': info['availability'],
                'プライム対象': info['is_prime'],
                'URL': url
            })
        # サーバーに負荷をかけないためのマナー
        time.sleep(2) # 2秒待機

    if not results:
        print("処理できるデータがありませんでした。")
        return

    print(f"処理が完了しました。'{output_csv_path}' に結果を書き出します。")
    with open(output_csv_path, mode='w', newline='', encoding='utf-8-sig') as outfile:
        fieldnames = ['商品名', '価格', '在庫', 'プライム対象', 'URL']
        writer = csv.DictWriter(outfile, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(results)
    print("すべての処理が完了しました。")

if __name__ == '__main__':
    main()

3. コードの仕組みを徹底解説!

このスクリプトがどのように動作しているのか、重要な部分をステップバイステップで見ていきましょう。

3.1. get_product_info()関数:スクレイピングの心臓部

この関数が、1つのURLから情報を抽出するメインの処理を担っています。

・リクエストヘッダーの偽装

headers = {
    'User-Agent': '...',
    'Accept-Language': 'ja-JP,ja;...'
}
response = requests.get(url, headers=headers)

多くのWebサイトは、プログラムからの単純なアクセスをブロックすることがあります。そこで、headers情報を送信することで、通常のWebブラウザからのアクセスであるかのように「見せかける」ことができます。特にUser-Agentは、どのようなブラウザからアクセスしているかを示す重要な情報です。

・情報の抽出:CSSセレクタと属性セレクタの活用

Amazonのような巨大なサイトのHTMLは非常に複雑です。ブラウザの開発者ツールを駆使して、目的の要素を特定するための正確な「住所」(セレクタ)を見つけ出す必要があります。

  • 商品名: soup.find(id='productTitle')
    これは比較的簡単です。商品タイトルはid="productTitle"という一意のIDを持つ要素に含まれていることが多いです。
  • 価格: soup.select_one('.a-price-whole')
    価格はa-price-wholeというクラス名を持つ要素に含まれていることが多いです。select_oneは、条件に一致する最初の要素を見つけます。
  • プライム対象か: soup.select_one('[aria-label="Amazon Prime"]')
    これは少し高度なテクニックです。プライムのロゴアイコンには、特定のclassidが付いていない場合があります。しかし、aria-label="Amazon Prime"という属性を持っていることが多いです。[属性名="属性値"]という書き方は「属性セレクタ」と呼ばれ、特定の属性を持つ要素をピンポイントで探し出すのに非常に強力です。この要素が見つかればプライム対象、見つからなければ対象外、と判定しています。

3.2. main()関数:全体の流れを制御

main()関数は、プログラム全体の流れを制御しています。

  1. urls.csvcsv.DictReaderで読み込み、URLのリストを作成します。
  2. forループでURLを1件ずつ取り出し、get_product_info()関数を呼び出してスクレイピングを実行します。
  3. time.sleep(2): ループの最後に2秒間の待機を入れています。これは、相手のサーバーに過度な負荷をかけないための非常に重要なマナーです。この時間を短くしたり、削除したりしないでください。
  4. 全ての結果をresultsリストに集約します。
  5. 最後に、csv.DictWriterを使って、収集した全データをoutput.csvに書き出します。

4. スクリプトの使い方と注意点

  1. 上記のコードをamazon_scraper.pyなどの名前で保存します。
  2. 同じディレクトリに、調べたいAmazon商品ページのURLを記述したurls.csvファイルを作成します。
  3. ターミナルを開き、スクリプトを実行します。
    python amazon_scraper.py
  4. 処理が完了すると、output.csvというファイルが生成され、中に商品情報が書き出されています。Excelなどで開いて確認してみてください。

【重ねての注意】
このスクリプトは、あくまでHTMLの構造を学習するためのものです。Amazonの利用規約を遵守し、サイトに負荷をかけるような頻繁な実行や、収集したデータの商用利用、再配布などは絶対に行わないでください。


まとめ:実践的なスクレイピング技術で、データ収集を次のレベルへ

今回は、これまでの知識を総動員し、非常に複雑なWebサイトであるAmazonの商品ページから、複数の情報を自動で収集する実践的なプロジェクトに挑戦しました。

  • リクエストヘッダーを設定し、より人間に近いアクセスを行う方法。
  • ブラウザの開発者ツールを駆使して、複雑なHTMLから目的の要素を特定する考え方。
  • IDセレクタ、クラスセレクタ、そして強力な属性セレクタの使い分け。
  • 複数のURLを巡回し、結果をCSVにまとめる、一連のデータ収集パイプラインの構築。
  • サーバーに負荷をかけないためのtime.sleep()の重要性。

これらのテクニックは、Amazon以外の多くのWebサイトをスクレイピングする際にも応用できる、非常に価値のあるスキルです。ぜひ、ルールとマナーを守った上で、様々なサイトの構造を分析し、データ収集のスキルを磨いていってください!

その他の投稿はこちら

コメント

このブログの人気の投稿

タイトルまとめ

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

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