【Puppeteer】Chromeのお手軽自動化(2) 要素の操作

こんにちは、自動化エンジニアをしています。kozuです。

PCでのインターネットのブラウザは何を使用しているでしょうか。仕事の業務システムではIEが使われることはありますが、特に指定がない場合はほとんどの人がChromeを使用していると思います。

Chromeを自動操作する方法はいくつかありますが、Node.jsのライブラリ「Puppeteer」について開発方法を紹介します。実際のWebサイトで自動操作と情報を取得するプログラムの開発を通して、自動化ツールの開発について学ぶことができます。

PuppeteerというライブラリはGoogleのChromeを開発しているチームで開発されています。そのため信頼性が高く、最近でも頻繁に更新されており将来的にも期待できます。環境の準備が楽で実装も簡単であるため、個人的には他のライブラリやツールよりも好んで使用しています。本連載では、Node.jsの環境の準備からコードの実装について順を追って解説しようと思います。

この章では、ページに表示されている要素(ボタンやテキストボックス)を操作する処理の実装方法について解説します。Puppeteerを実行する環境が準備できていない方は以下の記事を参考にしてください。

1.対象者

ブラウザで定期的に手作業で行っているデータ入力やデータ収集等の作業から開放されたい、楽したいと考えている方を対象に、Chromeの操作を自動化するツールの開発ができるようになることを目指しています。プログラミングの経験がない方でも、コードをコピーすれば開発できるようになっています。

2.開発環境

以下の環境を使用します。
・OS:Windows10
・ブラウザ:Chrome
・node
・npm

3.準備

今回はYahoo!路線情報のページを対象に、指定した経路の料金の最安値を調べる操作を実装します。まずは操作を開始するページを表示するコードを準備します。動作を確認するためにヘッドレスモードをfalseに設定し、最後のブラウザを閉じる処理はコメントにしています。

const puppeteer = require('puppeteer-core');

(async () => {
 const browser = await puppeteer.launch({
   executablePath: 'C:\\Program Files\ (x86)\\Google\\Chrome\\Application\\Chrome.exe',
   defaultViewport: null,
   headless: false
 });
 
 //新しいタブを開く
 const page = await browser.newPage();
 
 //URLにアクセス
 await page.goto('https://transit.yahoo.co.jp/');
 
 //await browser.close();
})();

画像1

4.要素の確認

Puppeteerでは基本的に「セレクタ(querySelectorメソッド)」で要素を特定します。要素のセレクタは開発者ツールで確認することができます。「F12」キーで表示された開発者ツールの左上(上の赤枠)をクリックし、確認したい要素(下の赤枠)をクリックしてください。

画像2

要素をクリックすると、開発者ツール内に表示されているHTMLの対象要素の背景が水色になります。背景色が水色の箇所で右クリック→「Copy」→「Copy selector」でセレクタのテキストがクリップボードにコピーされます。

同じ要素でもセレクタの指定方法はいくつもパターンがあり、この方法で取得したセレクタが最適でない場合が多いですが今回はそのままの値を指定します。

画像3

5.テキスト入力

テキストボックス「出発(駅)」「到着(駅)」にテキストを入力します。URLにアクセスする処理の後に以下のコードを追加してください。「page.type('{セレクタ}', '{入力文字}')」でpage(タブの画面)内の指定したセレクタ要素にテキストを1文字ずつ入力(タイピング)します。「await」は呼び出した処理が終わるまで待機するため基本的にメソッドの前につけます。

//「出発」に入力
await page.type('#sfrom', '東京');
//「到着」に入力
await page.type('#sto', '秋葉原');
//フォーカスを変更
await page.keyboard.press('Tab');

このメソッドで注意があります。最初から入力されている文字がある場合は後ろに追加で入力することになります。最初から入力する方法については別の記事で解説しようと思います。

最後にTabキーの押下を行っていますが、Yahoo!路線情報のページでは駅名のテキストボックスにフォーカスが入っているとプルダウンが表示されてしまいます。以降の処理に影響があるため、対策として入れています。

6.セレクトボックス選択

セレクトボックス「表示順序」の選択を行います。以下のコードを追加してください。「page.select('{セレクタ}', '{選択する値}')」でセレクトボックスの値を選択します。

//セレクトボックス「表示順序」選択
await page.select(
   '#mdRouteSearch > div.elmRouteSearch.noreg > form > div > div:nth-child(3) > dl.optSort > dd > select',
   '1');

ここで注意することがあります。{選択する値}は見えている文字ではなく、内部の値を指定する必要があります。開発者ツールでセレクトボックスのHTMLを確認すると、selectタグの中にoptionタグが複数含まれています。このoptionタグがセレクトボックスで選択できる値になります。optionタグの外側に表示されている文字(黒字)が画面に表示される文字になり、value="{値}"で表示されている文字(青字)が内部の値になります。したがって、指定する値は後者のvalue="{値}"の値になります。

Puppeteer標準のメソッドでは見えている文字を指定することはできないので、別の記事で実装方法を解説しようと思います。

画像4

7.ラジオボタンクリック

ラジオボタン「(日時)指定なし」のクリックを行います。以下のコードを追加してください。「page.click('{セレクタ}')」でラジオボタンをクリックします。手動のクリックと同様に、ラジオボタンをクリックすると同じグループのチェック箇所が1つだけになります。

//ラジオボタン「指定なし」クリック
await page.click('#tsAvr');

8.チェックボックスクリック

チェックボックス「(手段)空路」のクリックを行います。以下のコードを追加してください。「page.click('{セレクタ}')」でチェックボックスをクリックします。上記のラジオボタンと書き方は同じです。手動で操作した場合も同じであるため、感覚的にはわかりやすいと思います。

ここで注意が必要です。クリックはチェックの状態を切り替える操作であり、チェックの状態を指定することができません。チェック済みの状態でクリックするとチェックが外れ、チェックされていない状態でクリックするとチェックされることになります。したがって、画面を表示したときにチェックの状態がわかっていることが前提になります。Puppeteer標準のメソッドではチェックの状態を指定できないため、チェックの状態を指定する方法については別の記事で実装方法を解説しようと思います。

//ラジオボタン「空路」クリック
await page.click('#air');

9.ボタンクリック

ボタン「検索」のクリックを行います。以下のコードを追加してください。ここまで読んでいただいた方であればお分かりの通り、「クリック」の操作は同じメソッドを使用します。上記までで解説したチェックボックス、ラジオボタン以外の要素でも同様です。

ここで1つ注意があります。今回は検索ボタンをクリックすると画面の遷移が行われます。対象の要素が表示される前に次の操作が実行されるとエラーになってしまいます。そのため、クリックした後に画面遷移の完了を待つ必要があります。今回は詳しい解説は省きますが、以下のように実装することで画面遷移の完了を待つことができます。

//ボタン「検索」クリック
await Promise.all([
  page.waitForNavigation(),
  page.click('#searchModuleSubmit')
]);

10.テキストの取得

最後に、画面に表示されているテキスト「料金」を取得します。「page.$('{セレクタ}')」で要素のオブジェクトを1つだけ取得し、「page.evaluate()」で引数に指定した要素の「textContent」の値をテキストとして取得します。最後に確認用にテキストをコンソールに出力しています。

//テキスト「料金」取得
const elm = await page.$('#rsltlst > li:nth-child(1) > dl > dd > ul > li.fare > span');
const text = await page.evaluate(elm => elm.textContent, elm);
console.log(text);

今回は1つ目の料金を取得しましたが、同じ項目を繰り返し取得するにはセレクタの指定とメソッドを変更する必要がありますので、別の記事で解説しようと思います。

今回はpuppeteerでの基本的な操作について紹介しました。次回は待機について解説しようと思います。上記でも少し触れましたが、動作を安定させるためには必要な処理になります。



この記事が気に入ったらサポートをしてみませんか?