Edited at

puppeteerでよく使うであろう処理の書き方

puppeteer

https://github.com/GoogleChrome/puppeteer/releases

puppeteerを触ってみて自分がよく使う書き方を載せたら

これから始めてみようかなって人に需要あるんじゃないかと書いてみます


Basic認証突破

const USERNAME = 'user';

const PASSWORD = 'passwd';
await page1.setExtraHTTPHeaders({
Authorization: `Basic ${new Buffer(`${USERNAME}:${PASSWORD}`).toString('base64')}`
});


ページ移動

await page.goto("https://qiita.com/", {waitUntil: "domcontentloaded"});

第二引数のwaitUntilオプションなしで次にセレクタに関する処理を書くと

ページを読み込む前に処理が走ってセレクタを取得できずエラーになったりするので

DOM読み込み完了を待たせます


タブ切り替え

const page1 = await browser.newPage();

const page2 = await browser.newPage();
await page1.bringToFront();

2個タブ開いて1個目のタブに戻る


入力

await page.type("#loginid", "input");

id="loginid"の入力欄にinputって入力してくれます


セレクトボックスから選択

await page.select('select[name="birthday_month"]', '12');

value="12"のoption要素を選択します


クリック

page.click('a[href^="index.php?query="]');

正規表現も使えるので^=って書くと前方一致で探せます

index.php?query=から始まるhref属性を持つaタグをクリックしてくれます


フォーム送信

await page.evaluate(({}) => {

$('input[name="mode"]').parent("form").submit();
},{});

<input type="hidden" name="mode" value="submit">

みたいな要素を含むformをsubmitしてくれます

id属性がないフォームが並んでたりするときは無理やりsubmitボタンをクリックさせるより

submitさせる方が便利だったりします


ページ遷移を待つ

page.click('a[href="index.php"]');

await page.waitForNavigation({timeout: 60000, waitUntil: "domcontentloaded"});

page.waitFor(3000)みたいに待つのはちょっとかっこ悪いのでページ遷移を検知させます

page.waitForNavigationの方だけawaitさせるのがポイントです


遷移を待つ その2

await page.click('a[href="login.php"]');

await page.waitFor('a[href="mypage.php"]', {timeout: 120000});

遷移先の要素が取得できるようになるまで待たせる、というやり方です

いっぱいリダイレクトしてある要素のあるページにたどり着く、みたいな時はこれですかね


CSSを操作

await page.evaluate(({}) => {

$('#slider').css("display", "block");
},{});

アコーディオンとかはクリックさせて開くか、cssを直接いじるか

隠れてる入力欄に入力とかさせる分には困らないんですが

ヘッドレスモードオフで画面見ながら動かしたい時はこうやって表示させたり


valueの取得

var login_id = await page.$eval('input[name="login_id"]', el => el.value);

readonlyの入力欄から値を取ったりhidden属性のinput要素から値を取るにはこれ


要素内のテキストを取得

var data = await page.$eval('.classname', item => {

return item.textContent;
});

<div class="classname"></div>とかで囲まれているテキストを取る時はこれ

API一覧見るともっともっとたくさんありますが

この辺の書き方使えばそれなりに事足りるかなと