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

如何让Selenium ChromeDriver在元素变化时执行回调(C#)

监听网页Div内容变化的C#实现方案

要替代轮询实现精准响应Div内容变化,核心是利用浏览器原生的MutationObserver API监听DOM变更,再通过C#与网页的通信机制把变更事件同步到C#代码中。以下分两种常见场景给出实现方案:

场景一:使用Selenium自动化浏览器

适合爬虫或自动化测试场景,通过Selenium的DevTools协议接收网页发送的变更通知:

实现步骤

  1. 初始化Selenium驱动并加载目标网页
  2. 注入MutationObserver脚本监听目标Div的内容变化
  3. 通过DevTools协议监听网页的控制台输出接收变更数据
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
using OpenQA.Selenium.DevTools.V119.Runtime;
using System.Text.Json;

// 初始化Chrome驱动
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("你的目标网页URL");

// 注入MutationObserver脚本,监听mydiv的内容变更
var observerScript = @"
const target = document.getElementById('mydiv');
const observer = new MutationObserver(mutations => {
  mutations.forEach(() => {
    // 将变更内容序列化为JSON并输出到控制台
    console.log(JSON.stringify({
      type: 'divUpdate',
      content: target.textContent.trim()
    }));
  });
});
// 配置监听规则:监听子节点变化(内容变更属于子节点更新)
observer.observe(target, { childList: true, subtree: true });
";

((IJavaScriptExecutor)driver).ExecuteScript(observerScript);

// 启用DevTools会话监听控制台输出
var devTools = driver as IDevTools;
var session = devTools.GetDevToolsSession();
await session.Runtime.Enable(new EnableCommandSettings());

// 注册控制台消息回调
session.Runtime.ConsoleAPICalled += (sender, e) =>
{
  if (e.Type != ConsoleAPICalledEventType.Log) return;
  
  foreach (var arg in e.Args)
  {
    var rawData = arg.Value.ToString();
    if (!rawData.Contains("divUpdate")) continue;
    
    var updateData = JsonSerializer.Deserialize<DivUpdateData>(rawData);
    // 这里处理内容变更逻辑
    Console.WriteLine($"Div内容已更新:{updateData.Content}");
  }
};

// 用于接收变更数据的模型类
public class DivUpdateData
{
  public string Type { get; set; }
  public string Content { get; set; }
}

场景二:使用WebView2嵌入网页(WinForms/WPF)

适合桌面应用嵌入网页的场景,WebView2支持JS与C#的双向直接通信,实现更简洁:

实现步骤

  1. 初始化WebView2控件并加载网页
  2. 将C#回调对象注册到JS全局环境
  3. 注入MutationObserver脚本,触发时直接调用C#的回调方法
using Microsoft.Web.WebView2.Core;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public partial class MainForm : Form
{
  public MainForm()
  {
    InitializeComponent();
    Load += MainForm_Load;
  }

  private async void MainForm_Load(object sender, EventArgs e)
  {
    // 初始化WebView2
    await webView21.EnsureCoreWebView2Async();
    webView21.CoreWebView2.Navigate("你的目标网页URL");

    // 将C#回调对象注册到JS,命名为DivChangeHandler
    webView21.CoreWebView2.AddHostObjectToScript("DivChangeHandler", new DivChangeCallback());

    // 注入MutationObserver脚本
    var observerScript = @"
const target = document.getElementById('mydiv');
const observer = new MutationObserver(mutations => {
  mutations.forEach(() => {
    // 直接调用C#的回调方法
    window.chrome.webview.hostObjects.sync.DivChangeHandler.OnContentChanged(target.textContent.trim());
  });
});
observer.observe(target, { childList: true, subtree: true });
";
    await webView21.CoreWebView2.ExecuteScriptAsync(observerScript);
  }
}

// 回调类需标记为ComVisible才能被JS访问
[ComVisible(true)]
public class DivChangeCallback
{
  public void OnContentChanged(string newContent)
  {
    // 处理内容变更,注意WinForms/WPF需切换回UI线程操作控件
    Console.WriteLine($"Div内容更新为:{newContent}");
    
    // 示例:更新WinForms控件(需Invoke避免跨线程异常)
    // Application.OpenForms[0].Invoke(new Action(() => {
    //   label1.Text = newContent;
    // }));
  }
}

关键注意事项

  • MutationObserver配置:必须设置childList: true,因为Div内容变更本质是文本子节点的替换;如果内容包含嵌套元素,需额外开启subtree: true监听所有子节点变更。
  • 资源清理:不再需要监听时,需在JS中调用observer.disconnect()释放资源,避免内存泄漏。
  • 跨线程处理:在UI框架中(WinForms/WPF),回调方法运行在非UI线程,需用Invoke/Dispatcher.Invoke切换回UI线程操作控件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:42:54