orangain flavor

じっくりコトコト煮込んだみかん2。知らないことを知りたい。

SeleniumとHeadless ChromeでAmazonの注文履歴を取得する

Pythonクローリング&スクレイピングの初版ではAmazonの注文履歴を取得するサンプルコードを掲載していました。増補改訂版の執筆の際、RoboBrowserのようなJavaScriptを扱えないクローラーではログインが難しくなっていたので、対象のサイトを変更しました。

せっかくなので、SeleniumとHeadless Chromeで書き直したコードを紹介します。

import os
import logging

from selenium.webdriver import Chrome, ChromeOptions, Remote
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException

logging.basicConfig(level=logging.INFO)

# 認証の情報は環境変数から取得する。
AMAZON_EMAIL = os.environ['AMAZON_EMAIL']
AMAZON_PASSWORD = os.environ['AMAZON_PASSWORD']

options = ChromeOptions()
# ヘッドレスモードを有効にするには、次の行のコメントアウトを解除する。
# options.headless = True
driver = Chrome(options=options)  # ChromeのWebDriverオブジェクトを作成する。
# Windows上の仮想マシンの場合は、前の行をコメントアウトして、
# 次の行のコメントアウトを解除する。Remote()の第1引数はゲストOSから見たホストOSのChromeDriverのURL。
# driver = Remote('http://10.0.2.2:4444', options=options)


def main():
    # 注文履歴のページを開く。
    logging.info('Navigating...')
    driver.get('https://www.amazon.co.jp/gp/css/order-history')

    # サインインページにリダイレクトされていることを確認する。
    assert 'Amazonログイン' in driver.title

    # name="signIn" というサインインフォームを埋める。
    # フォームのname属性の値はブラウザーの開発者ツールで確認できる。
    email_input = driver.find_element_by_name('email')
    email_input.send_keys(AMAZON_EMAIL)  # name="email" という入力ボックスを埋める。
    email_input.send_keys(Keys.RETURN)

    password_input = driver.find_element_by_name('password')
    password_input.send_keys(AMAZON_PASSWORD)  # name="password" という入力ボックスを埋める。

    # フォームを送信する。正常にログインするにはRefererヘッダーとAccept-Languageヘッダーが必要。
    logging.info('Signing in...')
    password_input.send_keys(Keys.RETURN)

    # ページャーをたどる。
    while True:
        assert '注文履歴' in driver.title  # 注文履歴画面が表示されていることを確認する。

        print_order_history()  # 注文履歴を表示する。

        try:
            link_to_next = driver.find_element_by_link_text('次へ')  # 「次へ」というテキストを持つリンクを取得する。
        except NoSuchElementException:
            break  # 「次へ」のリンクがない場合はループを抜けて終了する。

        logging.info('Following link to next page...')
        link_to_next.click()  # 「次へ」というリンクをたどる。

    driver.quit()  # ブラウザーを終了する。


def print_order_history():
    """
    現在のページのすべての注文履歴を表示する。
    """
    # ページ内のすべての注文履歴について反復する。ブラウザーの開発者ツールでclass属性の値を確認できる。
    for line_item in driver.find_elements_by_css_selector('.order-info'):
        order = {}  # 注文の情報を格納するためのdict。
        # 注文の情報のすべての列について反復する。
        for column in line_item.find_elements_by_css_selector('.a-column'):
            try:
                label_element = column.find_element_by_css_selector('.label')
                value_element = column.find_element_by_css_selector('.value')
                label = label_element.text
                value = value_element.text
                order[label] = value  # 注文の情報を格納する。
            except NoSuchElementException:
                pass  # ラベルと値がない列は無視する。
        print(order['注文日'], order['合計'])  # 注文の情報を表示する。

if __name__ == '__main__':
    main()

.envファイルに次のようにログイン情報を保存します。ファイルの取り扱いには気をつけてください。

AMAZON_EMAIL=<Amazon.co.jpのメールアドレス>
AMAZON_PASSWORD=<Amazon.co.jpのパスワード>

次のように実行すると、日付と価格が表示されます。

$ forego run python selenium_amazon_order_history.py
INFO:root:Navigating...
INFO:root:Signing in...
2019年9月8日 ¥ 0
2019年8月12日 ¥ 2,236
2019年8月4日 ¥ 30,000
2019年7月29日 ¥ 648
2019年7月29日 ¥ 2,592
2019年7月29日 ¥ 648
2019年7月29日 ¥ 648
2019年7月29日 ¥ 648
2019年7月29日 ¥ 648
2019年7月28日 ¥ 648
INFO:root:Following link to next page...
2019年7月28日 ¥ 648
2019年7月28日 ¥ 648
2019年7月26日 ¥ 20,807
2019年7月25日 ¥ 0
2019年6月19日 ¥ 767
2019年6月3日 ¥ 10,092
2019年5月31日 ¥ 5,054
2019年4月15日 ¥ 2,500
2019年4月7日 ¥ 1,800

増補改訂版は好評発売中です。よろしくお願いします!