【问题标题】:Puppeteer / Node - Target.createTarget - Target ClosedPuppeteer / 节点 - Target.createTarget - 目标已关闭
【发布时间】:2018-02-09 12:19:06
【问题描述】:

我在下面的代码中使用 Node/Puppeteer,传入大量 URL 以进行遍历和抓取。尽管我发现我越来越接近答案,但异步执行它一直很困难。我目前遇到与以下错误相关的问题。

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 17): Error: Protocol error (Target.createTarget): Target closed.

此错误在 while 循环的每次迭代中发生一次。虽然我不确定我可能做错了什么。

有人可以帮我做以下事情吗:
1) 诊断错误来源。
2) 可能找到一种更有效的方法来异步遍历大量 URL。

async function subProc(list, batchSize) {
let subList = null;
let i = 0;

while (list.length > 0) {
    let browser = await puppeteer.launch();
    subList = list.splice(0, batchSize);
    console.log("Master List Size :: " + list.length);
    console.log("SubList Size :: " + subList.length);

    for (let j = 0; j < subList.length; j++) {
        promiseArray.push(new Promise((resolve, reject) => {
            resolve(pageScrape(subList[j], browser));
        }));
    }
    Promise.all(promiseArray)
        .then(response => {
            procArray.concat(response);
        });
    promiseArray = new Array();
    try {
        await browser.close();
    } catch(ex){
        console.log(ex);
    }
};
}

async function pageScrape(url, browser) {
let page = await browser.newPage();
await page.goto(url, {
    timeout: 0
});
await page.waitFor(1000);
return await page.evaluate(() => {
    let appTitle = document.querySelector('').innerText;
    let companyName = document.querySelector('').innerText;
    let dateListed = document.evaluate("", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.innerText;
    let category = document.evaluate("']//a//strong", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.innerText;
    /*  */
    return {
        appTitle,
        companyName,
        dateListed,
        category
    }
}).then(response => {
    let urlData = {
        id: subList[j],
        appName: response.appTitle,
        companyName: response.companyName,
        dateListed: response.dateListed,
        category: response.category
    }
    return urlData;
});

};

【问题讨论】:

  • 当然,你应该在Promise.all(promiseArray)之前添加await。您能给我们提供所有代码的示例以重现问题吗?

标签: web-scraping puppeteer


【解决方案1】:

我找到了解决问题的方法。 每台计算机的处理能力都是有限的,因此您不必同时遍历 1000 个 url,而必须将其分解成更小的部分。

通过使用 PromiseAll,一次迭代和抓取 10 个 url 并将这些值存储在一个数组中,我能够限制迭代所有 1000 个 url 所需的处理。

 processBatch(subData, 10, procArray).then((processed)=>{
            for(let i = 0; i < procArray.length; i++){
                for(let j = 0; j < procArray[i].length; j++){
                   results.push(procArray[i][j]);
                }
            }

 function processBatch(masterList, batchSize, procArray){
    return Promise.all(masterList.splice(0, batchSize).map(async url => 
    {
    return singleScrape(url)
    })).then((results) => {
    if (masterList.length < batchSize) {
        console.log('done');
        procArray.push(results);
        return procArray;
    } else {
        console.log('MasterList Size :: ' + masterList.length);
        procArray.push(results);
        return processBatch(masterList, batchSize, procArray);
    }
   })
 }

【讨论】:

    猜你喜欢
    • 2019-01-08
    • 2023-03-25
    • 2019-07-02
    • 2021-02-27
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    相关资源
    最近更新 更多