最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Puppeteer: how to listen for on innerHTML change - Stack Overflow

programmeradmin0浏览0评论

I have a chat app with status represented by this line:

<span id='status'>Offline</span> 

and I want Puppeteer to log every time the text within this span changes.

Say, in the beginning the status was "Offline", then it was changed to "Online", and then after some time to "Away" and so on. I want Puppeteer to capture those moments and the status (Offline>Online>Away)

What I managed to do is the following:

const page = await browser.newPage();
await page.goto('');
const statusHandle = await page.$('span#status');
let statusText = await page.evaluate(() => document.querySelector('#status').innerText);
let iniVal = {statusHandle,statusText };

at this point I have the statusHandle and the initial status.

Now, my understanding (as per 1 and 2) is that I need to bine the two in

await page.waitForFunction(
  (iniVal) => iniVal.statusHandle.innerHTML !== iniVal.statusText, 
  { timeout: 0 }, 
  iniVal
) 

and place it in a loop. That's the point, where I'm struggling.

First it gives a type error "TypeError: Converting circular structure to JSON", which is due to the passed key value pairs not being primitives, but even when I oversimplify and just do (as per 1):

await page.waitForFunction(
  'document.querySelector("span#status").inner‌​Text === "Online"'
)

it yields nothing.

To sum up: I am looking to

  1. Make Puppeteer evaluate the change in document.querySelector('#status').innerText !== statusText

  2. Return the new status value

  3. Have the process run in a loop

I have a chat app with status represented by this line:

<span id='status'>Offline</span> 

and I want Puppeteer to log every time the text within this span changes.

Say, in the beginning the status was "Offline", then it was changed to "Online", and then after some time to "Away" and so on. I want Puppeteer to capture those moments and the status (Offline>Online>Away)

What I managed to do is the following:

const page = await browser.newPage();
await page.goto('https://chat.');
const statusHandle = await page.$('span#status');
let statusText = await page.evaluate(() => document.querySelector('#status').innerText);
let iniVal = {statusHandle,statusText };

at this point I have the statusHandle and the initial status.

Now, my understanding (as per 1 and 2) is that I need to bine the two in

await page.waitForFunction(
  (iniVal) => iniVal.statusHandle.innerHTML !== iniVal.statusText, 
  { timeout: 0 }, 
  iniVal
) 

and place it in a loop. That's the point, where I'm struggling.

First it gives a type error "TypeError: Converting circular structure to JSON", which is due to the passed key value pairs not being primitives, but even when I oversimplify and just do (as per 1):

await page.waitForFunction(
  'document.querySelector("span#status").inner‌​Text === "Online"'
)

it yields nothing.

To sum up: I am looking to

  1. Make Puppeteer evaluate the change in document.querySelector('#status').innerText !== statusText

  2. Return the new status value

  3. Have the process run in a loop

Share Improve this question edited May 17, 2018 at 14:20 laggingreflex 34.7k36 gold badges144 silver badges200 bronze badges asked May 17, 2018 at 13:29 denisdenis 631 silver badge4 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 4

I'd just set a recursive function with a callback:

async function monitor (selector, callback, prevValue) {
  const newVal = await page.$(selector);
  if (newVal !== prevValue) {
    callback(newVal);
  }
  /* add some delay */
  await new Promise(_ => setTimeout(_, 1000))
  /* call recursively */
  monitor (selector, callback, newVal);
}
monitor('span#status', status => {
  // Fires whenever `status` changes
})

Rather than polling with recursion and setTimeout, better use MutationObserver like in this answer.

发布评论

评论列表(0)

  1. 暂无评论