木偶-使用瞬间评估页面

Ann*_*lee 3 javascript momentjs puppeteer

我正在尝试使用"puppeteer": "^1.16.0","moment": "^2.24.0",。当运行page.evaluate()通过瞬间将字符串转换为日期obj时,我得到:

错误:评估失败:ReferenceError:未定义矩

在下面的最小示例中查找:

const puppeteer = require("puppeteer-extra")
const moment = require('moment')

function shuffle(dataObjArr) {
    let res = dataObjArr.sort(() => Math.random() - 0.5);
    return res
}

let issuerUrls = JSON.parse('[{"id":62,"name":"Product 1","ecomUrl":"/product/252","createdAt":"2019-05-25T07:51:49.000Z","updatedAt":"2019-05-25T07:51:49.000Z"},  {"id":15,"name":"Product 2","ecomUrl":"/product/251","createdAt":"2019-05-25T07:51:49.000Z","updatedAt":"2019-05-25T07:51:49.000Z"}]')

let issuerUrlsShuffled = shuffle(issuerUrls)
let BASE_URL = "https://www.webscraper.io/test-sites/e-commerce/allinone"
// puppeteer usage as normal
puppeteer.launch({
    headless: false,
    args: ["--disable-notifications"]
}).then(async browser => {
    const page = await browser.newPage()
    await page.setViewport({
        width: 800,
        height: 600
    })

    for (let i = 0; i < issuerUrlsShuffled.length; i++) {
        try {

            let URL = BASE_URL + issuerUrlsShuffled[i].ecomUrl;

            await page.goto(URL)

            page.waitForNavigation({
                timeout: 60,
                waitUntil: 'domcontentloaded'
            });

            const data = await page.evaluate(() => {

                const priceData = []

                let date = "9/23/2016" // this is needed for testing purposes only!!!

                priceData.push({
                    price_date: moment(date, 'M/DD/YYYY').toDate()
                })
                return priceData
            }, moment)

            // show data
            console.log(JSON.stringify(data, null, 2))

            await page.waitFor(3000)
        } catch (error) {
            console.log(error)
        }
    }
    await browser.close()
})
Run Code Online (Sandbox Code Playgroud)

如您所见,我尝试将moment实例传递给evaluate函数,但是仍然出现错误。

有什么建议我做错了吗?

感谢您的答复!

Tho*_*orf 5

您只能将可序列化的数据page.evaluate作为参数传递给函数。(有关更多信息,请参阅文档)。正如moment一个函数和一个函数无法序列化一样,您不能那么容易地使用它。

要将功能从Node.js环境公开到页面,可以使用page.exposeFunction。从文档引用:

该方法添加了一个name在页面window对象上调用的函数。调用该函数时,该函数puppeteerFunction在node.js中执行,并返回一个Promise,该Promise解析为返回值puppeteerFunction

代码示例:

Node.js环境中的以下代码设置了一个formatDate返回格式化日期的函数:

await page.exposeFunction('formatDate', (date) =>
  moment(date, 'M/DD/YYYY').toDate()
);
Run Code Online (Sandbox Code Playgroud)

请注意,exposeFunction在导航过程中,您只需在页面上调用一次即可。这意味着您可以将此代码放在循环之外。

然后,您的操纵up代码可以使用如下功能:

const data = await page.evaluate(async () => {
  const priceData = []
  let date = "9/23/2016"
  priceData.push({
    price_date: await window.formatDate(date)
  })
  return priceData
})
Run Code Online (Sandbox Code Playgroud)

  • @Vaviloff感谢您的提示。:)`await`丢失了...我自己尝试过,现在可以使用了。 (2认同)
  • :D很高兴见到Thomas和Vaviloff以及大家互相帮助。我认为我们应该在答案上注明:Exposure函数应该在任何形式的循环或导航之前添加,因为“通过page.exposeFunction安装的函数可以幸免于导航。” (2认同)
  • @ Md.AbuTaher puppeteer-stackoverflow小队走到一起:D在提示中添加了提示。 (2认同)