Puppeteer:如何单击元素以便在新选项卡中打开?

nig*_*owl 8 javascript web-scraping puppeteer

我有一个包含 25 个可点击元素的列表。我需要在新选项卡中打开它们中的每一个,抓取在新选项卡中打开的新页面,然后将其关闭。然后转到下一个元素,并对列表中的每个元素执行相同的操作。

但是,我在通过单击链接在新选项卡中打开链接时遇到问题。我设法打开然后,page.goto('link")但我想让它更加人性化,而不是将链接粘贴到新选项卡中,我想通过单击打开。

let accountsClickElements = await page.$$eval(".result-lockup__name a", el => el.map(x => x.getAttribute("id")));
                                                                                        
 for (let i = 0; i<25; i++) {
     await autoScroll(page);
     await page.waitFor(3000);
     let id = companies[i];
     await page.focus("#"+accountsClickElements[0]);
     accountsClickElements = await page.$$eval(".result-lockup__name a", el => el.map(x => x.getAttribute("id")));
     await page.waitFor(3000);
     await page.focus("#"+accountsClickElements[i]);                             
     await page.click("#"+accountsClickElements[i]);
     await page.waitFor(2000);
     console.log("#"+companies[i].linid);
     await page.goBack(); 
  }                              `
Run Code Online (Sandbox Code Playgroud)

这是一段在同一选项卡中打开链接的代码,但一段时间后,它不会占用所有 25 个元素,并且由于每次打开页面时 id 都会发生变化,因此出现错误。

我已经像这样更改了代码,因此不是单击元素,而是单击 href 属性。目标 _blank 属性在那里,但它仍然在同一个选项卡上打开。你能指出原因吗?

await page.$$eval('.result-lockup__name a', el => el.map(x => x.setAttribute("target", "_blank")));
let accountsClickElements = await page.$$eval(".result-lockup__name a", el => el.map(x => x.getAttribute("href")));                                                                                                                  
for (let i = 0; i<25; i++) {
   await page.waitFor(2000);
   await autoScroll(page);
   await page.waitFor(2000);    
   await page.click('a[href="'+accountsClickElements[i]+'"]');
}
Run Code Online (Sandbox Code Playgroud)

小智 8

WindowsLinux上,按住 Ctrl 键,然后单击:

\n
    // Ctrl+click to open in new tab\n    await page.keyboard.down(\'Control\');\n    await page.click(\'a[href="\'+accountsClickElements[i]+\'"]\')\n    await page.keyboard.up(\'Control\');\n
Run Code Online (Sandbox Code Playgroud)\n

然后找到打开的选项卡。一种方法是使用await browser.pages()并过滤掉当前页面。请注意,当您启动 Puppeteer 时,它已经打开了一个选项卡,因此如果您所做的第一件事是const page = await browser.newPage();您可能有两个选项卡并且需要.close()第一个选项卡。

\n

这是更完整的代码示例:

\n
import puppeteer from \'puppeteer\';\n\n(async () => {\n    const browser = await puppeteer.launch();\n    // When the browser launches, it should have one about:blank tab open.\n    const page = (await browser.pages())[0];\n\n    // A safer way to do the above is to open a new tab and then close all\n    // tabs that aren\'t the tab you just opened.\n    // const page = await browser.newPage();\n    // // Close any tabs that aren\'t the one we created on the line above\n    // for (const p of (await browser.pages())) {\n    //     if (p !== page) {\n    //         await p.close()\n    //     }\n    // }\n\n    await page.goto(\'https://example.com/\');\n\n    // Ctrl-click the "More information..." link to open it in a new tab\n    await page.keyboard.down(\'Control\');\n    await page.click(\'a\');\n    await page.keyboard.up(\'Control\');\n\n    // Wait a second for the tab to open\n    await page.waitForTimeout(1000);\n\n    // Print the URLs of all currently open tabs\n    console.error((await browser.pages()).map(p => p.url()));\n\n    if ((await browser.pages()).length !== 2) {\n        throw "unexpected number of tabs";\n    }\n    const otherPage = (await browser.pages())[1];\n    // Do something with the other tab\n    // ...\n    // Then close it\n    await otherPage.close();\n\n    await browser.close();\n})();\n
Run Code Online (Sandbox Code Playgroud)\n

macOS上这不起作用。快捷方式是 Command+单击,因此您必须执行await page.keyboard.down(\'Meta\')以下操作\'Control\',但这不起作用,因为在 macOS 上,使用 Command 键的键盘快捷键通常由操作系统处理,而不是浏览器(例如 \xe2\x8c \x98-A,通常选择所有文本,也不起作用)。你可以试试

\n\n


nig*_*owl 7

中键单击使用page.click

let options = {button : 'middle'};
await page.click('a[href="'+accountsClickElements[i]+'"]', options)
Run Code Online (Sandbox Code Playgroud)

新选项卡可能需要一些时间才能打开,您可以使用 等待await page.waitForTimeout(1000)

完整代码:

let accountsClickElements = await page.$$eval('.result-lockup__name a', el => el.map(x => x.getAttribute('href')));

browser.on('targetcreated', function(){                                            
    console.log(accountsClickElements[i]) 
})   

let options = {
    button : 'middle'
};
for (let i = 0; i<25; i++) {
    await page.waitForTimeout(2000);
    await page.focus('a[href="'+accountsClickElements[i]+'"]')                                                    
    await page.click('a[href="'+accountsClickElements[i]+'"]', options)
    const [tab1, tab2, tab3] = await browser.pages();
    await page.waitForTimeout(2000);
    await tab3.bringToFront();                                                                               
    await ListenCompanyPageNewTab(tab3); 
    await tab2.bringToFront();                                                            
} 
Run Code Online (Sandbox Code Playgroud)