#node.js #web-scraping #puppeteer
#node.js #очистка веб-страниц #puppeteer
Вопрос:
Мне нужно очистить данные продуктов из списка, но данные находятся на страницах этих продуктов. Например, допустим, я хотел бы получить .product-image
страницу продукта.
Код до сих пор успешно извлекает каждый URL и добавляет в массив, но я не уверен, куда идти дальше, так как использование по какой-то причине page
возвращает Error: Evaluation failed: ReferenceError: page is not defined
при использовании его вне urls
.
const page = await browser.newPage();
page.waitForNavigation({ timeout: 0, waitUntil: "domcontentloaded" });
await page.goto(siteSearchUrl 1);
await page.screenshot({ path: "carpet.png" });
const urls = await page.evaluate(() => {
const items = document.querySelectorAll("li.product-item");
const productLinks = [];
console.log(page);
items.forEach((item) => {
const productLink = item
.querySelector("a.product-image") // NOT the product image, it's the link.
.getAttribute("href");
productLinks.push(`${siteUrl productLink}`);
});
productLinks.forEach((link) => {
page.screenshot({ path: link ".png" });
}, page);
});
await browser.close();
return Promise.resolve(urls);
})();
Как именно мне собирать данные по каждой из ссылок?
Ответ №1:
Невозможно использовать page
внутри page.evaluate
.
Вы получаете, ReferenceError: page is not defined
из-за page.evaluate
выполнения сценария в контексте страницы (например, вы console.log(page)
вошли в консоль Chromium, а не в консоль узла), другие методы puppeteer (например, page.screenshot
) не могут быть запущены на стороне клиента, но только в puppeteer. Поэтому вам нужно переместить его наружу.
Например.:
const urls = await page.evaluate(() => {
const productLinks = []
...
productLinks.push(...)
...
return productLinks
})
for (const url of urls) {
await page.goto(url)
await page.screenshot({ path: url '.png' })
}
Редактировать
Я исправил приведенный выше пример. Вы можете обнаружить, что можете решить проблему, используя page.$eval
, page.$$eval
более лаконично.
const hrefs = await page.$$eval('li.product-item > a.product-image', elements => elements.map(el => el.href))
const urls = hrefs.map(el => siteUrl el)
for (const url of urls) {
await page.goto(url)
await page.screenshot({ path: url '.png' })
}
Комментарии:
1. Не будет
productLinks
быть udefined внутриpage.evaluate()
и впоследствии пустым без переноса массива между контекстами?2. верно. действительно, я забыл, что сложно заполнить массив из контекста страницы. Я переделаю свой пример, чтобы он работал.
3. Спасибо за помощь! У меня есть один запрос — как будет выглядеть разбивка на страницы в вашем коде? Запрос для разбивки на страницы ?страница= 1.
4. вау, я думаю, что это заслуживает нового вопроса, я не уверен, что мой комментарий будет полезен для достижения того, что вам нужно. puppeteer не всегда учитывает параметры GET в URL. если вы хотите перевернуть страницу после завершения очистки текущей страницы, вы можете просто нажать на кнопку «Следующая страница», как это делает реальный пользователь:
await page.click('.next-page-btn')