如何从DOM获取所有链接?

时间:2018-03-26 12:55:59

标签: node.js web-crawler puppeteer

根据https://github.com/GoogleChrome/puppeteer/issues/628,我应该可以从<获取所有链接a href =“xyz”> 这一行:

const hrefs = await page.$$eval('a', a => a.href);

但是当我尝试一个简单的

console.log(hrefs)

我只得到

http://example.de/index.html

作为输出,这意味着它只能找到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);
    });;

}

2 个答案:

答案 0 :(得分:7)

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

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

const hrefs = await page.$$eval('a', as => as.map(a => a.href));

答案 1 :(得分:2)

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

由于示例中的a表示一个数组,因此您将需要指定要从中获取href的数组元素,或者您需要全部map href属性中的一个到数组。

page。$$ eval()

const hrefs = await page.$$eval('a', links => links.map(a => a.href));

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

page.evaluate()

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

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

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