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

如何使用Puppeteer监听指定span元素的文本内容变化

Hey there! Let's tackle your problem step by step. The issues you're facing come down to two key points: passing non-serializable values to waitForFunction (which causes the circular structure error) and using a static condition that doesn't fit your need to track any status change. Here's how to fix this and achieve your goal of logging every status update with timestamps:

This is the most efficient and reliable way to track text changes in an element, as it listens directly for DOM mutations instead of polling the element repeatedly.

const page = await browser.newPage();
await page.goto('https://chat.com');

// Get initial status and log it
let currentStatus = await page.$eval('#status', el => el.innerText.trim());
console.log(`[${new Date().toISOString()}] Initial status: ${currentStatus}`);

// Expose a function to the browser context to log status changes
await page.exposeFunction('logStatusChange', (newStatus) => {
  console.log(`[${new Date().toISOString()}] Status updated to: ${newStatus}`);
  currentStatus = newStatus;
});

// Set up MutationObserver in the browser context to watch for text changes
await page.evaluate(() => {
  const statusElement = document.querySelector('#status');
  // Store the last seen status to avoid duplicate logs
  window.lastRecordedStatus = statusElement.innerText.trim();

  const observer = new MutationObserver((mutations) => {
    for (const mutation of mutations) {
      // Check if the change affects the element's text content
      if (mutation.type === 'characterData' || mutation.type === 'childList') {
        const updatedStatus = statusElement.innerText.trim();
        if (updatedStatus !== window.lastRecordedStatus) {
          window.lastRecordedStatus = updatedStatus;
          logStatusChange(updatedStatus);
        }
      }
    }
  });

  // Configure observer to watch for text-related changes
  observer.observe(statusElement, {
    characterData: true,
    childList: true,
    subtree: true // Required if text is nested inside child elements
  });
});

// Keep the page open to continue listening (adjust timeout as needed)
await page.waitForTimeout(3600000); // Listen for 1 hour

Option 2: Poll with waitForFunction

If you prefer a simpler approach (or if MutationObserver doesn't work for your specific DOM structure), you can use a loop with waitForFunction to check for status changes.

const page = await browser.newPage();
await page.goto('https://chat.com');

let currentStatus = await page.$eval('#status', el => el.innerText.trim());
console.log(`[${new Date().toISOString()}] Initial status: ${currentStatus}`);

// Loop indefinitely to track changes
while (true) {
  // Wait until the status differs from the current value
  await page.waitForFunction(
    (currentVal) => document.querySelector('#status').innerText.trim() !== currentVal,
    {}, // Optional: Add timeout options here if needed
    currentStatus // Pass current status as a serializable parameter
  );

  // Fetch and log the new status
  currentStatus = await page.$eval('#status', el => el.innerText.trim());
  console.log(`[${new Date().toISOString()}] Status updated to: ${currentStatus}`);
}

Why Your Original Code Failed

  1. Circular Structure Error: You tried passing statusHandle (an ElementHandle) to waitForFunction. ElementHandles are Node.js-side objects with circular references, which can't be serialized and sent to the browser context. Always use primitive values (like strings) as parameters for waitForFunction.
  2. Static Condition: Your simplified waitForFunction checked for an exact match to "Online"—if the status never changed to that value, the function would hang indefinitely. Instead, you need to wait for the status to differ from the current known value.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:08:37