#javascript #puppeteer
#javascript #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>
Я пробовал несколько разных способов, но безуспешно, например, чтобы получить заголовок «Название пользователя», это последние попытки:
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;
})
});
что дает мне «Заголовок не определен» .. если я его привяжу .. он действует так, как будто код внутри evaluate вообще не запускается (даже консоль.журнал вверху не отображается), и
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
mess) дает мне Cannot read property 'trim' of undefined
, если я выхожу из li
системы в первой строке some
… Я получаю объект ElementHandle.
Ответ №1:
Вы пытаетесь передать переменную ( 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);
Комментарии:
1. Спасибо, Томас, мне просто нужно было перейти
document.querySelectorAll
наquerySelector
, и теперь это работает для меня. (querySelectorAll
возвращает anodeList
, у которого нетElement
функций, поэтому произойдет сбой приheaderDom.querySelectorAll
)