我使用Puppeteer开发了解析应用程序,并且运行良好。但问题是此应用有时会出错,我不知道为什么会发生此错误。
我必须捕获大约90,000个数据。
该错误似乎是由于未阅读班级列表引起的,但是即使我将Headless选项设置为False并检查,班级列表也存在。
起初,它运行良好,并且随机生成错误。
我认为,有时页面无法在网站本身上加载,并继续在加载栏上停止,这就是原因。
即使我在waitUntil值中输入networkidle0或2,如果此预测正确,我也不知道如何检测到它。
[完整代码]
'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.
答案 0 :(得分:1)
根据您的错误消息,此行中发生错误:
let by = await page.evaluate(() => document.getElementsByClassName('text')[0].innerText); // 게시글 작성자 Text 파싱
当您向一个网站发出大约75,000个请求时,我可以想象该网站正在采取保护性措施来禁止您的漫游器爬行。另外,您尝试抓取的帖子可能不存在。
要解决您的问题,您可以像这样更改evaluate
函数。如果元素不存在,则将返回undefined(而不是引发错误)。通过仅使用一个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保存为错误情况并进行查看。