Кукловод продолжает получать TimeoutError: Превышен тайм-аут навигации 80000 мс - PullRequest
0 голосов
/ 19 июня 2020

Я пытаюсь очистить любую веб-страницу, переданную как функцию очистки, но независимо от тайм-аута, установленного в page.goto (), я продолжаю получать ошибку тайм-аута, если установлено значение 0, приложение просто продолжает ждать.

const express = require('express');
const cors = require('cors');
const MYPORT = process.env.PORT || 4001;


const app = express();
const puppeteer = require('puppeteer');

app.use(express.json());
app.use(cors());

const scrape = async (url) => {
    var body;
    try {
        const browser = await puppeteer.launch({
            headless: true,
            args: ['--no-sandbox'],
            timeout: 0
        });
        console.log('Browser launched');
        const page = await browser.newPage();
        console.log('Page opened');
        await page.goto(url, { waitUntil: 'load', timeout: 3 * 60000 });
        await page.waitForSelector('body', {waitUntil: 'load'})
        console.log('Link opened');
        await page.waitForNavigation({waitUntil: 'networkidle2', timeout: 3 * 60000});
        page.$eval('html', bdy => {
            console.log(bdy);
            body = bdy.innerHTML;
        });
        browser.close();
        return body;
    } catch (err) {
        console.log(err);
    }
};

scrape('http://google.com');

Пожалуйста, что я делаю не так?

Я использую Ubuntu 18.04 на WSL (Windows Подсистема для Linux)

1 Ответ

0 голосов
/ 19 июня 2020

Вы немного усложнили время ожидания для части вашего скрипта. Я рекомендую следующие изменения:

  1. Если вы не уверены, что вызывает тайм-аут, вы должны установить headless: false, чтобы вы могли видеть в пользовательском интерфейсе, что идет не так, вы можете открыть консоль браузера et c.
  2. Не устанавливайте тайм-ауты, пока сценарий не сделает то, что вы хотите, с помощью waitForSelector -s. Я удалил их из вашего скрипта.
  3. Если вас не интересуют все сетевые события (особенно не аналитика и запросы отслеживания), а вам нужна только DOM, тогда используйте waitUntil: 'domcontentloaded' вместо load или самый строгий networkidle2! Посмотрите, в чем точное различие между ними, в документации: [ссылка]
  4. Не waitForNavigation после того, как вы уже подождали селектор. Это была основная причина неудачи вашего скрипта: как только <body> появился в DOM, вы попросили кукловода дождаться завершения навигации, но вы не выполняли навигацию в это время: вы уже были на странице. Имейте в виду:

    page.waitForNavigation разрешается, когда страница переходит на новый URL-адрес или перезагружается. Это полезно, когда вы запускаете код, который косвенно вызывает навигацию по странице. [источник]

  5. Ваш page.eval$ не обладал своей асинхронной c природой, тогда как он всегда должен быть асинхронным c. В любом случае innerHTML из <body> можно получить проще с помощью: await page.evaluate(el => el.innerHTML, await page.$('body')).
const scrape = async url => {
  try {
    const browser = await puppeteer.launch({
      headless: false,
      args: ['--no-sandbox']
    })
    console.log('Browser launched')
    const page = await browser.newPage()
    console.log('Page opened')
    await page.goto(url, { waitUntil: 'domcontentloaded' })
    await page.waitForSelector('body')
    console.log('Link opened')
    const body = await page.evaluate(el => el.innerHTML, await page.$('body'))
    console.log(body)
    browser.close()
    return body
  } catch (err) {
    console.log(err)
  }
}
...