首页 > 解决方案 > 使用 puppeteer 创建对象数组的更有效方法

问题描述

我正在尝试抓取包含一堆短信的页面。消息的排列方式与下面的示例类似。我想使用 puppeeter 创建一个对象数组。每个对象将包含每个消息的内部文本,不包括其中一个元素。

我要构建的数组应如下所示:

const messages = [{name: 'Greg', textMessage: 'Blah Blah Blah'}, {name: 'James', textMessage: 'Blah Blah Blah'},{name: 'Sam', textMessage: 'Blah Blah Blah'}]

示例:HTML 标记

<div class="messages">
  <div class="message">
    <a class="name">Greg</a>
    <p class="element-you-dont-want">Don't scrape this</p>
    <p class="textMessage">Blah Blah Blah</p>
  </div>
  <div class="message">
    <a class="name">James</a>
    <p class="element-you-dont-want">Don't scrape this</p>
    <p class="textMessage">Blah Blah Blah</p>
  </div>
  <div class="message">
    <a class="name">Sam</a>
    <p class="element-you-dont-want">Don't scrape this</p>
    <p class="textMessage">Blah Blah Blah</p>
  </div>
</div>

我当前的代码创建了两个数组,一个用于名称,另一个用于 textMessages,然后我必须将它们组合起来。有没有更有效的方法来做到这一点。

 const names = await page.evaluate(
      () =>  Array.from(document.querySelectorAll("div.messages a.name")).map(name => name.innerText)
    );
    const textMessages = await page.evaluate(
      () =>  Array.from(document.querySelectorAll("div.messages p.textMessage")).map(textMessage => textMessage.innerText)
    );

... From here I combine the two into an object of arrays. 

标签: puppeteer

解决方案


中有一个$$eval函数Page,它在上下文中转换为Array.from(document.querySelectorAll(selector))并将其作为第一个参数传递给pageFunction

用法:

const result = await page.$$eval('div.message', (msgs) => msgs.map((msg) => {
            return {
                name: msg.querySelector('a.name').innerText,
                textMessage: msg.querySelector('a.textMessage').innerText
            }})
    );

推荐阅读