我正在用 Puppeteer 抓取一堆页面。内容不区分类/ID/等。并且在页面之间以不同的顺序呈现。因此,我需要根据元素的内部文本来选择元素。我在下面包含了一个简化的示例 html:
<table>
<tr>
<th>Product name</th>
<td>Shakeweight</td>
</tr>
<tr>
<th>Product category</th>
<td>Exercise equipment</td>
</tr>
<tr>
<th>Manufacturer name</th>
<td>The Shakeweight Company</td>
</tr>
<tr>
<th>Manufacturer address</th>
<td>
<table>
<tr><td>123 Fake Street</td></tr>
<tr><td>Springfield, MO</td></tr>
</table>
</td>
</tr>
在这个例子中,我需要抓取制造商名称和制造商地址。所以我想我需要根据嵌套 th 的内部文本选择适当的 tr 并在同一个 tr 中刮掉相关的 td。请注意,该表的行顺序并不总是相同,并且该表包含的行比这个简化示例多得多,所以我不能只选择第 3 和第 4 个 td。
我尝试使用 XPATH 选择基于内部文本的元素,如下所示,但它似乎不起作用:
var manufacturerName = document.evaluate("//th[text()='Manufacturer name']", document, null, XPathResult.ANY_TYPE, null)
这甚至不是我需要的数据(它将是与此相关的 td),但我认为这至少是第 1 步。如果有人可以提供有关通过内部文本选择或选择与此相关联的 td 的策略的输入,我将非常感激。
最佳答案
这确实是一个 xpath 问题,并不特定于 puppeteer,所以这个问题也可能会有所帮助,因为您需要找到 <td>
出现在 <th>
之后您已找到:XPath:: Get following Sibling
但是您的 xpath 确实对我有用。在您问题中包含 HTML 的页面上的 Chrome DevTools 中,运行以下行来查询文档:
$x('//th[text()="Manufacturer name"]')
注意:$x()
是一个仅在 Chrome DevTools 中有效的辅助函数,虽然 Puppeteer 有一个类似的 Page.$x
功能。该表达式应该返回一个包含一个元素的数组,
<th>
在查询中使用该文本。获取 <td>
在它的旁边:$x('//th[text()="Manufacturer name"]/following-sibling::td')
并获取其内部文本:$x('//th[text()="Manufacturer name"]/following-sibling::td')[0].innerText
一旦您能够遵循该模式,您应该能够使用类似的策略在 puppeteer 中获取您想要的数据,类似于:const puppeteer = require('puppeteer');
const main = async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://127.0.0.1:8080/'); // <-- EDIT THIS
const mfg = await page.$x('//th[text()="Manufacturer name"]/following-sibling::td');
const prop = await mfg[0].getProperty('innerText');
const text = await prop.jsonValue();
console.log(text);
await browser.close();
}
main();
关于javascript - Puppeteer - 如何根据内部文本选择元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64048744/