追記 2020/6/6
nanacoギフトコードを直接指定できるように変更しました。
登録失敗時に再登録を試みるよう変更しました。
追記 2020/5/15
nanaco番号などがスクリプトに入力されていない場合、実行時に尋ねるように変更しました。
合わせて本記事に書かれている手順も見直しました。
概要
PythonでSeleniumを使用し、nanacoギフトコードの取得から登録までを自動化します。
nanacoギフトコードの取得をせずに、予めストックしておいたギフトコードの登録も可能です。
入力支援ではなく、自動化です。
※福利厚生倶楽部のギフトコードでテストしました。その他の場所で購入したギフトコードはテストしていませんのでご注意ください。
※下記ツイート内の動画は早送りしておらず等倍再生です。また、コンソール画面には全てMISSEDと表示されていますが、2回目の実行のため重複登録扱いになっているためです。実際に1回目の実行時は正しく登録されてOKと表示されますのでご安心ください。
seleniumで便利なもの作りたいと思ったので、nanacoギフトコードを自動で取得、登録するスクリプト作りました。https://t.co/7efggT42D5 pic.twitter.com/HFm6o2NTzw
— 🅽.🆈. \オンシャ!!/ (@nog_yo) May 15, 2020
スクリプト実行までの準備(初回限定)
-
最新のPython3をインストールします。すでにインストールされている場合は次の手順に進んでください。
上記サイトよりインストールする場合、「パスに追加する」旨のチェックボックスをオンにしてください。
※画像はhttps://www.javadrive.jp/python/install/index3.html より引用 -
最新のChromeをインストールします。すでにインストール済みの場合は次の手順に進んでください。
-
追加ライブラリをインストールします。Windowsならコマンドプロンプト、Macならターミナルで下記コマンドを実行してください。
※環境に応じてpip
またはpip3
で実行してください。pip3 install selenium pip3 install chromedriver-binary
-
下記スクリプトをコピーし、メモ帳などのテキストエディタに貼り付け、
nanaco_transiter.py
というファイル名で保存してください。
この時、福利厚生倶楽部のIDやnanaco番号などをスクリプト内に記載すると、実行がスムースになります。記載する欄は8行目から10行目です。
#!/usr/bin/env python3
import time
import re
from sys import argv
import selenium
from selenium import webdriver
userName = "" # <- 購入した福利厚生倶楽部のIDを6桁と4桁で入力してください(例: 012345-6789)
nanacoNo = "" # <- nanaco番号16桁を入力してください(例: 0123456789012345)
securityCode = "" # <- カード記載の番号を7桁で入力してください(例: 0123456)
def getGiftCodes(driver, url):
driver.get(url.strip())
driver.find_element_by_name("kainno").send_keys(userName)
driver.find_element_by_class_name("next").click()
elements = driver.find_elements_by_css_selector(".table_gift tbody tr")
giftCodes = []
for element in elements:
texts = element.text.split(" ")
if re.match("^[a-zA-Z\d]{16}$", texts[-3]):
giftCodes.append(texts[-3])
return giftCodes
# nanacoサイトのセッションを張る
def loginNanaco(driver):
driver.get('https://www.nanaco-net.jp/pc/emServlet')
driver.find_element_by_name("XCID").send_keys(nanacoNo)
driver.find_element_by_name("SECURITY_CD").send_keys(securityCode)
driver.find_element_by_name("ACT_ACBS_do_LOGIN2").click() # ここでログイン
time.sleep(1)
driver.find_element_by_link_text("nanacoギフト登録").click()
time.sleep(1)
# セッション内でギフトコードを登録する
def registGiftCode(driver, code, continueCount = 0):
driver.find_element_by_xpath("//input[@alt=\"ご利用約款に同意の上、登録\"]").click() # ここで新規ウィンドウが開く
time.sleep(1)
driver.switch_to.window(driver.window_handles[1]) # 直前に開いた新規ウィンドウをカレントにする
try:
driver.find_element_by_id("gift01").send_keys(code[:4])
driver.find_element_by_id("gift02").send_keys(code[4:8])
driver.find_element_by_id("gift03").send_keys(code[8:12])
driver.find_element_by_id("gift04").send_keys(code[12:])
driver.find_element_by_id("submit-button").click()
time.sleep(0.1)
result = "Succeeded"
driver.find_element_by_xpath("//input[@alt=\"登録する\"]").click()
except selenium.common.exceptions.NoSuchElementException:
result = "Duplicated" if "このギフトIDは、すでに下記の通り登録済です。" in driver.page_source else "Missed"
time.sleep(0.1)
driver.close() # カレントウィンドウ(さっき開いた新規ウィンドウ)を閉じる
driver.switch_to.window(driver.window_handles[0]) # nanacoページのウィンドウをカレントにする
return result if result != "Missed" or continueCount >= 5 else registGiftCode(driver, code, continueCount + 1)
# 入力内容を整理して正しくスクリプトが動作するようにする
# 必要変数が空の場合、対話形式で補完していく
def checkEnviroment(arg):
global userName, nanacoNo, securityCode
if not userName:
print("購入した福利厚生倶楽部のIDを6桁と4桁で入力してください(例: 012345-6789)")
userName = input()
if not nanacoNo:
print("nanaco番号16桁を入力してください(例: 0123456789012345)")
nanacoNo = input()
if not securityCode:
print("カード記載の番号を7桁で入力してください(例: 0123456)")
securityCode = input()
urlsOrGiftCodes = []
if len(arg) < 2:
print("nanacoギフトコード、またはnanacoギフトコードを表示するためのURLを1行ずつ入力してください。")
print("全て入力し終わったら、何も入力せずにEnterを押してください。")
while True:
code = input()
if urlsOrGiftCodes and not bool(code):
break
if code.strip() != "":
urlsOrGiftCodes.append(code.strip())
else:
for code in arg[1:]:
urlsOrGiftCodes.append(code.strip())
return urlsOrGiftCodes
if __name__ == "__main__":
urlsOrGiftCodes = checkEnviroment(argv)
print("Preparing...")
driver = selenium.webdriver.Chrome()
driver.set_page_load_timeout(30)
print("Getting gift codes ...")
giftCodes = []
for code in urlsOrGiftCodes:
# 入力内容がURLの場合、コードを取得しにいく
if code[:8] == "https://":
giftCodes += getGiftCodes(driver, code)
# 入力内容がURLでない場合、それがギフトコードとして扱う
else:
giftCodes.append(code)
print("Logging in nanaco website ...")
loginNanaco(driver)
progress = {}
print("Registing codes ...")
for giftCode in giftCodes:
print(giftCode, "...", end = "\r")
result = registGiftCode(driver, giftCode)
if not result in progress:
progress[result] = 0
progress[result] += 1
print(giftCode, "(%d/%d)" % (sum(progress.values()), len(giftCodes)), result)
for key in progress:
print(key + ":", progress[key])
print("Total:", sum(progress.values()))
driver.find_element_by_id("memberInfoInner").click()
driver.quit()
Githubにも掲載しています。
実行方法
Windowsならコマンドプロンプト、Macならターミナルで下記コマンドを実行してください。
※環境に応じてpython
またはpython3
で実行してください。
python3 nanaco_transiter.py "ギフトコードのURL"|"ギフトコード" ["ギフトコードのURL"|"ギフトコード" ...]
実行例
python3 nanaco_transiter.py "https://www.fukuri.net/main/www/gift/login.jsp?jujuno=xxxxxxxxxx&cococd=xx" da1Ddf2fffsd4589 fffsd4589da1Ddf2 "https://www.fukuri.net/main/www/gift/login.jsp?jujuno=yyyyyyyyyy&cococd=yy"
上記の場合、URL指定した2つのページよりnanacoギフトコードを取得し、ギフトコード指定した2つのギフトコードと合わせて登録を行います。
出力結果
スクリプトの進捗状況と、各ギフトコードの登録結果を表示します。
各ギフトコードの出力結果「ギフトコード 進捗度合い 登録結果」で表示されます。
表示例は次のとおりです。
abcdefgHIJ123456 (13/20) Succeeded
登録結果は以下の3種類で表示されます。
登録結果 | 説明 |
---|---|
Succeeded | 登録に成功しました |
Duplicated | すでに登録されています |
Missed | 5回試行しましたが、5回とも登録に失敗しました。正しいギフトコードかどうかとネットワーク環境を確認してください |
その他
- 引数に何も入力せずに実行した場合、実行時に入力を求められます。ギフトコードが記載されてるURLか、ギフトコードを1行ずつ入力してください。
- 引数のURLは""で括る必要があります。括らない場合、文字列中の&をシェル命令の&と解釈されてしまい正しく動作しません。ギフトコードの場合は括らなくても問題ありません。
- 引数の場合も実行中に入力の場合も、ギフトコードとURLは混在して入力できます。
- ギフトコードの登録に失敗した場合、成功するまで最大5回繰り返します。全て失敗した場合、Missedと表示されます。
- 福利厚生倶楽部のIDの入力は必須です。全てギフトコードを入力した場合はテキトーな値を入力してください。
- 細かなエラー処理は実装していません。本来の使い方でご使用ください。
- ギフトコードの登録中に落ちてしまっても、再実行すれば問題なく登録できます。
- 不具合などありましたらご連絡いただけると助かります。
免責
- このスクリプトの実行は全て自己責任でお願いします。
- このスクリプトに悪意ある動作は含めていませんが、万一不具合によって実行者が被害を被ったとしても、作者は一切の責任を負いませんのでご注意ください。