Проблема:
Контекст выполнения был разрушен, скорее всего, из-за навигации.
Ошибка говорит о том, что вы хотите нажать на какую-то ссылку или сделать что-то с нейстраница, которая больше не существует, скорее всего из-за того, что вы ушли.
Логика:
Думайте о сценарии кукловода как о реальном человеке, просматривающем настоящую страницу.
Сначала мы загружаем URL (https://stackoverflow.com/questions/tagged/web-scraping).
. Далее мы хотим просмотреть все вопросы, заданные на этой странице. Чтобы сделать то, что мы обычно делаем? Мы сделаем одно из следующих действий:
- Откройте одну ссылку на новой вкладке . Сфокусируйтесь на этой новой вкладке, завершите нашу работу и вернитесь к исходной вкладке. Продолжите следующую ссылку.
- Мы нажимаем на ссылку, делаем свое дело, возвращаемся на предыдущую страницу , продолжаем следующую.
Таким образом, оба они предполагают отход от и возвращение ктекущая страница.
Если вы не выполните этот поток, вы получите сообщение об ошибке, как указано выше.
Решение
Существует как минимум 4 или более способов решенияэто. Я пойду с самыми простыми и сложными.
Путь: извлечение ссылок
Сначала мы извлекаем все ссылки на текущей странице.
const links = await page.$$eval(".hyperlink", element => element.href);
Это дает намсписок URL. Мы можем создать новую вкладку для каждой ссылки.
for(let link of links){
const newTab = await browser.newPage();
await newTab.goto(link);
// do the stuff
await newTab.close();
}
Это будет проходить по каждой ссылке по одной.Я мог бы улучшить это, используя обещание.map и различные библиотеки очередей, но вы поняли идею.
Способ: возвращение на главную страницу
Нам нужно как-то сохранить состояние, чтобы мы могли знатькакую ссылку мы посетили в прошлый раз.Если мы посетили третий вопрос и вернулись на страницу тега, нам нужно в следующий раз перейти к четвертому вопросу и наоборот.
Проверьте следующий код.
const puppeteer = require("puppeteer");
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto(
`https://stackoverflow.com/questions/tagged/web-scraping?sort=newest&pagesize=15`
);
const visitLink = async (index = 0) => {
await page.waitFor("div.summary > h3 > a");
// extract the links to click, we need this every time
// because the context will be destryoed once we navigate
const links = await page.$$("div.summary > h3 > a");
// assuming there are 15 questions on one page,
// we will stop on 16th question, since that does not exist
if (links[index]) {
console.log("Clicking ", index);
await Promise.all([
// so, start with the first link
await page.evaluate(element => {
element.click();
}, links[index]),
// either make sure we are on the correct page due to navigation
await page.waitForNavigation(),
// or wait for the post data as well
await page.waitFor(".post-text")
]);
const currentPage = await page.title();
console.log(index, currentPage);
// go back and visit next link
await page.goBack({ waitUntil: "networkidle0" });
return visitLink(index + 1);
}
console.log("No links left to click");
};
await visitLink();
await browser.close();
})();
Результат: ![enter image description here](https://i.stack.imgur.com/9YLbs.png)
РЕДАКТИРОВАТЬ: Есть несколько вопросов, похожих на этот.Я буду ссылаться на них, если вы хотите узнать больше.