如何从DOM获取所有链接?

Veg*_*ega 4 web-crawler node.js puppeteer

根据https://github.com/GoogleChrome/puppeteer/issues/628,我应该可以通过以下单行获取<a href ="xyz">的所有链接:

const hrefs = await page.$$eval('a', a => a.href);
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试一个简单的

console.log(hrefs)
Run Code Online (Sandbox Code Playgroud)

我只能得到

http://example.de/index.html
Run Code Online (Sandbox Code Playgroud)

作为输出,这意味着它只能找到1个链接?但该页面在源代码/ DOM中肯定有12个链接.为什么找不到它们?

最小的例子:

'use strict';
const puppeteer = require('puppeteer');

crawlPage();

function crawlPage() {
    (async () => {
	
	const args = [
            "--disable-setuid-sandbox",
            "--no-sandbox",
            "--blink-settings=imagesEnabled=false",
        ];
        const options = {
            args,
            headless: true,
            ignoreHTTPSErrors: true,
        };

	const browser = await puppeteer.launch(options);
        const page = await browser.newPage();
	await page.goto("http://example.de", {
            waitUntil: 'networkidle2',
            timeout: 30000
        });
     
	const hrefs = await page.$eval('a', a => a.href);
        console.log(hrefs);
		
        await page.close();
	await browser.close();
		
    })().catch((error) => {
        console.error(error);
    });;

}
Run Code Online (Sandbox Code Playgroud)

Mig*_*rón 14

在您使用的示例代码中page.$eval,而不是page.$$eval.由于前者使用document.querySelector而不是document.querySelectorAll,您描述的行为是预期的行为.

此外,您应该更改您pageFunction$$eval参数:

const hrefs = await page.$$eval('a', as => as.map(a => a.href));
Run Code Online (Sandbox Code Playgroud)

  • 从某种意义上来说它是"错误的",因为它现在不能以这种方式工作,但是如果你重读这个问题,你会发现那个示例代码是一个"概念证明"的例子,它将如何`$$ eval `工作一旦实现(现在它已实现,它的工作方式略有不同). (3认同)

Gra*_*ler 6

该方法在页面内page.$$eval()运行并将其作为第一个参数传递给页面函数。Array.from(document.querySelectorAll(selector))

由于a在您的示例中表示一个数组,因此您要么需要指定要从中获取的数组元素href,要么需要数组的map所有属性。href

页面.$$eval()

const hrefs = await page.$$eval('a', links => links.map(a => a.href));
Run Code Online (Sandbox Code Playgroud)

或者,您也可以使用或、、 或page.evaluate()的组合来实现页面中所有链接的数组。page.$$()elementHandle.getProperty()jsHandle.jsonValue()

页面.evaluate()

const hrefs = await page.evaluate(() => {
  return Array.from(document.getElementsByTagName('a'), a => a.href);
});
Run Code Online (Sandbox Code Playgroud)

page.$$() / elementHandle.getProperty() / jsHandle.jsonValue()

const hrefs = await Promise.all((await page.$$('a')).map(async a => {
  return await (await a.getProperty('href')).jsonValue();
}));
Run Code Online (Sandbox Code Playgroud)