【发布时间】:2021-07-13 14:25:14
【问题描述】:
我有以下 html:
<article data-tid="product-detail"> <!-- I page.$eval on this element. -->
<h1 itemprop="name">Product name</h1> <!-- This I can query by itemprop -->
<h2>Some other topic</h2>
<p>I don't want this text.</p>
<h2>Unique topic</h2> <!-- I can find this innerText === "Unique topic". -->
<p>Text I want real' bad.</p> <!-- I want this innerText. -->
<h2>Some other topic</h2>
<p>I don't want this text.</p>
</article>
如何获得“我想要真正的'不好的文字”。从页面,知道“独特的主题”?
我从节点脚本运行 puppeteer。
这是我目前所拥有的:
async function puppeteerProductDataExtractor($product) {
// This works like charm.
const productName = $product.querySelector('[itemprop=name]')?.innerText;
// Now I have to find the right h2 and get it's next element sibling.
const h2 = $product.querySelectorAll('h2');
// 1. If I try to get innerText of all h2, it fails with getProperty function not defined.
console.log(
await Promise.all([...h2].map(async $el => await (await element.getProperty('innerText')).jsonValue()))
);
// 2. This returns empty array
console.log([...h2].filter($el => $el.innerText.startsWith('Unique topic')));
// This prints JSHandle@array - innerText is not a string.
console.log([...h2].map($el => $el.innerText));
// This also prints JSHandle@array which is just insane.
console.log([...h2].map($el => Object.keys($el)));
// This fails with "property is not a function" error.
console.log([...h2].map(el => el.property('innerText')));
// So does this.
console.log([...h2].map(el => el.getProperty('innerText')));
}
page.on('console', consoleObj => console.log('xxxx', consoleObj.text()));
const product = await page.$eval('article[data-tid=product-detail]', puppeteerProductDataExtractor);
第一次尝试来自这里:https://stackoverflow.com/a/52828950/336753
其他一切都只是沮丧的盲目射击。必须承认我很困惑。有些东西应该根据文档工作,但它只是失败了。像 JSHandle should have the property function,但是当我调用它时它失败了(不是函数)。
我什至没有进入 nextSibling 部分。
我尝试了很多代码,但大部分都失败了,不想用它污染问题。感觉这应该很简单,我只是错过了一些东西。希望初衷清晰。
我确信有一个简单的解决方案,但尝试和失败似乎不是解决问题的方法。
经过更多挖掘,事实证明我的初衷是正确的。 filter() 不起作用不是因为 innerText 将是 JSHandle 的实例(如它所显示的那样),而是因为大写的第一个字母是由 CSS 完成的(在比较之前必须小写以统一字符串)。有点惭愧……抱歉,感谢@ggorlen 的帮助。
/* WE'RE INSIDE $eval FUNCTION */
// This returns JSHandle@array which is just weird...
console.log([...h2].map(el => el.innerText));
// But this returns the joined string correctly. Huh...
console.log([...h2].map(el => el.innerText).join(';'));
// So this eventually works
console.log([...h2]
.filter(el => el.textContent.toLowerCase().startsWith('unique topic'))[0]?
.nextElementSibling.textContent);
【问题讨论】:
标签: puppeteer