在调用 cluster.queue() 之后,人偶操纵者 cluster.close() "crashes"
Puppeteer cluster.close() "crashes" after calling cluster.queue()
长话短说,我制作了一个用于网络抓取的应用程序,为了让它能够同时 运行 一次处理 1 个以上的进程(打开了 1 个以上的 Chromium),我使用了木偶集群。我已经将它同时用于 运行 多个进程,但此后集群不会停止,它会永久地 运行s。一路上遇到了如下错误(1)
await cluster.close(); // Gives the following error -> cluster.close is not a function (1)
如果我这样使用它 (2)
(await cluster).close(); // This returns no error (2)
任何人,主要问题是当代码到达集群关闭的行时(在代码末尾,检查下面的代码),它在那里冻结。不会 return 任何错误,因为我试图捕捉它,但同时它也不会崩溃。
const puppeteer = require('puppeteer');
const { Cluster } = require('puppeteer-cluster/');
function delay(time) {
return new Promise(function(resolve) {
setTimeout(resolve, time)
});
}
(async () => {
const cluster = Cluster.launch({
concurrency: Cluster.CONCURRENCY_BROWSER,
maxConcurrency: 2,
});
const test = async () => {
const user = process.argv[2];
const pass = process.argv[3];
const smis = process.argv[4];
const nrinreg = process.argv[5];
const browser = await puppeteer.launch({headless: false, defaultViewport: null, args:['--start-fullscreen']}); // you can also use '--start-fullscreen']});
const page = await browser.newPage();
//await page.setViewport({width: 1200, height: 900});
await page._client.send('Page.setDownloadBehavior', {behavior: 'allow', downloadPath: './'+smis+''}).catch(e => {});
await page.goto('https://aplicatii2014.smis.fonduri-ue.ro/smis2014app/').catch(e => {});
await delay(2000);
// await page.waitFor(3000);
//scriere credentiale pt elementele de tip HTML user&parola
await page.type('#j_idt38 > .step-content > .step-pane > .col-md-12 > .form-group > input[name="j_idt38:utilizator"]', user).catch(e => {});
await delay(1000);
await page.type('#j_idt38 > .step-content > .step-pane > .col-md-12 > .form-group > input[name="j_idt38:pass"]', pass).catch(e => {});
await delay(1000);
page.click('#j_idt38 > .actions > a').catch(e => {});
await delay(2000);
page.click('#idPanelGroup > #headerPanel > div > #j_idt18 > tbody > tr > #topMenuCell > #j_idt22').catch(e => {});
await delay(2000);
await page.type('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > table > tbody > tr > td > input[id="formCereriFinantare:idSmisAll"]', smis).catch(e => {});
await delay(1000);
page.click('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > table > tbody > tr > td > a[id="formCereriFinantare:commandBtnSearch"]').catch(e => {});
await delay(1000);
page.click('span.ui-chkbox-icon.ui-icon.ui-icon-blank.ui-c').catch(e => {});
await delay(1000);
await page.type('#dialogAcordConfidentialitate > .ui-dialog-content > #formAcordConfidentialitate > div[id="formAcordConfidentialitate:j_idt167"] > .ui-scrollpanel-container > .ui-scrollpanel-content > .col-md-12 > .row > .col-md-3 > input[id="formAcordConfidentialitate:CNP"]', pass).catch(e => {});
await delay(1000);
page.click('#dialogAcordConfidentialitate > .ui-dialog-content > #formAcordConfidentialitate > div[id="formAcordConfidentialitate:j_idt167"] > .ui-scrollpanel-container > .ui-scrollpanel-content > .col-md-12 > .row > a[id="formAcordConfidentialitate:btnConfirmContent"]').catch(e => {});
await delay(1000);
page.click('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > div > div > a > .ui-icon-seek-end').catch(e => {});
await delay(2000);
const doc_details = await page.evaluate(() => {
//Extract each doc's basic details
let table = document.querySelector('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > div[id="formCereriFinantare:tableCereriFinantare"] > .ui-datatable-tablewrapper > table > tbody');
let doc_panels = Array.from(table.children);
// Loop through each doc and get their details
let doc_info = doc_panels.map(doc_panel => {
let codsmis = doc_panel.querySelector("tr > td:nth-child(1)").textContent;
let titlu = doc_panel.querySelector("tr > td:nth-child(2)").textContent;
let versiune = doc_panel.querySelector("tr > td:nth-child(3)").textContent;
let contractare = doc_panel.querySelector("tr > td:nth-child(4)").textContent;
return { versiune, contractare };
});
return doc_info;
});
doc_details.sort((a, b) => (parseInt(a.versiune) < parseInt(b.versiune) ? 1 : -1));
let res = new Array();
res = doc_details.filter(a => a.contractare.length > 0);
/**
* Get first elem from a array
* // [...res].shift()
*/
const [first] = res;
/**
* If no element exist
*/
if (first === null) {
page.click('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > div > div > a > .ui-icon-seek-prev').catch(e => { });
}
else {
let version = first["versiune"];
await delay(1000);
const example = await page.$('#dialogCereriFinantare > .ui-dialog-titlebar');
const bounding_box = await example.boundingBox();
await page.mouse.move(bounding_box.x + bounding_box.width / 2, bounding_box.y + bounding_box.height / 2);
await page.mouse.down();
await page.mouse.move(126, 19);
await page.mouse.up();
await delay(1000);
await page.waitForXPath("//tr/td[3][contains(., '"+ version +"')]");
const [projects] = await page.$x("//tr/td[3][contains(., '"+ version +"')]");
projects.click().catch(e => {});
await delay(2000);
await page.goto("https://aplicatii2014.smis.fonduri-ue.ro/smis2014app/faces/pages/comunicare.xhtml").catch(e => {});
await delay(2000);
await page.evaluate(() => {
document.querySelector('#j_idt68 > div > #idPanelContent > #j_idt140 > #j_idt140_content > #j_idt142 > div > .ui-datatable-tablewrapper > table > tbody').scrollIntoView();
}).catch(e => {});
await delay(2000).catch(e => {});
const [com] = await page.$x("//tr/td[1][contains(., '37114')]").catch(e => {});
if (com){
com.click().catch(e => {});
}
else
{
let [com2] = await page.$x("//tr/td[1][contains(., '"+ nrinreg +"')]");
do{
page.click('#j_idt68 > div > #idPanelContent > #j_idt140 > #j_idt140_content > #j_idt142 > div > div[id="j_idt142:idComunicareTable_paginator_bottom"] > .ui-paginator-next').catch(e => {});
await delay(2000).catch(e => {});
let [com2] = await page.$x("//tr/td[1][contains(., '"+ nrinreg +"')]").catch(e => {});
if (com2){
break;
}
}
while(!com2);
let [com3] = await page.$x("//tr/td[1][contains(., '"+ nrinreg +"')]").catch(e => {});
com3.click().catch(e => {});
await delay(2000).catch(e => {});
await page.evaluate(() => {
document.querySelector('#j_idt68 > div > #idPanelContent > #j_idt140 > div > #idDetaliicomunicare').scrollIntoView();
}).catch(e => {});
await delay(2000).catch(e => {});
}
await delay(2000);
const listadownload = await page.$$('#j_idt68 > div > #idPanelContent > div > div > #idDetaliicomunicare > div > div > div > ul > li > .ui-treenode-children > li > span');
for (let iteminlistadownload of listadownload){
await iteminlistadownload.click({button: 'right',}).catch(e => {});
await delay(2000);
let [viz] = await page.$x('//*[@id="idDetaliicomunicare:j_idt163"]/ul/li/a').catch(e => {});
viz.click().catch(e => {});
await delay(2000);
}
}
await delay(3000);
await browser.close();
};
(await cluster).queue(test);
(await cluster).idle();
(await cluster).close();
})();
我一直在互联网上搜索解决方案,在 GitHub 上寻找修复程序,但似乎没有任何效果。我做错了什么,只是不会终止这个过程?
PS : 我添加了整个代码,希望它是相关的。
Cluster.launch
return 一个承诺。如果你只是调用 const cluster = Cluster.launch
,现在 cluster
是 Promise,当你调用 (await cluster).close();
时,(await cluster)
将 return 一个 Cluster
实例 -> 它工作!
让我们使用 cluster
作为 Cluster
实例而不是 Promise 对象:
const cluster = await Cluster.launch({ // wait until it "launch" finish
concurrency: Cluster.CONCURRENCY_BROWSER,
maxConcurrency: 2,
});
长话短说,我制作了一个用于网络抓取的应用程序,为了让它能够同时 运行 一次处理 1 个以上的进程(打开了 1 个以上的 Chromium),我使用了木偶集群。我已经将它同时用于 运行 多个进程,但此后集群不会停止,它会永久地 运行s。一路上遇到了如下错误(1)
await cluster.close(); // Gives the following error -> cluster.close is not a function (1)
如果我这样使用它 (2)
(await cluster).close(); // This returns no error (2)
任何人,主要问题是当代码到达集群关闭的行时(在代码末尾,检查下面的代码),它在那里冻结。不会 return 任何错误,因为我试图捕捉它,但同时它也不会崩溃。
const puppeteer = require('puppeteer');
const { Cluster } = require('puppeteer-cluster/');
function delay(time) {
return new Promise(function(resolve) {
setTimeout(resolve, time)
});
}
(async () => {
const cluster = Cluster.launch({
concurrency: Cluster.CONCURRENCY_BROWSER,
maxConcurrency: 2,
});
const test = async () => {
const user = process.argv[2];
const pass = process.argv[3];
const smis = process.argv[4];
const nrinreg = process.argv[5];
const browser = await puppeteer.launch({headless: false, defaultViewport: null, args:['--start-fullscreen']}); // you can also use '--start-fullscreen']});
const page = await browser.newPage();
//await page.setViewport({width: 1200, height: 900});
await page._client.send('Page.setDownloadBehavior', {behavior: 'allow', downloadPath: './'+smis+''}).catch(e => {});
await page.goto('https://aplicatii2014.smis.fonduri-ue.ro/smis2014app/').catch(e => {});
await delay(2000);
// await page.waitFor(3000);
//scriere credentiale pt elementele de tip HTML user&parola
await page.type('#j_idt38 > .step-content > .step-pane > .col-md-12 > .form-group > input[name="j_idt38:utilizator"]', user).catch(e => {});
await delay(1000);
await page.type('#j_idt38 > .step-content > .step-pane > .col-md-12 > .form-group > input[name="j_idt38:pass"]', pass).catch(e => {});
await delay(1000);
page.click('#j_idt38 > .actions > a').catch(e => {});
await delay(2000);
page.click('#idPanelGroup > #headerPanel > div > #j_idt18 > tbody > tr > #topMenuCell > #j_idt22').catch(e => {});
await delay(2000);
await page.type('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > table > tbody > tr > td > input[id="formCereriFinantare:idSmisAll"]', smis).catch(e => {});
await delay(1000);
page.click('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > table > tbody > tr > td > a[id="formCereriFinantare:commandBtnSearch"]').catch(e => {});
await delay(1000);
page.click('span.ui-chkbox-icon.ui-icon.ui-icon-blank.ui-c').catch(e => {});
await delay(1000);
await page.type('#dialogAcordConfidentialitate > .ui-dialog-content > #formAcordConfidentialitate > div[id="formAcordConfidentialitate:j_idt167"] > .ui-scrollpanel-container > .ui-scrollpanel-content > .col-md-12 > .row > .col-md-3 > input[id="formAcordConfidentialitate:CNP"]', pass).catch(e => {});
await delay(1000);
page.click('#dialogAcordConfidentialitate > .ui-dialog-content > #formAcordConfidentialitate > div[id="formAcordConfidentialitate:j_idt167"] > .ui-scrollpanel-container > .ui-scrollpanel-content > .col-md-12 > .row > a[id="formAcordConfidentialitate:btnConfirmContent"]').catch(e => {});
await delay(1000);
page.click('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > div > div > a > .ui-icon-seek-end').catch(e => {});
await delay(2000);
const doc_details = await page.evaluate(() => {
//Extract each doc's basic details
let table = document.querySelector('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > div[id="formCereriFinantare:tableCereriFinantare"] > .ui-datatable-tablewrapper > table > tbody');
let doc_panels = Array.from(table.children);
// Loop through each doc and get their details
let doc_info = doc_panels.map(doc_panel => {
let codsmis = doc_panel.querySelector("tr > td:nth-child(1)").textContent;
let titlu = doc_panel.querySelector("tr > td:nth-child(2)").textContent;
let versiune = doc_panel.querySelector("tr > td:nth-child(3)").textContent;
let contractare = doc_panel.querySelector("tr > td:nth-child(4)").textContent;
return { versiune, contractare };
});
return doc_info;
});
doc_details.sort((a, b) => (parseInt(a.versiune) < parseInt(b.versiune) ? 1 : -1));
let res = new Array();
res = doc_details.filter(a => a.contractare.length > 0);
/**
* Get first elem from a array
* // [...res].shift()
*/
const [first] = res;
/**
* If no element exist
*/
if (first === null) {
page.click('#dialogCereriFinantare > .ui-dialog-content > #formCereriFinantare > div > div > a > .ui-icon-seek-prev').catch(e => { });
}
else {
let version = first["versiune"];
await delay(1000);
const example = await page.$('#dialogCereriFinantare > .ui-dialog-titlebar');
const bounding_box = await example.boundingBox();
await page.mouse.move(bounding_box.x + bounding_box.width / 2, bounding_box.y + bounding_box.height / 2);
await page.mouse.down();
await page.mouse.move(126, 19);
await page.mouse.up();
await delay(1000);
await page.waitForXPath("//tr/td[3][contains(., '"+ version +"')]");
const [projects] = await page.$x("//tr/td[3][contains(., '"+ version +"')]");
projects.click().catch(e => {});
await delay(2000);
await page.goto("https://aplicatii2014.smis.fonduri-ue.ro/smis2014app/faces/pages/comunicare.xhtml").catch(e => {});
await delay(2000);
await page.evaluate(() => {
document.querySelector('#j_idt68 > div > #idPanelContent > #j_idt140 > #j_idt140_content > #j_idt142 > div > .ui-datatable-tablewrapper > table > tbody').scrollIntoView();
}).catch(e => {});
await delay(2000).catch(e => {});
const [com] = await page.$x("//tr/td[1][contains(., '37114')]").catch(e => {});
if (com){
com.click().catch(e => {});
}
else
{
let [com2] = await page.$x("//tr/td[1][contains(., '"+ nrinreg +"')]");
do{
page.click('#j_idt68 > div > #idPanelContent > #j_idt140 > #j_idt140_content > #j_idt142 > div > div[id="j_idt142:idComunicareTable_paginator_bottom"] > .ui-paginator-next').catch(e => {});
await delay(2000).catch(e => {});
let [com2] = await page.$x("//tr/td[1][contains(., '"+ nrinreg +"')]").catch(e => {});
if (com2){
break;
}
}
while(!com2);
let [com3] = await page.$x("//tr/td[1][contains(., '"+ nrinreg +"')]").catch(e => {});
com3.click().catch(e => {});
await delay(2000).catch(e => {});
await page.evaluate(() => {
document.querySelector('#j_idt68 > div > #idPanelContent > #j_idt140 > div > #idDetaliicomunicare').scrollIntoView();
}).catch(e => {});
await delay(2000).catch(e => {});
}
await delay(2000);
const listadownload = await page.$$('#j_idt68 > div > #idPanelContent > div > div > #idDetaliicomunicare > div > div > div > ul > li > .ui-treenode-children > li > span');
for (let iteminlistadownload of listadownload){
await iteminlistadownload.click({button: 'right',}).catch(e => {});
await delay(2000);
let [viz] = await page.$x('//*[@id="idDetaliicomunicare:j_idt163"]/ul/li/a').catch(e => {});
viz.click().catch(e => {});
await delay(2000);
}
}
await delay(3000);
await browser.close();
};
(await cluster).queue(test);
(await cluster).idle();
(await cluster).close();
})();
我一直在互联网上搜索解决方案,在 GitHub 上寻找修复程序,但似乎没有任何效果。我做错了什么,只是不会终止这个过程? PS : 我添加了整个代码,希望它是相关的。
Cluster.launch
return 一个承诺。如果你只是调用 const cluster = Cluster.launch
,现在 cluster
是 Promise,当你调用 (await cluster).close();
时,(await cluster)
将 return 一个 Cluster
实例 -> 它工作!
让我们使用 cluster
作为 Cluster
实例而不是 Promise 对象:
const cluster = await Cluster.launch({ // wait until it "launch" finish
concurrency: Cluster.CONCURRENCY_BROWSER,
maxConcurrency: 2,
});