无法使用Puppeteer访问innerText属性-。$$ eval和。$$没有产生结果-JavaScript

时间:2018-12-05 21:16:43

标签: javascript html dom web-crawler puppeteer

我正在研究一个Web抓取器,该抓取器在Google中搜索某些内容,然后从结果页面中提取文本,但是在让Puppeteer返回所需的文本时遇到了问题。我要返回的是一个字符串数组。

比方说,我在div中有几个嵌套的div,每个文本都有这样的文字:

 <div class='mainDiv'>
   <div>Mary Doe </div>
   <div> James Dean </div>
 </div>

在DOM中,我可以执行以下操作以获得所需的结果:

document.querySelectorAll('.mainDiv')[0].innerText.split('\n')

这将产生:["Mary Doe", "James Dean"]

我知道Puppeteer不会返回NodeLists,而是使用JSHandles,但是我仍然不知道如何使用规定的方法获取任何信息。请参阅下文,了解我在Puppeteer中尝试过的内容以及相应的控制台输出:

在每种情况下,我都会做await page.waitFor('selector')来开始。

方案1(使用.$$eval()):

const genreElements = await page.$$eval('div.mainDiv', el => el);
console.log(genreElements) // [] 

方案2(使用evaluate):

function extractItems() {
   const extractedElements = document.querySelectorAll('div.mainDiv')[0].innerText.split('\n')
   return extractedElements
}

let items = await page.evaluate(extractItems)
console.log(items) // UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'innerText' of undefined

方案3(使用evaluateHandle):

const selectorHandle = await page.evaluateHandle(() => document.querySelectorAll('div.mainDiv'))
const resultHandle = await page.evaluate(x => x[0], selectorHandle)
console.log(resultHandle) // undefined

任何有关我如何实施或如何实现我想要做的事情的帮助或指导,都深表感谢。谢谢!

3 个答案:

答案 0 :(得分:0)

使用 page.$eval

const names = await page.$eval('.mainDiv', (element) => {
    return element.innerText
});

在这里,元素由选择器检索,并直接传递给要评估的函数。

使用 page.evaluate

const namesElem = await page.$('.mainDiv');
const names = await page.evaluate(namesElem => namesElem.innerText, namesElem);

这基本上是第一种方法,分为两个步骤。有趣的是,ElementHandles可以作为page.evaluate()中的参数传递,并且可以像JSHandles那样求值。

请注意,为简单起见,我使用了检索单个元素的方法。但是page。$$()和page。$$ eval()的工作方式相同,同时选择多个元素并返回一个数组。

答案 1 :(得分:0)

像这样尝试:

match

这样,您就可以在chrome控制台中测试整个过程。

答案 2 :(得分:0)

使用page。$$ eval()或page.evaluate():

您可以使用page.$$eval()page.evaluate()在页面上下文中运行Array.from( document.querySelectorAll() ),而在map()中使用innerText每个元素到结果数组的位置:

const names_1 = await page.$$eval('.mainDiv > div', divs => divs.map(div => div.innerText));
const names_2 = await page.evaluate(() => Array.from(document.querySelectorAll('.mainDiv > div'), div => div.innerText));
  

注意:请记住,如果您使用Puppeteer在Google上自动执行搜索,则可能会被暂时屏蔽并收到"Unusual traffic from your computer network"通知,要求您解决{{ 3}}。这可能会破坏您的网页抓取工具,因此请谨慎操作。