クエリセレクター
クエリは、サイト上のDOMと対話するための主要なメカニズムです。たとえば、典型的なワークフローは次のようになります。
// Import puppeteer
import puppeteer from 'puppeteer';
(async () => {
// Launch the browser
const browser = await puppeteer.launch();
// Create a page
const page = await browser.newPage();
// Go to your site
await page.goto('YOUR_SITE');
// Query for an element handle.
const element = await page.waitForSelector('div > .class-name');
// Do something with element...
await element.click(); // Just an example.
// Dispose of handle
await element.dispose();
// Close browser.
await browser.close();
})();
P
セレクター
Puppeteerは、クエリにCSSセレクター構文のスーパーセットを使用します。この構文をPセレクターと呼び、ディープコンビネーターやテキスト選択などの追加機能で強化されています。
Pセレクターは実際のCSSセレクターのように見えますが(意図的にこのように設計しました)、実際にCSSスタイルに使用するべきではありません。これらはPuppeteer専用に設計されています。
Pセレクターは、セレクターの最初の「深さ」でのみ機能します。たとえば、:is(div >>> a)
は機能しません。
>>>
と>>>>
コンビネーター
>>>
と>>>>
は、それぞれディープ子孫とディープコンビネーターと呼ばれます。どちらのコンビネーターも、>>>
がノードの下のすべてのシャドウホストに移動し、>>>>
が(ノードがシャドウホストである場合は)直近のシャドウホストに移動する効果があります。それ以外の場合は、何もしません。
>>>
の柔軟性を考慮すると、いつ>>>>
を>>>
よりも選択すべきかというよくある質問があります。>
とスペースについても同様の質問ができます。特定のノードの下のすべての要素をクエリする必要がない場合は>
を選択し、それ以外の場合はスペースを選択します。この答えは、>>>>
(>
)と>>>
(スペース)に自然に拡張されます。
例
次のマークアップがあるとします。
<custom-element>
<template shadowrootmode="open">
<slot></slot>
</template>
<custom-element>
<template shadowrootmode="open">
<slot></slot>
</template>
<custom-element>
<template shadowrootmode="open">
<slot></slot>
</template>
<h2>Light content</h2>
</custom-element>
</custom-element>
</custom-element>
注:
<template shadowrootmode="open">
はFirefoxではサポートされていません。詳細についてはこちらをご覧ください。
この場合、custom-element >>> h2
はh2
を返しますが、内側のh2
はより深いシャドウルートにあるため、custom-element >>>> h2
は何も返しません。
P
-要素
P
要素は、-p
ベンダープレフィックスが付いた疑似要素です。これにより、XPath、テキストクエリ、ARIAなどのPuppeteer固有のクエリエンジンを使用してセレクターを強化できます。
テキストセレクター(-p-text
)
テキストセレクターは、(開いている)シャドウルート内であっても、指定されたテキストを含む「最小」要素を選択します。ここで、「最小」とは、指定されたテキストを含む最も深い要素であり、その親(技術的には指定されたテキストも含む)ではないことを意味します。
例
const element = await page.waitForSelector('div ::-p-text(My name is Jun)');
// You can also use escapes.
const element = await page.waitForSelector(
':scope >>> ::-p-text(My name is Jun \\(pronounced like "June"\\))'
);
// or quotes
const element = await page.waitForSelector(
'div >>>> ::-p-text("My name is Jun (pronounced like \\"June\\")"):hover'
);
XPathセレクター(-p-xpath
)
XPathセレクターは、ブラウザのネイティブなDocument.evaluate
を使用して要素をクエリします。
例
const element = await page.waitForSelector('::-p-xpath(h2)');
ARIAセレクター(-p-aria
)
ARIAセレクターは、指定されたARIAラベルを持つ要素を見つけるために使用できます。これらのラベルは、Chromeの内部表現を使用して計算されます。
例
const node = await page.waitForSelector('::-p-aria(Submit)');
const node = await page.waitForSelector(
'::-p-aria([name="Click me"][role="button"])'
);
カスタムセレクター
Puppeteerは、Puppeteer.registerCustomQueryHandlerを使用して独自のクエリセレクターをPuppeteerに追加する機能を提供します。これは、フレームワークオブジェクトまたはその他のベンダー固有のオブジェクトに基づいてカスタムセレクターを作成する場合に役立ちます。
カスタムセレクター
カスタムセレクターを作成できるカスタムクエリハンドラーを登録できます。たとえば、getById
セレクターのクエリハンドラーを定義します。
Puppeteer.registerCustomQueryHandler('getById', {
queryOne: (elementOrDocument, selector) => {
return elementOrDocument.querySelector(`[id="${CSS.escape(selector)}"]`);
},
// Note: for demonstation perpose only `id` should be page unique
queryAll: (elementOrDocument, selector) => {
return elementOrDocument.querySelectorAll(`[id="${CSS.escape(selector)}"]`);
},
});
これで、次のように使用できます。
const node = await page.waitForSelector('::-p-getById(elementId)');
// OR used in conjunction with other selectors
const moreSpecificNode = await page.waitForSelector(
'.side-bar ::-p-getById(elementId)'
);
カスタムフレームワークコンポーネントセレクター
ライブラリまたはフレームワークの内部APIに依存する場合は注意してください。これらはいつでも変更される可能性があります。
クエリにVue内部を使用することにより、名前でVueコンポーネントを見つけます。
Puppeteer.registerCustomQueryHandler('vue', {
queryOne: (element, name) => {
const walker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT);
do {
const currentNode = walker.currentNode;
if (
currentNode.__vnode?.ctx?.type?.name.toLowerCase() ===
name.toLocaleLowerCase()
) {
return currentNode;
}
} while (walker.nextNode());
return null;
},
});
次のようにVueコンポーネントをクエリします。
const element = await page.$('::-p-vue(MyComponent)');
Webコンポーネント
Webコンポーネントは独自のタグを作成するため、タグ名でクエリできます。
const element = await page.$('my-web-component');
カスタムタグの型を定義するには、HTMLElementTagNameMap
を拡張します。これにより、PuppeteerはElementHandleの戻り値の型を推論できます。
declare global {
interface HTMLElementTagNameMap {
'my-web-component': MyWebComponent;
}
}