Ошибка оценки: ошибка в кукловоде и обработка ошибок - PullRequest
1 голос
/ 02 апреля 2019

Я разрабатываю приложение для парсинга с помощью Puppeteer, и оно работает хорошо.Но проблема в том, что это приложение иногда имеет ошибку, и я не знаю, почему эта ошибка возникает.

Мне нужно захватить около 90 000 данных.

Ошибка, вероятно, вызвана не чтениемсписок классов, но даже если я задаю опцию Безголовый для False и проверю, список классов существует.

Сначала он работает хорошо и случайным образом генерирует ошибки.

На мой взгляд, иногдастраница не загружается на сам сайт и продолжает останавливаться на панели загрузки, поэтому.

Даже если я даю networkidle0 или 2 в значении waitUntil, если этот прогноз верен, я незнать, как его обнаружить.

[полный код]

'use strict';

const puppeteer = require('puppeteer'); // Puppeteer 모듈 Load
(async () => {
    const browser = await puppeteer.launch({ // Puppeteer 모듈을 사용하지 않고 기존의 크롬 사용자 정보를 사용 (Auth 인증을 패스하기 위하여)
        executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
        userDataDir: 'C:\\User\\AppData\\Local\\Google\\Chrome\\User Data', // 설치시 개인 크롬 Directory로 수정하여야함
        headless: true
    });
    const page = await browser.newPage(); // Broswer Open
    await page.setViewport({ // Viewport 설정 가로의 경우 일반적으로 최대 1920, 새로의 경우 예상되는 최대 px를 지정해주면됨
        width: 800,
        height: 6000
    });
    page.on('dialog', async dialog => { // 삭제된 게시글의 경우 Band에서 Dialog를 띄우는데 이를 제거하기 위하여 필요
        console.log(dialog.message());
        await dialog.dismiss(); // Dialog 창 닫음
        await postNumber++; // 삭제된 게시글의 경우 Dialog 창이 닫힌후에 이전 URL로 돌아가므로 postNumber 1증가 시켜줌
        await page.goto(`https://band.us/band/58075840/post/${postNumber}`, {
            waitUntil: 'networkidle0'
        });
    })
    let postNumber = 14565; // 시작되는 PostNumber * 이 부분 부터 시작 *
    while (postNumber <= 90000) { // PostNumber 끝값 * 이 부분은 마지막 값 *
        await page.goto(`https://band.us/band/58075840/post/${postNumber}`, {
            waitUntil: 'networkidle0' // 페이지가 완전히 Load된후 작동
        });

        let by = await page.evaluate(() => document.getElementsByClassName('text')[0].innerText); // 게시글 작성자 Text 파싱
        let date = await page.evaluate(() => document.getElementsByClassName('time')[0].innerText); // 게시글 작성일 Text 파싱
        let element = await page.$('.boardList'); // 게시글, 댓글 전체 Class
        await element.screenshot({ // ScreenShot Function
            path: `./image/${postNumber}-${by}-${date.replace(":","_")}.png` // 파일 저장 위치 & 파일이름 지정, replace 메소드의 경우 Windows 탐색기에서 :를 파일명으로 지원하지 않기때문
        });
        console.log(`${postNumber}-${by}-${date.replace(":","_")}.png`) // Console.log에서 파일 확인
        await postNumber++; // 최종 성공시 postnumber 증가
    }
    await browser.close(); // 종료
})();

[сообщение об ошибке]


(node:16880) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'innerText' of undefined
    at __puppeteer_evaluation_script__:1:50
    at ExecutionContext.evaluateHandle (C:\Users\\Downloads\Projects\Bander-Statistics\node_modules\puppeteer\lib\ExecutionContext.js:121:13)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  -- ASYNC --
    at ExecutionContext.<anonymous> (C:\Users\\Downloads\Projects\Bander-Statistics\node_modules\puppeteer\lib\helper.js:108:27)
    at ExecutionContext.evaluate (C:\Users\\Downloads\Projects\Bander-Statistics\node_modules\puppeteer\lib\ExecutionContext.js:48:31)
    at ExecutionContext.<anonymous> (C:\Users\\Downloads\Projects\Bander-Statistics\node_modules\puppeteer\lib\helper.js:109:23)
    at DOMWorld.evaluate (C:\Users\\Downloads\Projects\Bander-Statistics\node_modules\puppeteer\lib\DOMWorld.js:105:20)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  -- ASYNC --
    at Frame.<anonymous> (C:\Users\\Downloads\Projects\Bander-Statistics\node_modules\puppeteer\lib\helper.js:108:27)
    at Page.evaluate (C:\Users\\Downloads\Projects\Bander-Statistics\node_modules\puppeteer\lib\Page.js:809:43)
    at Page.<anonymous> (C:\Users\\Downloads\Projects\Bander-Statistics\node_modules\puppeteer\lib\helper.js:109:23)
    at C:\Users\\Downloads\Projects\Bander-Statistics\band.js:29:29
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:16880) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:16880) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

1 Ответ

1 голос
/ 02 апреля 2019

Error

Ошибка происходит в этой строке в соответствии с вашим сообщением об ошибке:

let by = await page.evaluate(() => document.getElementsByClassName('text')[0].innerText); // 게시글 작성자 Text 파싱

Поскольку вы делаете примерно 75 000 запросов на веб-сайт, я могу предположить, что на веб-сайте предусмотрены защитные меры, запрещающие вашему боту сканировать. Кроме того, сообщение может просто не существовать, что вы пытаетесь сканировать.

Fix

Чтобы исправить вашу проблему, вы можете изменить функцию evaluate следующим образом. Это вернет неопределенное (вместо выдачи ошибки), если элементы не существуют. Это также улучшает ваш код, используя только один page.evaluate вызов.

let [by, date] = await page.evaluate(() => {
    const textNode = document.getElementsByClassName('text')[0];
    const timeNode = document.getElementsByClassName('time')[0];
    return [
        textNode && textNode.innerText,
        timeNode && timeNode.innerText,
    ];
});
if (!by || !date) {
    // by or date is undefined
    console.log(`Not working for ID: ${postNumber}`);
    await element.screenshot({ path: `error-${postNumber}.png` });
}

Это сделает скриншот страниц, где происходит ошибка. Может быть, вы увидите, что веб-сайт изменился (может, они показывают вам капчи?) Или сообщение, которое вы пытаетесь сканировать, просто не существует.

Если скриншот не помогает, вы также можете использовать page.content(), чтобы сохранить HTML-код в случае ошибки и просмотреть его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...