Nintendo Switchの入荷状況をWebスクレイピングで取得しLINEで通知する方法
■今回の流れ
[1] My Nintendo Store(マイニンテンドーストア)にアクセスしHTMLを取得し、「SOLDOUT」以外のステータスか確認
[2] ステータスに変更が合った場合にLINEに通知する(設定に1~2時間かかるかも)
[3] 定期的に実行
※お断り:普通に使えるけど、スピード勝負の個人用に作ったものなのでコードはお粗末ですよ。文句言わないでね。
■必要なもの
・Linuxサーバ (bash使います、crontab使います)
・Googleアカウント (スプレッドシートとApps Script使います)
・LINE Messaging APIのアカウント
■内容
[1] My Nintendo Store(マイニンテンドーストア)にアクセスしHTMLを取得
#!/bin/sh #HTMLを取得 curl https://store.nintendo.co.jp/customize.html -o switch_html -s #検索するために無駄なものを削ぎ落とす(改行や半角スペース・ダブルクォーテーション消す) perl -pi -e 's/\s|"//g' switch_html #ステータス確認 #ページ下部にあるSOLDOUTボタンが切り替わったか確認する if grep "buttonclass=btnbtn__primary_soldoutto_carttype=submit><span>SOLDOUT</span></button" -q -R switch_html then echo "売り切れ" else echo "入荷されたよ" fi
[2] ステータスに変更が合った場合にLINEに通知する(1~2時間かかるよ)
こちらを参考にさせていただきました!ありがとうございました!
▼参考サイト
「https://bita.jp/dml/line-messaging-api-exp」
「http://qiita.com/mobe_yura/items/453fc779c8c90046eb77」
①まずはLINEから送られるJSONを受け取れるようにGoogle Apps Scriptの準備。
1.Googleドライブで新規->その他->Google Apps Script
※ない場合はその他内にあるアプリ追加から「Google Apps Script」を選択
2.スクリプトファイルを開き、公開->ウェブアプリケーションとして導入->更新
※この時引っかかったところ、で公開設定。
次のユーザーとしてアプリケーションを実行:自分
アプリケーションにアクセスできるユーザー:全員(匿名ユーザを含む)
3.現在のウェブ アプリケーションの URLをどこかにメモっとく。LINEの設定で使う。
②次にLINE Messaging APIのアカウントを作成。
https://business.line.me/ja/services/bot
1.必ず「Developer Trialを始める」を選択。アカウントを作成。
2.アカウント設定 > bot設定 でまずは「APIを利用する」を選択
3.リクエスト設定は下記で。
Webhook送信 「利用する」
Botのグループトーク参加 「利用する」
自動応答メッセージ 「利用しない」
友だち追加時あいさつ 「利用しない」
4.BOT設定のステータスあたりにある「LINE Developersで設定する」を選択
5.Webhook URLはさきほど作ったGoogle Apps Scriptを設定。※変更はVERIFYを押す。
6.Channel Access Tokenは使うので「ISSUE」を押して出てきたコードをどこかにメモ。
③作ったAPIとお友達になってグループチャットを作る(LINE上での操作)
1.さきほどの「LINE Developersで設定する」内にあるQRコードを読み取りAPIちゃんとお友達になる。
2.在庫状況追加用のグループチャットを作り、APIちゃんを呼ぶ。
※なんでグループチャットにしたかというと、他に在庫状況知りたい友人がいたから。
④グループチャットのIDを調べる。(LINE通知するときの宛先)
1.Googleドライブで新規⇒スプレッドシートを作成
2.スプレッドシートのURLをどこかにメモっとく。
3.①で作ったGoogle Apps Scriptにコードを入力
※LINEのグループチャットに適当なメッセージを送った時、
APIちゃんがGoogle Apps Scriptにコールバックする。
Google Apps ScriptはAPIちゃんからきた情報をスプレッドシートに書き込む。
var channel_id = ""; //LineBotの管理画面から取得 var channel_secret = ""; //LineBotの管理画面から取得 var mid = ""; //LineBotの管理画面から取得 function doGet(e) { return ContentService.createTextOutput(UrlFetchApp.fetch("http://ip-api.com/json")); } //●●●●●●●●はスプレッドシートのURL、さっきメモったやつ function writeSpread(group_id){ var url ='●●●●●●●●'; var spreadsheet = SpreadsheetApp.openByUrl(url); var sheets = spreadsheet.getSheets(); var sheet = sheets[0]; var lastrow = sheet.getLastRow(); sheet.getRange(lastrow+1, 1).setValue(group_id); } function doPost(e) { var webhook = JSON.parse(e.postData.contents).events[0]; if(webhook.type === 'join'){ writeSpread(webhook.source.groupId); }else{ var message_type= JSON.parse(e.postData.contents).events[0].message.type; if (message_type === 'text') { var user_message = JSON.parse(e.postData.contents).events[0].message.text; writeSpread(webhook.source.groupId); } } }
4.LINEのグループチャットに適当にメッセージを入れると、スプレッドシートにグループチャットのIDが表示される。これをどこかにメモっとく。
⑤curlを使ってLINE通知実行!
#LINE MESSAGE #{ENTER_ACCESS_TOKEN}は②の6でメモったやつ #toはxxxxxは④の4でメモったやつ curl -X POST \ -H 'Content-Type:application/json' \ -H 'Authorization: Bearer {ENTER_ACCESS_TOKEN}' \ -d "{ \"to\": \"xxxxx\", \"messages\":[ { \"type\":\"text\", \"text\":\"入荷したよ!\" }, { \"type\":\"text\", \"text\":\"https://store.nintendo.co.jp/customize.html" } ] }" https://api.line.me/v2/bot/message/push
⑥最終的なコード:在庫ステータスをチェックしてLINE通知送るまでのコード
#!/bin/sh # 一度在庫有りステータスになったあと何度も実行しないように時間制御いれてる # いらなかったら外してOK START=`date +%s` # 入荷ステータス時の1900/1/1からの秒数を求める FINISH=`cat status1_second` if [ -n "$FINISH" ]; then # 終了日 - 開始日 の差分秒を求める DIFF=`expr $START - $FINISH` # 秒分で割ることで時間が求められる(小数点切り捨て) HOUR=`expr $DIFF / 60 / 60` # 1時間以内は送らない if [ $HOUR -le 1 ]; then echo "stop" exit fi fi #-------------------------------------------- #SWITCH 状況確認 curl https://store.nintendo.co.jp/customize.html -o switch_html -s perl -pi -e 's/\s|"//g' switch_html if grep "buttonclass=btnbtn__primary_soldoutto_carttype=submit><span>SOLDOUT</span></button" -q -R switch_html then echo "売り切れ" else echo "入荷されたよ" curl -X POST \ -H 'Content-Type:application/json' \ -H 'Authorization: Bearer {ENTER_ACCESS_TOKEN}' \ -d "{ \"to\": \"xxxxx\", \"messages\":[ { \"type\":\"text\", \"text\":\"入荷したよ!\" }, { \"type\":\"text\", \"text\":\"https://store.nintendo.co.jp/customize.html" } ] }" https://api.line.me/v2/bot/message/push #入荷時ステータスを記録 :> status1_second echo $START > status1_second fi exit
[3] 定期的に実行
作ったシェルスクリプトを定期実行しよう。
$ crontab -e
#switch
*/1 7-23 * * * (sh exec.sh 2>&1 >> cron_log) | tee -a cron_log
書き込み時は大体月曜日、水曜日が入荷日。
マイニン完売時間
04/03(月) 13:37-13:46 9分
04/13(木) 13:20-13:45 25分
04/21(金) 12:52-13:32 40分
04/28(金) 12:55-13:10 15分
05/08(月) 12:54-13:03 9分
05/11(木) 12:48-13:13 25分
05/18(木) 12:16-12:43 27分
05/18(木) 17:03-17:10 7分
05/25(木) 12:29-12:36 7分
06/01(木) 12:42-鯖落ち
06/13(火) 09:51-10:08 17分
06/19(月) 18:06-18:12 6分
06/21(水) 10:08-10:25 17分
06/26(月) 18:38-18:51 13分
このスクリプト作る前は、
金曜日にヨドバシに朝から張り込んだり、
入荷すらわからない店舗の開店を狙ったり、
土日の電気屋の抽選に朝から並ぶという非常に体力を使っていたが、それでも買えなかった・・・
頑張ってスクリプト監視を入れたら、マイニンテンドウですぐ買えた!
ちなみに応用でこのスクリプトをコピーして、
他のサイトを監視するのもあり。
ただし、サーバ攻撃にならないよう実行は5分おきにするなど節度は守りましょう。