仕事でPEXギフトコードの入力作業を行っています。しかし、コードの単位が500円ごとになっており、毎度毎度大量のコード入力がとても面倒です。

そこで、Seleniumを使ってコード入力を自動化してみました。

プログラムの概要

仕組み

コードの入力画面を開く、コード入力、ボタンを押す。基本的には、これらをループで繰り返していくだけです。

しかし、極端に早く処理をしすぎてしまうと、ボットであると検知されてしまう可能性もあります。

ソースコード

#! /usr/bin/python3
import time,os,sys,random,re
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

#ヘッドレスモード用
from selenium.webdriver import Firefox, FirefoxOptions

#プロファイルの場所
fp = webdriver.FirefoxProfile("プロファイルのパスを指定してください。")

#ヘッドレスモードで起動させる。
options = FirefoxOptions()
#options.add_argument('-headless')

browser = webdriver.Firefox(fp, options=options)

#本番用
browser.get("https://pex.jp/point_gift/new")

#待ち時間の設定
DEFAULT_RANDOM_TIME = 3 
DEFAULT_STABLE_TIME = 3
WAIT_TIME           = 1.2
TIMEOUT             = 5

#改行除去
NEW_LINE_PATTERN = re.compile(r"\n")

#コードリストの取得
CODE_FILE       = open('./code.txt')
CODE            = CODE_FILE.readlines()
CODE_FILE.close()
LEN_CODE        = len(CODE)
for i in range(LEN_CODE):
    CODE[i]   = NEW_LINE_PATTERN.sub("",CODE[i])


def main():

    try:
        html_wait = WebDriverWait(browser,3)
        print("HTML取得中")
        html_elem = html_wait.until(expected_conditions.visibility_of_element_located((By.TAG_NAME, "html")))
        print("HTML取得完了")
    except:
        print("HTMLの取得に失敗しました")

    else:
        
        #コードが終わるまで処理を続ける
        for i in range(LEN_CODE):

            #===============コードの入力作業======================================================
            html_wait   = WebDriverWait(browser,TIMEOUT)
            code_elem   = html_wait.until(expected_conditions.visibility_of_element_located((By.XPATH, "//input[@id='pex_point_gift_charge_log_gift_code']")))
            y_pos       = code_elem.location["y"]
            browser.execute_script("window.scroll(0 , " + str(y_pos) + ");")
            time.sleep(WAIT_TIME)
            code_elem.click()
            code_elem.send_keys(CODE[i])
            print(CODE[i] + "を入力しました。")
            #===============コードの入力作業======================================================

            #===============同意する======================================================
            html_wait   = WebDriverWait(browser,TIMEOUT)
            code_elem   = html_wait.until(expected_conditions.visibility_of_element_located((By.XPATH, "//p[@class='guideline_check']/label")))
            y_pos       = code_elem.location["y"]
            browser.execute_script("window.scroll(0 , " + str(y_pos) + ");")
            time.sleep(WAIT_TIME)
            code_elem.click()
            #===============同意する======================================================

            #===============チャージする======================================================
            html_wait   = WebDriverWait(browser,TIMEOUT)
            code_elem   = html_wait.until(expected_conditions.visibility_of_element_located((By.XPATH, "//input[@id='btn-charge']")))
            y_pos       = code_elem.location["y"]
            browser.execute_script("window.scroll(0 , " + str(y_pos) + ");")
            time.sleep(WAIT_TIME)
            code_elem.click()
            #===============チャージする======================================================


            #===============元に戻る======================================================
            html_wait   = WebDriverWait(browser,TIMEOUT)
            code_elem   = html_wait.until(expected_conditions.visibility_of_element_located((By.XPATH, "//a[@class='btn-base btn-large btn-sub']")))
            y_pos       = code_elem.location["y"]
            browser.execute_script("window.scroll(0 , " + str(y_pos) + ");")
            time.sleep(WAIT_TIME)
            code_elem.click()
            #===============元に戻る======================================================

            timer = random.random() * DEFAULT_RANDOM_TIME + DEFAULT_STABLE_TIME
            time.sleep(timer)

    return True

if __name__ == "__main__":
    try:
        print(main())
        sys.exit()

    except KeyboardInterrupt:
        print("\nprogram was ended.\n")
        sys.exit()

突貫で作ったので色々雑ですが、ちゃんと動きます。

このプログラムの解説

まず、Seleniumでコードの入力画面を開きます。続いて、事前にテキストファイルに格納されている、PEXギフトコードを読み取って入力していきます。

主な使用するメソッドはclick()send_key()ぐらいです。

要素を指定してクリックするか、入力していくだけなのでSeleniumの初心者でも簡単に作れるでしょう。

工夫したところ

特にありませんが、あえて言うのであれば、Seleniumの動作ごとにコメントを使い、コードを分割して見やすくしました。

こうすることで保守も楽になります。

動作環境

  • Python3.6
  • Seleniumがインストール済み
  • 事前にPEXにログインしておく
  • 事前にcode.txtにコードを入力しておく

他のログインが必要なサイトと同じように、プロファイルを指定してログイン作業を省略しているので、事前にPEXにログインしておく必要があります。

実際に動かしてみる

起動すると、PEXのコード入力画面が表示されます。

下記の画像のようにコードの入力、チェックボックスのクリック、ボタンのクリックの順で動作します。

PEXのコードを入力する

コードの入力が完了したあとは、前の画面に戻るリンクをクリックします。

前の画面に戻る

正常終了すると、シェルには以下のように表示されます。

シェルの表示

メリットとデメリット

メリット

  • 面倒なコード入力作業が自動化できる
  • 手動でやる場合と違って打ち損じてしまうことが無い
  • キャプチャツールを使えば、あとから確認もできる

面倒なコード入力作業が自動化できる

PEXコードをコピペして、マウスをカチカチクリック。これを繰り返さなくていいだけで、とても楽です。

特にSeleniumであれば、プロファイルの読み込みで認証が必要なサイトであっても問題なく作業ができます。

他の単純作業系のサイトでも同じように、自動化できるでしょう。

手動でやる場合と違って打ち損じてしまうことが無い

何度か、PEXのギフトコードを手動で入力したことがありましたが、打ち損じてしまうことがありました。

一回の打ち損じで500円のロストなので、この作業の自動化はありがたいです。

キャプチャツールを使えば、あとから確認もできる

万一、Seleniumで入力作業を自動化したとしても、動画のキャプチャツールを使って撮影していれば、何を入力し損ねているのかを確認できます。

もちろん確認作業も面倒なので、その辺りも自動化させていきたいところです。

デメリット

  • 突貫で作ったので、色々と雑
  • 事前にPEXのコードを入力した、テキストファイルを用意しておく必要がある
  • BANされるリスク

突貫で作ったので、色々と雑

手動での入力作業にイライラして作ったので、色々と雑です。(特に変数名とか)

とはいえ、リファクタリングしようと思えば何時でもできるレベルの規模ですし、それほど問題にはならないでしょう。

実際、数日前に作ってかれこれ5回以上動かしていますが、問題なく動作しています。

事前にPEXのコードを入力した、テキストファイルを用意しておく必要がある

このツールはPEXコードが入力されたファイルを用意する必要があります。

とはいえ、PEXのギフトコードは別のプログラムによって自動的に入力されるので、問題はありません。

BANされるリスク

正直言って、これが一番怖いです。今のところ問題はありませんが、あまり高速に入力しているとBANされるのではないかと考えています。

一応、待ち時間は長めに設定しているので、人間が手動で入力するよりも遅いですが、やや不安です。このツールを利用しようと考えている方は自己責任でお願いします。

結論

単調な手動の作業以上に面倒なものはありません。今回の開発で日頃の面倒な作業が、またひとつ無くなりました。

関連記事

Amazonのほしい物リストの値下げされた商品を抜き出す

【内部リンク】Amazonのほしい物リストから値下げされた商品だけをメールで通知するPythonプログラム

Amazonのほしい物リストはページをスクロールしなければ読み込んでくれません。

そこでSeleniumを使ってスクロール、読み取りを繰り返し、メールで送信しています。

ハローワークの求人情報抽出プログラム

【内部リンク】ハローワークから求人情報を自動的に取得して、メールで通知するPythonプログラム

ハローワークの求人情報もブラウザで条件を入力しない限りは取得できません。

そこでSeleniumに入力を手伝ってもらっています。