javascript - Puppeteer - Page.evaluate 使用 moment

标签 javascript momentjs puppeteer

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

Error: Evaluation failed: ReferenceError: moment is not defined

在下面找到我的最小示例:

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()
})

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

对我做错了什么有什么建议吗?

感谢您的回复!

最佳答案

您只能将可序列化数据作为参数传递给 page.evaluate 函数。 (有关详细信息,请参阅 docs)。由于 moment 是一个函数,而函数不能被序列化,所以你不能那么容易地使用它。

要从您的 Node.js 环境向页面公开一个函数,您可以使用 page.exposeFunction .引用自文档:

The method adds a function called name on the page's window object. When called, the function executes puppeteerFunction in node.js and returns a Promise which resolves to the return value of puppeteerFunction.

代码示例:

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

await page.exposeFunction('formatDate', (date) =>
  moment(date, 'M/DD/YYYY').toDate()
);

请注意,您只需在页面上调用一次 exposeFunction,因为它会在导航后继续存在。这意味着您可以将这段代码放在循环之外。

然后你的 puppeteer 代码可以使用这样的函数:

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

关于javascript - Puppeteer - Page.evaluate 使用 moment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56408206/

相关文章:

javascript - Django:在 Javascript 中启用翻译的简单方法?

javascript - 无法加载 chrome 中 500 内部服务器错误的响应

javascript - jQuery 防止函数在点击时重复

javascript - 如果与 match() 一起使用,正则表达式将不起作用

javascript - Momentjs utc() 在本地 (Mac) 和服务器 (Ubuntu) 上的工作方式不同

javascript - Puppeteer 不会点击元素

node.js - moment.js 在不同时区给出错误的时间

angular - 防止定时器在后台模式下暂停

html - 使用 puppeteer 抓取表以获取特定数据

javascript - Puppeteer 屏幕截图缺少/不可见文本