selenium・pythonを使ってAmazonの領収書を自動取得する方法〜シリーズ3:コード解説(kioskオプション,保存ディレクトリの指定, actionChains)〜

Python
この記事は約16分で読めます。

さて、またまたAmazonの領収書をseleniumを使ってPDF保存する方法のシリーズです。

前回記事で、実際のコード一覧と使用上の注意点を説明してきました。今回はこのコードの解説になるので、まだ前回分をみていない方は、以下のリンクから先にご確認ください。

それでは、実際のコード解説に行ってみましょう。すべてを説明するとあまりに長くなってしまうので、今回はコードの中で特徴的な部分として以下の3つを説明していきます。

  • kioskオプションを利用したPDF保存方法
  • seleniumでの保存ディレクトリの指定方法
  • actionchainsを利用した右クリックなどの実行方法
スポンサーリンク
もしも_楽天

実際のコードのおさらい

まずは、参照目的ですが、前回のせたコードを一括再掲載しておきます。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.expected_conditions import visibility_of
from pathlib import Path
import bs4,requests,time,os,sys,random,re,csv,json

url = "https://www.amazon.co.jp/ap/signin?_encoding=UTF8&openid.assoc_handle=jpflex" \
      "&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select" \
      "&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select" \
      "&openid.mode=checkid_setup&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0" \
      "&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0" \
      "&openid.pape.max_auth_age=0&openid.return_to=https%3A%2F%2Fwww.amazon.co.jp%2Fgp%2Fyourstore%2Fhome%3Fie%3DUTF8%26action" \
      "%3Dsign-out%26path%3D%252Fgp%252Fyourstore%252Fhome%26ref_%3Dnav_AccountFlyout_signout%26signIn%3D1%26useRedirectOnSuccess%3D1"

e_mail = "emailアドレス"
password = "パスワード"
downloadPath = "DLファイルの絶対パス"


options = webdriver.ChromeOptions()
settings = {"recentDestinations": [{"id": "Save as PDF",
                                    "origin": "local",
                                    "account": ""}],
            "selectedDestinationId": "Save as PDF",
            "version": 2}
prefs = {'printing.print_preview_sticky_settings.appState': json.dumps(settings),'savefile.default_directory':downloadPath}
options.add_experimental_option('prefs', prefs)
options.add_argument('--kiosk-printing')


wd = webdriver.Chrome("chrome_driverのパス", options=options)
wd.get(url)
time.sleep(1)

"""
メールアドレスの入力+送信
"""
email_box = wd.find_element_by_xpath('//*[@id="ap_email"]')
email_box.send_keys(e_mail)
emai_box_submit = wd.find_element_by_xpath('//*[@id="continue"]')
emai_box_submit.click()
time.sleep(1)

"""
passwordの入力
"""
password_box = wd.find_element_by_xpath('//*[@id="ap_password"]')
password_box.send_keys(password)
password_box_submit = wd.find_element_by_xpath('//*[@id="signInSubmit"]')
password_box_submit.click()
time.sleep(3)

"""
2FAコードの取得+入力
oathtoolを利用
"""
import subprocess, re
twoFA = ['oathtool', '--totp', '--base32', 'アカウント追加キー']
print(subprocess.check_output(twoFA))

LoginPass_array = re.findall(r'\d+', subprocess.check_output(twoFA).decode('utf-8'))
LoginPass = LoginPass_array[0]
"""
認証アプリ画面への移動
"""
"""
wd.find_element_by_xpath('//*[@id="auth-select-device-form"]/div[1]/fieldset/div[3]/label/input').click()
wd.find_element_by_xpath('//*[@id="auth-send-code"]').click()
time.sleep(1)
"""
"""
OTP入力画面
"""
otp_box = wd.find_element_by_xpath('//*[@id="auth-mfa-otpcode"]')
otp_box.send_keys(LoginPass)
otp_box_submit = wd.find_element_by_xpath('//*[@id="auth-signin-button"]')
otp_box_submit.click()
time.sleep(1)


"""
アカウント&リストへ遷移
"""
account_list_top = wd.find_element_by_xpath('//*[@id="nav-link-accountList"]/span[1]')
account_list_top.click()
account_list_page =wd.find_element_by_xpath('//*[@id="a-page"]/div[3]/div/div[2]/div[1]/a/div/div/div/div[2]/h2')
account_list_page.click()

"""
wd.find_element_by_id('a-autoid-1"').click()
wd.find_element_by_xpath('orderFilter_3').click()
"""

"""
2020年の選択
"""
select_year_tab = wd.find_element_by_xpath('//*[@id="a-autoid-8-announce"]')
select_year_tab.click()
select_2020_tab = wd.find_element_by_xpath('//*[@id="orderFilter_3"]')
select_2020_tab.click()
time.sleep(3)

while True:
    main_brows = wd.current_window_handle
    reciept_links = wd.find_elements_by_link_text('領収書等')

    for reciept_link in reciept_links:
        reciept_link.click()
        time.sleep(3)
        reciept_purcahseresult_link = wd.find_element_by_link_text('領収書/購入明細書')

        before_click_handles = wd.window_handles

        """新しいタブでPDFを開く"""
        actions = ActionChains(wd)
        actions.key_down(Keys.COMMAND)
        actions.click(reciept_purcahseresult_link)
        actions.perform()

        WebDriverWait(wd, 5).until(lambda a: len(wd.window_handles) > len(before_click_handles))

        after_click_handles = wd.window_handles
        handle_new = list(set(after_click_handles) - set(before_click_handles))
        """タブ移動"""
        wd.switch_to.window(handle_new[0])

        """
        pdf保存
        """
        wd.execute_script('window.print();')

        wd.close()
        wd.switch_to.window(main_brows)

    try:
        wd.find_element_by_class_name('a-last').find_element_by_tag_name('a')
        wd.find_element_by_class_name('a-last').click()
        wd.switch_to.window(wd.window_handles[-1])
    except:
        break

wd.quit()

コード解説

それでは、早速先ほどピックアップした3要素についてコードの該当部分をみながら解説していきたいと思います。

kioskオプションを利用したPDF保存方法

まずは、kioskオプションの解説からです。そもそもkioskオプションってなんだって人も多いと思うので、概要から順に追って理解していきましょう。

kioskオプション(キオスクモードで起動するオプション)とは?

これはseleniumの機能ではなく、chrome自体に搭載されている機能です。(別にchromeに限った話ではないですが。。)

一般的には業務用のデバイスなどで活用されている機能で、一般ユーザが自分のブラウザをこの設定にすることは少ないかもしれません。

わかりやすい使われている例としては、コンビニや銀行のATM端末、オフィス等の案内端末、デジタルサイネージ、展示会の商品説明プレゼンテーションタブレットなどです。

kioskオプション(キオスクモード)でできること

では、キオスクオプション(キオスクモード)で何が通常のブラウザ操作と変わるのでしょうか?簡潔にいうと以下のようなイメージです。

多用途に利用できる汎用コンピュータやタブレットを、専用端末のように、ひとつの用途のみ利用できるようにする

実際の活用コード

今回のコードの中で、利用しているのは以下の部分です。

【kioskモード(+silent printing)での起動部分】

options = webdriver.ChromeOptions()
settings = {"recentDestinations": [{"id": "Save as PDF",
                                    "origin": "local",
                                    "account": ""}],
            "selectedDestinationId": "Save as PDF",
            "version": 2}
prefs = {'printing.print_preview_sticky_settings.appState': json.dumps(settings),'savefile.default_directory':downloadPath}
options.add_experimental_option('prefs', prefs)
options.add_argument('--kiosk-printing')


wd = webdriver.Chrome("chrome_driverのパス", options=options)

【実際の印刷(PDF保存)処理】

wd.execute_script('window.print();')

このadd_argumentに引数で渡している–kioskがキオスクモードでの起動を示唆しています。そして-printingの部分が、キオスクモードで起動して印刷ダイアログを表示させずに、そのまま印刷(今回の場合はPDF保存)させる機能を持ちます。いわゆるsilent printingと言われるやつです。

そして、そのprintingの設定方法として、settingsをprinting.print_preview_sticky_settings.appStateに渡して、add_experimental_optionに入れてwebdriverを起動させています。

要は立ち上げるブラウザに関する設定を今回の仕様に合うように調整している、と理解してもらえればいいです。

seleniumでの保存ディレクトリの指定方法

seleniumでの保存ディレクトリの指定方法の紹介です。

実際の活用コード

downloadPath = "DLファイルの絶対パス"

prefs = {'printing.print_preview_sticky_settings.appState': json.dumps(settings),'savefile.default_directory':downloadPath}
options.add_experimental_option('prefs', prefs)

こちらも先ほどのsilent printingの設定と同じように、chromeの起動時に保存するディレクトリをしてするオプションを設定して対応しています。

実際のオプションとしては、savefile.default_directoryというものをprefに入れて、add_experimental_optionとして設定する形になります。

actionchainsを利用した右クリックなどの実行方法

actionchainsはこれまでの2つと異なり、selenium自体の機能です。

actionchainsとは?

これはseleniumのドキュメントにもありますので、そちらを直接みてみるのがいいと思います。以下のような記載になっています。

ActionChains are a way to automate low level interactions such as mouse movements, mouse button actions, key press, and context menu interactions. This is useful for doing more complex actions like hover over and drag and drop.

https://selenium-python.readthedocs.io/api.html?highlight=actionchains#selenium.webdriver.common.action_chains.ActionChains.init

要はマウス操作(右クリックとかメニュー表示とか)を操作するためのモジュールです。

実際の活用コード

actionchainsでやれる内容の説明は実際のコードみながらの方がわかりやすいので、まずは該当部分のコードを貼っていきます。

"""新しいタブでPDFを開く"""
        actions = ActionChains(wd)
        actions.key_down(Keys.COMMAND)
        actions.click(reciept_purcahseresult_link)
        actions.perform()

今回は右クリックして新しいタブでPDF印刷用のhtmlを開くために利用しています。

actions = ActionChains(wd)部分: ActionChainsオブジェクトを作成し、wd(webdriver)を渡します

actions.key_down(Keys.COMMAND)部分:ActionChainsオブジェクトに対して、key_downメソッドを使用してコマンドキーを押させる(引数に渡されているKeysはselenium.webdriver.common.keysのKeys)

key_downメソッドの概要は以下です

key_down(valueelement=None)
Sends a key press only, without releasing it.
Should only be used with modifier keys (Control, Alt and Shift).


Args:
value: The modifier key to send. Values are defined in Keys
 class.
element: The element to send keys. If None, sends a key to current focused element.

actions.click(reciept_purcahseresult_link)部分:コマンドキーを押したまま対象のリンクをクリックする

actions.perform()部分:これまで設定した2つの操作(key_dwon及びclick)を実行する

という、流れで実行しています。

まとめ

さて、今回は【selenium・pythonを使ってAmazonの領収書を自動取得する方法〜シリーズ3:コード解説(kioskオプション,保存ディレクトリの指定, actionChains)〜】として、実際第2回で紹介したコードの解説をしてきました。

selenium自体の機能と合わせて、ブラウザ側の設定をいじる(調整して起動する)ことにより、いろいろ対応が可能です。よくseleniumでは保存ディレクトリの指定ができないと嘆く人やできないよと書かれるweb記事も多いのですが、実際やれます。

単純にseleniumでできること以外にも目を向けること(今回のケースで言えば、ブラウザの調整設定を入れればできること)でより実現したいことに近づけることができるので、多様な知識を薄らとでも見聞きすることが実装の可能性を広げるキーになるのでは、と思います。

次は番外編として第1回で紹介した2要素認証をパスするためのOTP作成についての理解を深める記事を紹介しようと思います。

関連記事: seleniumでAmazon領収書をPDF保存する方法関連記事

確定申告の時期にいつも必要になる領収書。そしてよく使うAmazon。そんなAmazonの領収書を一つ一つクリックして保存するなんて、時間的にも精神的にも辛い。というわけで、Amazonの領収書をseleniumを使って自動で指定フォルダにPDF保存する方法の紹介をするシリーズです。

  1. シリーズ1:2要素認証をパスする方法
  2. シリーズ2:2020年を選択して領収書PDFを保存
  3. シリーズ3:コード解説(kioskオプション,保存ディレクトリの指定, actionChains)
  4. シリーズ4(番外編):OTPについての理解を深める
タイトルとURLをコピーしました