查询选择器
查询是与网站 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
,但 custom-element >>>> h2
将返回空,因为内部的 h2
在更深的阴影根中。
P
元素
P
元素是 伪元素,带有 -p
供应商前缀。它允许您使用 Puppeteer 特定的查询引擎(如 XPath、文本查询和 ARIA)来增强您的选择器。
文本选择器 (-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;
}
}