PythonでAmazon商品をスクレイピング 2

Amazonスクレイピングアイキャッチ Uncategorized

前回PythonでAmazon商品をスクレイピングする記事を書きました。一部要素が取得できないケースがあったりしたので、そのアップデートと、1ページ分を丸々取得する方法を今回はご紹介します。

前回の記事

Pythonを学習したいという方はこちらから。

今回もPython + Seleniumで、キーワードを入力するとAmazon商品のURLとタイトル、評価数を取得するスクリプトの紹介です。評価数が表示されない商品もあるので、そちらはスキップして次の商品に進みます。

はじめに

前回の記事同様、スクレイピング先のサイトのUI(ざっくりと記載すると画面)が変わると、要素も変わるので、取得できなくなる可能性があることをはじめにお伝えします。こちらの記事は2023年2月4日時点の記事です。

また、スクレイピングのための準備は前回の記事を参考にしてください。

早速コードの紹介

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
import chromedriver_binary
import time
import datetime
import csv
import os

base_url = "https://www.amazon.co.jp/"

os.makedirs("./output/", exist_ok=True)

dt_now = datetime.datetime.now()
output_file_date = dt_now.strftime('%Y%m%d_%H%M')

output_file = "./output/Amazon_data_{}.csv".format(output_file_date)
with open(output_file,'w',encoding='utf-8-sig',newline='') as f:
    writer = csv.DictWriter(f,["Link URL","title","star member num"])
    writer.writeheader()

class SaveItem:
    def __init__(self,link,title,star_mem,output_file):
        self.link = link
        self.title = title
        self.star_mem = star_mem
        self.output_file = output_file

    def csvoutput(self):
        contents = {"Link URL":self.link,"title":self.title,"star member num":self.star_mem}
        with open(self.output_file,'a', encoding='utf-8-sig',newline='') as f:
            fieldnames = ["Link URL","title","star member num"]
            writer = csv.DictWriter(f,fieldnames=fieldnames)
            writer.writerow(contents)


search_text = input("検索ワードを入力してください:")

options = webdriver.ChromeOptions()
#Web USB Bluetooth等のエラー出力を除外
options.add_argument('--log-level=3')
options.add_argument('--headless')


driver = webdriver.Chrome(options=options)

driver.get(base_url)
driver.maximize_window()

WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.CSS_SELECTOR,".nav-input.nav-progressive-attribute"))
)

element = driver.find_element(by=By.CSS_SELECTOR, value=".nav-input.nav-progressive-attribute")
element.send_keys(search_text)

search_click = driver.find_element(by=By.CSS_SELECTOR, value=".nav-input.nav-progressive-attribute[value="'検索'"]")
search_click.click()

WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.CSS_SELECTOR,".s-search-results"))
)

search_num = 0

while driver.find_elements(by=By.CSS_SELECTOR, value=("[data-index=" + "'" + str(search_num + 1) + "'" + "]")):
    check_ele = driver.find_element(by=By.CSS_SELECTOR, value=("[data-index=" + "'" + \
        str(search_num + 1) + "'" + "]")).get_attribute("class")

    if "s-widget-spacing-large" in check_ele:
        pass
    else:
        if driver.find_elements(by=By.CSS_SELECTOR, value=("[data-index=" + "'" + str(search_num + 1) + \
            "'" + "]" + "[data-component-type="+ "'" + "s-search-result" + "'" + "]")):
        
            main_element = driver.find_element(by=By.CSS_SELECTOR, value=\
                ".s-main-slot.s-result-list.s-search-results.sg-row")
            value = "[data-index=" + "'" + str(search_num + 1) + "'" + "]"
            search_element = main_element.find_element(by=By.CSS_SELECTOR, value=value)    
            if search_element.find_elements(by=By.CSS_SELECTOR, value=".a-link-normal.s-no-outline"):

                get_link = search_element.find_element(by=By.CSS_SELECTOR, value=".a-link-normal.s-no-outline")
                link = get_link.get_attribute("href")

                get_title = search_element.find_element(by=By.CSS_SELECTOR,value=".s-title-instructions-style")
                title = get_title.find_element(by=By.CSS_SELECTOR,value=".a-text-normal").text
                print("title is ",title)
                if search_element.find_elements(by=By.CSS_SELECTOR,value=\
                    ".a-section.a-spacing-none.a-spacing-top-micro"):
                    get_attr = search_element.find_element(by=By.CSS_SELECTOR,value=\
                        ".a-section.a-spacing-none.a-spacing-top-micro")
                    if get_attr.find_elements(by=By.CSS_SELECTOR,value=".a-size-base.s-underline-text"):
                        get_star_member = get_attr.find_element(by=By.CSS_SELECTOR,value=\
                            ".a-size-base.s-underline-text").text
                    else:
                        get_star_member = None
                else:
                    pass
                item_data = SaveItem(link,title,get_star_member,output_file)
                item_data.csvoutput()

            else:

                if search_element.find_elements(by=By.CSS_SELECTOR,value=".sg-col-inner"):
                    print("hit")

        else:
            break
    time.sleep(1)
    search_num = search_num + 1


driver.close()

実行方法と結果

このスクリプトを実行すると

検索ワードを入力してください:

と表示されるので、検索キーワードを入力してください。
実行画面に「title is xxx」という形で商品のタイトルが表示されます。
「output」というフォルダに「Amazon_data_yyyyMMdd_hhmm.csv」というcsvファイルが作成されます。
csvはUTF-8(BOMあり)の形式です。
「商品のURL(Link URL)」「タイトル(title)」「評価数(star member num)」が出力されます。

プログラミングを学習して業務に活用したい方はこちらからどうぞ

補足

「SaveItem」クラスはCSVとして1行ずつ保存する部分のコードです。

参考になったら幸いです。

コメント

タイトルとURLをコピーしました