You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Puppeteer无法获取页面DOM元素实时值问题求助

Puppeteer点击按钮后DOM值更新但获取不到最新值的问题

问题描述

我正在试用Puppeteer,遇到一个问题:编写了两个函数,一个用于点击按钮增加购物车商品数量,另一个用于获取点击后应更新的页面DOM元素值。点击按钮后,浏览器中能看到DOM元素值已更新,但通过button.evaluate()获取的结果却和未点击时一致。

我在第一个函数中两次获取值:一次是DOM元素的初始值,另一次是点击后的预期值(应比初始值大1),问题就出在这个流程里。

已尝试方案

  • 使用anElementHandle.evaluateHandle(),但似乎访问的是DOM快照
  • 最初使用anElementHandle.evaluate()方法
  • 用page.evaluate()手动选择输入框

个人想法

我猜测可以通过刷新页面获取新值,但这方法繁琐且没必要,希望了解底层原理来解决问题。

版本信息

  • Puppeteer版本:22.7.0
  • Node版本:20.12.2 LTS

相关代码

增加购物车数量的函数

async function increaseItemInCartByOne(plusButton: ElementHandle, shoppingCartAPI: any) {
  try {
    const previousAmount = await shoppingCartAPI.cartItemAmountNumberByButton(plusButton)
    while (true) {
      const [_, response] = await Promise.all([
        plusButton.click(),
        page?.waitForResponse(r => r.request().url().includes('/cesta/') && r.request().method() === "PUT")
      ])

      if (response?.status() === 200) {
        const currentAmount = await shoppingCartAPI.cartItemAmountNumberByButton(plusButton)
        
        if (currentAmount === previousAmount) {
          const message = await getUIWarningMessage(4000) as string
          const outOfStock = message?.search(/lo sentimos no puede llevar la cantidad solicitada/i) >= 0
          if (outOfStock) {
            throw new Error("This item is now out of stock")
          } else throw new Error("Don't know what's happening")
        } else if (currentAmount > previousAmount) break;
      }
    }
  } catch (error) {
    console.log(error)
  }
}

购物车操作API函数

async function shoppingCartAPI() {
  await gotoCartMenu()
  const productItemRows = await page?.$$(".table-row.prod-item-info")
  if (!productItemRows) throw new Error("Shopping Cart is probably empty. Aborting")

  return {
    cartItemAmountNumberByButton: async (button: ElementHandle) => {
      const updatedValue = await page?.evaluate((button) => button.previousElementSibling?.getAttribute("value")?.trim(), button);

      const newUpdatedValue = await page?.evaluate(() => {
        const newValue = document.querySelector(".table-row.prod-item-info:nth-child(2) .btn.cart-plus-btn")
        console.log(newValue)
        console.log(newValue?.previousElementSibling?.getAttribute("value"))
        return newValue?.previousElementSibling?.getAttribute("value")?.trim()
      });
          
      return Number(updatedValue)
    },
    getBuyAnotherItemInCartButtons: async () => {
      const buttons = []
      for (const row of productItemRows) {
        buttons.push(
          (await row.evaluateHandle((productRow) => {
            const btn = productRow.querySelector(".btn.cart-plus-btn")
            return btn
          })).asElement()
        )
      }

      if (buttons.length !== productItemRows.length)
        logger.error(`There are ${productItemRows.length} product(s) in cart and ${buttons.length} buttons for adding items are missing. This is weird`)

      return buttons
    }
  }
}

解决方案

核心问题分析

  1. 误用getAttribute("value"):输入框的实时值存在input.value属性中,getAttribute("value")仅返回HTML上的初始属性值,不会同步更新。
  2. 未等待DOM完成更新:仅等待PUT请求响应不足以确保页面DOM已完成渲染,可能存在前端异步更新的延迟。
  3. 冗余的硬编码查询:cartItemAmountNumberByButton中第二个page.evaluate硬编码选择第二行按钮,与传入的目标按钮无关,属于无效代码。

具体修复步骤

  1. 修正值获取方式:将getAttribute("value")替换为input.value,获取实时值:
cartItemAmountNumberByButton: async (button: ElementHandle) => {
  const updatedValue = await button.evaluate(btn => {
    const input = btn.previousElementSibling;
    return input?.value?.trim(); // 用value属性获取实时值
  });
  return Number(updatedValue);
}
  1. 等待DOM值完成更新:在获取新值前,添加等待逻辑确保值已变化:
// 在点击响应成功后,先等待值变化再获取
if (response?.status() === 200) {
  // 等待输入框值与初始值不同
  await page?.waitForFunction(
    (btn, prevVal) => btn.previousElementSibling?.value !== prevVal,
    {},
    plusButton,
    previousAmount.toString()
  );
  const currentAmount = await shoppingCartAPI.cartItemAmountNumberByButton(plusButton);
  // 后续逻辑不变
}
  1. 移除冗余代码:删除cartItemAmountNumberByButton中硬编码查询第二行按钮的代码,避免干扰结果。

内容的提问来源于stack exchange,提问作者d3vr10

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 06:14:59