【テンプレートあり】JavaScriptで自動購入Bot作る

プログラミング

IQZeus

JavaScriptで自動購入Bot作る

今回私はJavaScriptを使ってPS5の自動購入Botを作成しました!

なのでそれを備忘録としてまとめておきます!

あくまで自分の保存用でもあるので多少雑なところはお見逃しください。。。

ちなみにPS5の自動購入はサイトから直接利用できるようになっているので良ければご使用ください!

スマホからでもできますのでどうぞ!

JavaScriptとは?

JavaScriptがどういうものかを知らない人もいるかもしれないので簡単に説明するとJavaScriptは基本的にブラウザで実行される動的な処理が得意なプログラミング言語です!基本的には!

はい。こんなに基本的にはと言っていれば想像できると思いますがサーバー上で動かすこともできます。

そういう時はNode.jsとかのフレームワークを使用して実行します。

他にもフレームワークはいろいろあるけど有名なもので実際に使うことが多いのはNode.jsですかね。。。

今回実行する自動購入BotもこのNode.jsを使用して処理を行うので「まだ導入していないよ!」という方は先に記事を作成しておいたのでこちらからインストールしておいてもらえるとスムーズに進みます。

私もこの方法でインストールして実行しているので環境もそろってちょうどいいかもしれませんね!

ちなみに実行環境はWindowsですのでそこはご注意ください!

あと今回の自動購入Botはブラウザを使うのですがheadless(ブラウザが画面に表示されない)で行うと購入できないことがあるのでできれば他のOSを使うにしてもモニター付きの環境で行うのがいいと思います!

まあモニターがなくても大丈夫な方法もあるのですが、それはこの記事が見られたら書きます。

宣伝よろしくお願いいたします

実際宣伝よろしくって言ってもどう宣伝すればいいのかもわかりませんよねw

他にも簡単にできるbot検知を回避する方法もあるのでそちらはそのうち紹介しますね~!

これはモニター云々関係なくただのbot検知回避する方法なのですが記事を書いたのでこちらをご覧ください。

大丈夫です。良ければ宣伝お願いします。(控え目)(低姿勢)

テンプレート

毎回行うテンプレート

ほぼそのまま使えるコードを張るのですが一応説明も入れながらやっていきます!

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({args: ['--no-sandbox'], headless: false});
const page = await browser.newPage();

まずはPuppeteerのインポートを行います。

Puppeteerのインストール自体はnpmから行いますのでコマンドライン等からあらかじめインストールを行って下さい。

インストールの仕方はさっきのNode.jsのインストール方法の記事に書いたかな?

書いてなかったのでまた記事書きますねw

簡単に言うとJavaScriptファイルがあるディレクトリに移動してnpm install puppeteerでできます。

さて、Puppeteerのインポートができたら

3行目でブラウザを起動しています。

デフォルトで起動させるのはpuppeteerをインストールするときに一緒にダウンロードされるchromiumです。

別のブラウザに変更することはできますが、このままでも問題ないので今回はこのままいきます。

launchの引数に--no-sandboxというのがありますがこれがないとちゃんと動かないので忘れずにつけましょう。

これを付けないと--no-sandboxつけてやってねっていうエラーが出て起動できません。

4行目でページを作っています。(タブかな?)

このページを変数に代入しているので、これ以降はこのpageを使って処理を指定していきます。

要素探索と購入処理

次は購入処理までの流れです。

var Target_URL = "https://google.com";
await page.goto(Target_URL, {timeout: 20000, waitUntil:'domcontentloaded'});

await page.waitForSelector('button.someClass', {timeout: 1000});
await page.click('button.someClass', { waitUntil: 'domcontentloaded' });

await page.waitForSelector('#someId', {timeout: 1000});
await page.click('#someId', { waitUntil: 'domcontentloaded' });

await page.waitForSelector('button[name="someLogin"]', {timeout: 1000});
await page.type('input[name="someName1"]', "username");
await page.type('input[name="someName2"]', "password");
page.click('button[name="someLogin"]', { waitUntil: 'domcontentloaded' });

ページを開く

購入処理まで行うときは大抵これの組み合わせで行けます。2行目でTarget_URLを開いています。

この時に大抵オプションでtimeoutを20000ms(20秒)に設定していたりwaitUntilをdomcontentloadedにしていたりします。

timeoutは指定時間を超えたら例外を出して処理を抜け出します。場合によってはサイトが混雑していて再接続した方がいい時もあるので一応設定しておいた方がいいでしょう。

waitUntilはそのままの意味ですがページのDOM読み込まれるまで待ちます。

JavaScriptとかの時間がかかる処理を完全に待つまでもなく次の操作が行えるので「次の処理はただボタン押したい」というときとかに有効です。

要素取得とクラス指定で取得

4行目ではwaitForSelectorを使いbutton.someClassが現れるまで待っています。

2行のdomcontentloadedですでに読み込まれているはずですが一応一秒のタイムアウトを設定しています。(404ページに飛ばされた場合や混雑ページに飛ばされたとき対策)

このwaitForSelectorでは第一引数に探したい物を指定するのですがこの4行目の場合someClassクラスのついているbuttonタグを探しています。

.クラス名という風に指定するとそのクラス名の要素を探すことができます。普通に(.とかつけずに)指定するとタグを指定することになります。(今回のbuttonみたいな)

5行目でpage.clickを使いbutton.someClassをクリックしています。

page.click効果があるのかは確認していませんが、一応遷移が入るのでdomcontentloadedをオプションにつけています。問題は起こってないのでいいかな?w

ID指定で取得

7,8行目は4,5行目とほとんど変わりませんがidで指定したいときは#を付けて指定します。

その説明のためだけに載せましたw

name属性を指定して取得

10,11行目も大方変わりありませんがname属性で指定する方法です。

ログインしたい時などのFormの中身を操作したいときに使うことがあるでしょう。

見たまんまですが

タグ[name=ネーム属性]

という風に使います。自動購入Botを作るには必須のテクニックだと思うので覚えておきましょう。

someLoginネーム属性が読み込まれたら入力欄もあると思うのでそのまま

page.type(要素)

でユーザー名(メールアドレスとか)とパスワードを入力しています。

入力し終わったらまたclickでログインボタンを押しています。

Seleniumとかだと既存のプロファイルを使ってクッキー使用のログインとかもできると思いますが、今回の私の用途ではそれはできないので調べていません。

購入処理

今までのことと同じですがこの後全部乗せたコードを上げるのでそのために一応書いておきます。

await page.click('button[name="buy"]', { waitUntil: 'domcontentloaded' });

こんな感じでname指定してあげるのが一般的かな?もしくはid指定。。。

awaitって?

ずっとスルーしてきたのですがawaitという文字が処理の最初についていると思います。

これは非同期処理の中で同期的に処理を行いたいときに使うプログラムで自動購入のような一度にブラウザを複数開くかもしれない処理には必要なプログラムとなります。

ちなみに非同期処理はasyncを使うとできます。

forループで非同期関数を同時に回しつつその非同期関数の中ではページのロードを待って次の処理を行ったり同期的な処理を行っているというわけですね。

しかしここまでasyncもfor文も登場していません。

一般的にpuppeteerは非同期関数の中で実行されることが多いのでコピペ用にawaitを付けておきました。

全文まとめて実用的な書き方をしたテンプレートをこの後まとめますね。

さいごに

はい。最後にテンプレ全文をまとめたやつを載せたいと思います。

const puppeteer = require('puppeteer');

var Target_URL = "https://google.com";
var is_debug = false;

async function buy_items(){

    const browser = await puppeteer.launch({args: ['--no-sandbox'], headless: false});
    const page = await browser.newPage();


    try{
        await page.goto(Target_URL, {timeout: 20000, waitUntil:'domcontentloaded'});

        await page.waitForSelector('button.new_addToCart', {timeout: 1000});
        await page.click('button.new_addToCart', { waitUntil: 'domcontentloaded' });

        await page.waitForSelector('#js-cartBtn', {timeout: 1000});
        await page.click('#js-cartBtn', { waitUntil: 'domcontentloaded' });

        await page.waitForSelector('button[name="submit"]', {timeout: 1000});
        await page.type('input[name="user"]', "username");
        await page.type('input[name="pass"]', "password");
        page.click('button[name="submit"]', { waitUntil: 'domcontentloaded' });


        if (is_debug == false){
            // 購入ボタンクリック
            await page.click('button[name="commit_order"]', { waitUntil: 'domcontentloaded' });
        }
    
    
    } catch(e) {
        console.log("エラーです。:" + e);
    } finally {
        //例外が発生しても発生しなくてもここは必ず通る
        await page.close()
        await browser.close();
    }
};

buy_items();

しっかりasyncも使っていますね。

実際に処理をするときはtry-catchを使った方がいいです。

というか基本的には使います。

使わないとタイムアウトしたときにプログラムが停止してしまいますからねw

他のサイトでは処理部分だけで結局うまくいかないこともあると思うので実用的なテンプレを載せてみました!

(一応説明も加えて)

実際にこのテンプレの組み合わせだけで購入することはできると思いますがやりたいことが増えてくると困ることも出てくると思うのでコメントしていただければお答えできるかもしれません。

これからも記事を書いていくのでよろしくお願いします!

それでは!

(気づいたら6000字超えてたw)

コメント

  1. しょう より:

    お世話になっております。質問がございます。
    参考にしてローカルでbotを作成しましたが、
    他の在庫ありのurlで試してみたら、楽天でBot検知されました。
    (「アクセスが集中し、ページを閲覧しにくい状態になっております」となる)
    Puppeteerの方法で楽天の場合は回避できないでしょうか。
    よろしくお願いいたします。

    • やーと より:

      コメントありがとうございます!

      短期間に複数回連続で接続している場合には(1分に10回とかでも多いかも)そのIPに対して制限をかけている場合があるのでプロキシサーバを使うかもっと頻度を落とす必要があると思います。
      他にはヘッダを書き換える方法等ありますがIPで制限をかけられている場合プロキシサーバはどちらにしろ必須です。

      もしくは逆にリロードし続けるとたまにいけることもありますがWebサーバに負荷をかけることになるので推奨できません。

  2. PS5欲しい より:

    リクエスト型のbotの作り方も解説して欲しいです

  3. ジョン より:

    初めまして、質問したいです!!

    ps5ではないのですが、
    別のサイトで別のことでbotを使いたいと考えてるのですが、その際にこちらのテンプレを加工すれば流用出来るのでしょうか?
    それとも新規作成になりますか??よろしくお願いいたします💦

    • やーと より:

      はい。コメントありがとうございます。
      基本的な動作はこのテンプレの流用で可能です。
      操作が決まっている物ならすぐに作れると思います。

      • ジョン より:

        ご返信ありがとうございます!!

        操作は決まってるのですが、中々難しいですね😢

  4. マイキー より:

    こんにちわ!テンプレートありがとうございます。右往左往しながらもなんとかテスト購入することが出来ました。
    ただ繰り返し処理がしたいため、catchにbuy_items();を入れることでカートボタンがそのURLで出てくるまで動くようにしてるのですがこれは正しいのでしょうか?

    ブラウザ立ち上げ→URLに飛ぶ→カートボタンあるかどうか見る→ないならタブを閉じるor再読み込み→カートボタンあるかどうか見る以下繰り返し・・・・
    と処理したいです!なにかアドバイスくれると嬉しいです!

    • やーと より:

      プログラムを見ない事には分かりませんが、それでも動くとは思います。
      ただプログラム的にはしっかり非同期処理の成功/失敗の返り値を受け取ってそれによって続きの処理をどうするか決めた方が綺麗だしあとから見ても何をしたかったのかが明瞭でいいと思います。(catchで実行するのは基本的にエラーそのものに対する対処なので、、、)
      頑張ってください💪

タイトルとURLをコピーしました