我有几段代码是从HTML那里获取数据的,这些HTML的数据检索结构不是很好,例如:
列表中的项目可能并不总是处于同一位置...所以我必须查看li > span
中的数据,以查看我是否在正确的位置。
<div id="j-profile-header-details" class="vcard font-color-white">
<h1 class="fn n font-color-white">User Name</h1>
<ul>
<li><span class="font-color-meta-light">Title</span><a href="/foobar" class="url font-color-normal">User Title</a><span class="jive-orgchart-recenter font-color-meta"><a href="/foobar" class="font-color-meta-light" title="view in orgchart"><span class="jive-icon-sml jive-glyph-orgchart"></span></a>
</span>
</li>
<li><span class="font-color-meta-light">Phone Number</span>+1(555) 5555555</li>
<li><span class="font-color-meta-light">Email</span><a href="mailto:foo@bar.com" class="font-color-normal">foo@bar.com</a></li>
<li><span class="font-color-meta-light">Manager</span>Bar, Foo</li>
</ul>
</div>
例如,为了获得标题“ User Title”,我尝试了几种不走运的方法,这是最新的尝试:
const headerDom = await profilePage.$(PROF_PAGE_HEADER_DETAILS_SELECTOR);
let title = "";
await profilePage.evaluate(() => {
Array.from(headerDom.querySelectorAll('li')).some(li => {
if (li.querySelector('span').textContent.trim().toLowerCase() === "title") {
title = li.querySelector('a').textContent.trim();
return true;
}
return false;
})
});
这给了我“ headerDom未定义” ..如果我将其绑定..它的作用就像评估中的代码根本无法运行(即使顶部的console.log也没有显示),和
const headerDom = await profilePage.$(PROF_PAGE_HEADER_DETAILS_SELECTOR);
let title = "";
(await headerDom.$$("li")).some(async li => {
if ((await li.$eval('span', ele => ele.textContent)).trim().toLowerCase() === "title") {
title = (await li.$eval('a.url', ele => ele.textContent)).trim();
return true;
}
return false;
});
如果我在await
的第一行中注销async
,除了(Cannot read property 'trim' of undefined
/ li
混乱之外)还会给我some
...我得到一个ElementHandle对象。
答案 0 :(得分:2)
您正试图将变量(headerDom
)从Node.js环境传递到浏览器上下文,反之亦然(title
)。
为此,您需要像这样将其作为参数传递:
await page.evaluate(element => { ... }, elementHandle);
这会将元素(句柄)从Node.js环境传递到浏览器上下文。但是我不建议这样做,最好将选择器从Node.js上下文传递到脚本,然后在其中执行所有操作。
此外,您不能像这样将title
传递回Node.js脚本。 page.evaluate仅将返回值传递回脚本。该功能在其他执行上下文(浏览器)中运行。
将所有内容合并在一起,代码可能如下所示:
const title = await profilePage.evaluate((PROF_PAGE_HEADER_DETAILS_SELECTOR) => {
let title = "";
const headerDom = document.querySelector(PROF_PAGE_HEADER_DETAILS_SELECTOR);
Array.from(headerDom.querySelectorAll('li')).some(li => {
if (li.querySelector('span').textContent.trim().toLowerCase() === "title") {
title = li.querySelector('a').textContent.trim();
return true;
}
return false;
})
return title;
}, PROF_PAGE_HEADER_DETAILS_SELECTOR);