使用以下 html:
<div class="borderTopWhite item-sub-details">
<ul>
<li>Sport: <a href="#">Baseball</a></li>
<li>Team:
<a href="#">Philadelphia Phillies</a>
</li>
</ul>
</div>
我的目标是获得Team的文本。在上面的例子中,我想退回费城费城人队。
我的(失败)尝试返回空对象:
const details = await page.$$eval(
'.item-sub-details ul li',
els => els.map(el => el)
)
尝试通过文本
Team:
选择来获取父元素,然后查询其中的<a>
:
const puppeteer = require("puppeteer"); // ^22.6.0
const url = "<Your URL>";
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.setJavaScriptEnabled(false);
await page.setRequestInterception(true);
page.on("request", req => {
if (req.url() === url) {
req.continue();
} else {
req.abort();
}
});
await page.goto(url, {waitUntil: "domcontentloaded"});
const team = await page.$eval(
"li::-p-text('Team:')",
el => el.querySelector("a").textContent
);
console.log(team); // => Oakland Athletics
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
请注意,您不需要 Puppeteer,因为数据位于静态 HTML 中。这就是为什么我在上面的代码中阻止了所有请求并禁用了 JS。只需使用 fetch 和轻量级 HTML 解析器 Cheerio:
const cheerio = require("cheerio"); // ^1.0.0-rc.12
const url = "<Your URL>";
fetch(url)
.then(res => {
if (!res.ok) {
throw Error(res.statusText);
}
return res.text();
})
.then(html => {
const $ = cheerio.load(html);
const team = $("li:contains(Team:)").find("a").text();
console.log(team); // => Oakland Athletics
})
.catch(err => console.error(err));
取来并欢呼:
real 0m1.158s
user 0m0.315s
sys 0m0.043s
优化的傀儡师:
real 0m1.489s
user 0m0.650s
sys 0m0.174s
未优化的 Puppeteer(禁用 JS 和请求拦截):
real 0m2.260s
user 0m0.980s
sys 0m0.263s