Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 木偶演员的执行环境被破坏,很可能是因为导航_Javascript_Node.js_Web Scraping_Puppeteer - Fatal编程技术网

Javascript 木偶演员的执行环境被破坏,很可能是因为导航

Javascript 木偶演员的执行环境被破坏,很可能是因为导航,javascript,node.js,web-scraping,puppeteer,Javascript,Node.js,Web Scraping,Puppeteer,当我在另一个页面上获取数据时,我在for循环中的Puppeter中遇到了这个问题,然后当我返回时,返回以下错误行: Error "We have an error Error: the execution context was destroyed, probably because of a navigation." 这是一个目录页面,每页包含15家公司,然后我想访问每家公司以获取信息 try { const browser = await pupputer.launch({

当我在另一个页面上获取数据时,我在for循环中的Puppeter中遇到了这个问题,然后当我返回时,返回以下错误行:

Error "We have an error Error: the execution context was destroyed, probably because of a navigation."
这是一个目录页面,每页包含15家公司,然后我想访问每家公司以获取信息

try {
    const browser = await pupputer.launch({
        headless: false,
        devtools: true,
        defaultViewport: {
            width: 1100,
            height: 1000
        }
    });

    const page = await browser.newPage();
    await page.goto('MyLink');

    await page.waitForSelector('.list-firms');

    for (var i = 1; i < 10; i++) {

        const listeCompanies = await page.$$('.list-firms > div.firm');

        for (const companie of listeCompanies) {

            const name = await companie.$eval('.listing-body > h3 > a', name => name.innerText);
            const link = await companie.$eval('.listing-body > h3 > a', link => link.href);

            await Promise.all([
                page.waitForNavigation(),
                page.goto(link),
                page.waitForSelector('.firm-panel'),
            ]);

            const info = await page.$eval('#info', e => e.innerText);

            const data = [{
                name: name,
                information: info,
            }];

            await page.goBack();

        }
        await Promise.all([
            page.waitForNavigation(),
            page.click('span.page > a[rel="next"]')
        ]);
    }
} catch (e) {
    console.log('We have error', e);
}
试试看{
const browser=等待puputer.launch({
无头:错,
devtools:没错,
默认视口:{
宽度:1100,
身高:1000
}
});
const page=wait browser.newPage();
等待page.goto('MyLink');
wait page.waitForSelector(“.上市公司”);
对于(变量i=1;i<10;i++){
const listcompanies=等待页面。$$(“.上市公司>部门公司”);
(上市公司的常数公司){
const name=wait companie.$eval('.listing body>h3>a',name=>name.innerText);
const link=wait companie.$eval('.listing body>h3>a',link=>link.href);
等待承诺([
page.waitForNavigation(),
第页转到(链接),
page.waitForSelector(“.公司面板”),
]);
const info=wait page.$eval('info',e=>e.innerText);
常数数据=[{
姓名:姓名,,
信息:信息,,
}];
等待page.goBack();
}
等待承诺([
page.waitForNavigation(),
页面。单击('span.page>a[rel=“next”]”)
]);
}
}捕获(e){
log('我们有错误',e);
}
我只能得到第一家公司的数据。

问题 该错误表示您正在访问由于导航而过时/无效的数据。在脚本中,错误引用变量
listcompanies

const listcompanies=wait page.$$('.list firms>div.firm');
首先,在循环中使用此变量,然后通过
页面导航。转到
,然后循环尝试从变量
列表中获取下一项。但是在导航发生后,该变量中的元素句柄不再存在,因此会抛出错误。这也是第一次迭代工作的原因

解决方案 有多种方法可以解决这个问题

  • 立即从页面中提取数据(在使用循环之前)
  • 使用第二个页面进行“循环导航”,这样您的主页就不需要导航了
  • 调用
    page.goBack

  • 选项1:在进入循环之前提取数据 这是最干净的方法。您一次提取第一页中的信息,然后迭代提取的数据。
    nameLinkList
    将是一个数组,其中包含
    name
    link
    值(例如
    [{name:''..',link:'''''},{name:''..',link:'''}]
    )。也不需要在循环结束时调用
    page.goBack
    ,因为已经提取了数据

    const nameLinkList=等待页面。$$eval(
    “.上市公司>部门公司”,
    (事务所=>firms.map(事务所=>{
    const a=firm.querySelector('.listing body>h3>a');
    返回{
    名称:a.innerText,
    链接:a.href
    };
    }))
    );
    用于(arr的常量{name,link}){
    等待承诺([
    page.waitForNavigation(),
    第页转到(链接),
    page.waitForSelector(“.公司面板”),
    ]);
    const info=wait page.$eval('info',e=>e.innerText);
    常数数据=[{
    姓名:姓名,,
    信息:信息,,
    }];
    }
    
    选项2:使用第二页 在这种情况下,浏览器将有两个打开的页面。第一个用于读取数据,第二个用于导航

    const page2=wait browser.newPage();
    (上市公司的常数公司){
    const name=wait companie.$eval('.listing body>h3>a',name=>name.innerText);
    const link=wait companie.$eval('.listing body>h3>a',link=>link.href);
    等待承诺([
    第2页转到(链接),
    第2页waitForSelector(‘公司小组’),
    ]);
    const info=wait page2.$eval('info',e=>e.innerText);
    // ...
    }
    
    选项3:“刷新”选择器 在这里,您只需在返回“主页”后重新执行选择器。注意,在替换数组时,..of
    必须更改为迭代器循环

    let listcompanies=wait page.$$('.list firms>div.firm');
    for(设i=0;i部门公司”);
    }
    

    我建议选择选项1,因为这也减少了必要的导航请求数量,因此会加快脚本速度。

    你不能等待多个这样的承诺,你必须一次做一个。我在发布我自己的答案后搜索并找到了这个答案,更奇怪的是,我在帖子中使用了类似的
    问题解决方案
    结构:D@Md.AbuTaher是的,这个问题确实非常接近这个问题。很高兴您能链接到这个答案。:)