puppeteer のワザ
ページの目的
ワザ一覧
POST リクエストでページ遷移する
通常、 page.goto() メソッドでは GET リクエストしかできない。しかし、ページによっては POST リクエストによって遷移したい場合がある。そのような時の対処法。
方法1: request interception を使って、メソッドやリクエストボディを書き換える
code: interception.ts
await page.setRequestInterception(true);
page.on('request', (interceptedRequest) => {
void interceptedRequest.continue({ method: 'POST', postData: JSON.stringify(reqBody) });
});
await page.goto(url)
await page.setRequestInterception(false);
方法2: form の html を自前で作って page に埋め込んで送信
code: html埋め込み.ts
const post = async (page: Page, url: string, formData: URLSearchParams) => {
const formDataEntries = formData.entries();
let formHtml = '';
formHtml += `
<input
type='hidden'
name='${name}'
value='${value}'
/>
`;
}
formHtml = `
<form action='${url}' method='post'>
${formHtml}
<input type='submit' />
</form>
`;
await page.setContent(formHtml);
await inputElement.click();
};
愚直にやると”危ない” HTML を埋め込んでしまう可能性があるので非推奨。
参考
安全に DOM を click する
puppeter の 愚直に page.click("selector~~") をすると、click したい DOM の前に他の DOM が描画されてるときにそいつがクリックされてしまう。
page.$evaluate("selector~~", (el) => el.click()) すると確実に所望の element の click event を発火できるんで便利
ほしいとこだけ pdf にする
TBW
localStorage の内容を取得・復元する
TBW
ブラウザで表示されるダイアログに対してアクションを起こす。
beforeunload などで出てくる「ページを離れますか?」みたいなダイアログは DOM が存在しないので普通にやるとクリックなどができずそこで操作が止まる。
code: typescript
await page.on('dialog', async (dialog) => {
await dialog.accept();
});
こんな感じで、dialog が出たときのアクションを指定できる。
dismiss とかもある。
Docker コンテナ内でヘッドレスブラウザを立ち上げると、OS の言語設定が読み込まれるせいで input field が英語圏のものになってしまったりする。
これはブラウザの動作なので、Accept-Language などで対応できるものではない。
input[type="date"] とか、年月日の順序が変わるせいで puppeteer での入力が変になったりする。
OS にもよるが、LANG: ja_JP.UTF-8 とか LANGUAGE: ja_JP:ja の環境変数を指定してやると日本語になる。
要素をテキストで検索する
code:typescript
const elem = page.$(cssSelector);
elem.$x(.//text()[contains(., "${selectorText}")]/parent::node());
上のようにすると特定の css を持ち、かつその innerText が selectorText であるような要素を取得できる。
不可視な要素を区別する
puppeteer.ElementHandle<Element> は boundingBox() メソッドを持っており、要素が visible でないときはこれが null を返す。それを以って不可視な要素かどうかを大体判定できる。