使用 puppeteer 从未知的 li 中检索数据

Retrieving data from unknown li with puppeteer

我有几个代码块,我从 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 is not defined".. 如果我将它绑定在.. 它就像评估中的代码根本没有得到 运行 (即使 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;
  });

如果我在 [=18] 的第一行注销 li,这(除了是 await/async 混乱之外)给我 Cannot read property 'trim' of undefined =]...我得到一个 ElementHandle object.

您正在尝试将变量 (headerDom) 从 Node.js 环境传递到您的浏览器上下文,反之亦然 (title)。

为此,您需要像这样将其作为参数传递:

await page.evaluate(element => { ... }, elementHandle);

这会将元素(句柄)从您的 Node.js 环境传递到您的浏览器上下文。但我不建议这样做,最好将你的选择器从你的 Node.js 上下文传递到你的脚本,然后在那里执行所有内容。

此外,您不能像那样将 title 传回您的 Node.js 脚本。 page.evaluate 只会将 return 值传递回您的脚本。该函数在不同的执行上下文(浏览器)中 运行。

将所有内容合并在一起,代码可能如下所示:

  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);