Help us understand the problem. What is going on with this article?

テレビ番組への観覧応募をpuppeteerで自動化する

More than 1 year has passed since last update.

大好きなテレビ番組の観覧募集にいつも応募してるのですが、なかなか当選しません:sob:
毎回名前やら住所やらを入力するのが面倒になってきたので、puppeteerで観覧応募を自動化してみました。

※あんまり良くないかなと思って具体的な番組名やサイトのURLを載せるのはやめました。なので単にフォーム入力の自動化の方法を紹介する内容になってます:sweat_smile:

puppeteerとは

ヘッドレスChromeを操作するためのNode.js APIを提供するライブラリです。
puppeteerを使うと、Webサイトを開いたり、WebサイトのページのスクリーンショットやPDFを取得したり、入力欄に文字を入力したりと、私たちがブラウザ上で手動で行う操作のほとんどをプログラムから実行することが可能になります。
puppeteerはWebアプリケーションのE2Eテストで使用されるケースが多いと思います。

以前にpuppeteerのサンプルプログラムを紹介する記事を書いたのでよかったらこちらもご覧ください。
ヘッドレスChromeライブラリpuppeteerの全てのサンプルプログラムを試してみた

画面構成

番組の観覧募集のページに行くと、以下のようなフォーム画面が表示されます。
このフォームはiframeで埋め込まれています。

image.png

スクリプトの解説

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // 1
  await page.goto('サイトURL');
  const frame = page.frames()[1];
  await frame.waitForSelector('input[name="quest[1]"]');

  // 2
  await frame.type('input[name="quest[1]"]', 'あなたの氏名');
  await frame.type('input[name="quest[2]"]', 'あなたのふりがな');
  await frame.type('input[name="quest[3]"]', 'あなたの年齢');
  await frame.click('input[name="quest[4]"][value="1"]');
  await frame.select('select[name="quest[5]"]', 'あなたの都道府県');
  await frame.type('input[name="quest[6]"]', 'あなたの電話番号');
  await frame.type('input[name="quest[7]"]', 'あなたのメールアドレス');
  await frame.type('textarea[name="quest[8]"]', 'あなたの同伴者の氏名・性別・年齢');

  // 3
  await frame.click('input[name="confirm"]');
  await frame.waitForSelector('input[name="commit"]');

  // 4
  await frame.evaluate(() => {
    const name = document.querySelector('.formDiv');
    name.scrollIntoView();
  });
  await page.screenshot({path: 'confirm.png', fullPage: true});

  // 5
  await frame.click('input[name="commit"]');

  // 6
  await page.screenshot({path: 'finish.png', fullPage: true});

  await browser.close();
})();

スクリプトの内容は以下のとおりです。

  1. 観覧募集ページを開く
  2. 氏名、ふりがな...を入力する
  3. 「確認」ボタンをクリックして確認画面に遷移する
  4. 「確認」画面のスクリーンショットを取得する。その際、確認フォームの内容が全部表示されるようにスクロールさせておく。 
  5. 「送信」ボタンをクリックして完了画面に遷移する
  6. 「完了」画面のスクリーンショットを取得する

1. 観覧募集ページを開く

観覧募集の入力フォームはiframeで埋め込まれており、puppeteerではpage.frames()[1]で2番目のフレームとして取得できます。
以降はこのフレームに対して操作をすることになります。

観覧募集ページを開いたら、frame.waitForSelector(selector)でフォームが表示されるまで待ちます。

2. 氏名、ふりがな...を入力する

frame.type(selector, text)でテキスト入力欄に入力をします。
ラジオボタンはframe.click(selector)で選択します。
セレクトボックスの操作には専用のframe.select(selector, ...values)というAPIが用意されています。
valuesにはoption要素で指定するvalue属性の値を指定します。例えばここでは11を指定すると、埼玉県を選択したことになります。

4. 「確認」画面のスクリーンショットを取得する

確認画面は以下に示すようにスクロールさせないと全ての項目が表示されません。
このままスクリーンショットを取ってしまうと「同伴者の氏名・性別・年齢」の部分が切れてしまいます。

confirm.gif

そこで、「氏名」欄が一番上に来るところまでスクロールさせてからスクリーンショットを取得するようにしています。
以下のコードがその部分です。
frame.evaluate(pageFunction)pageFunctionで渡した関数をブラウザのコンテキストで実行します。
Node.jsのコンテキストではdocument.querySelectorはありませんが、この関数はブラウザ上で実行されるので問題なく動作します。

await frame.evaluate(() => {
  const name = document.querySelector('.formDiv');
  name.scrollIntoView();
});

確認画面のスクリーンショットは以下のようになります。
※実際に取得される画像は全画面ですが、ここではフォーム部分だけ切り取っています。

image.png

まとめ

puppeteerはE2Eテストで使うものとして認知されていると思いますが、今回のようにちょっとしたライフハックにも使用できる便利なライブラリです。
是非みなさんもpuppeteerを使ってみてください。

takehilo
iOSアプリ開発エンジニア note: https://note.mu/takehilo 個人開発アプリ: https://apple.co/2S9HRR4
uzabase
企業活動の意思決定を支える情報インフラの提供
https://www.uzabase.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした