添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

想要在CEF3中访问DOM元素,只需要一句代码就可以得到DOM

browser->GetMainFrame()->VisitDOM(new DomVisitTestor());

但是这一句代码放在那里执行还是比较有讲究的。
这里的DomVisitTestor是继承自CefDOMVisitor的类,起什么名字都可以。只需要实现唯一的函数

virtual void Visit(CefRefPtr<CefDOMDocument> document) =0;

CEF会自动的调用这个Visit()并且把当前的DOM快照传递给我们

一、调用时机的选择

首先我们想要获取到完整的DOM就需要在页面加载完成之后再获取DOM,这时候的DOM是比较完成的,页面的元素都是存在的。
页面加载完成会触发一个函数:

virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,int httpStatusCode) 
	CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("get_dom");
    // Retrieve the argument list object.
    CefRefPtr<CefListValue> args = msg->GetArgumentList();
    // Populate the argument values.
    args->SetSize(2);
    args->SetString(0, "user");
    args->SetString(1, "password");
    // 通知Renderer进程,页面加载完成,继续进行下一步操作。
    browser->SendProcessMessage(PID_RENDERER, msg);

该函数是CefLoadHandler 类的一个方法,我们可以重载该方法,在页面加载完成的时候,做一些额外的操作。首先让demo中的SimpleHandler类继承CefLoadHandler,其次重载该方法,
由于该方法时在browser进程中调用的。鉴于VisitDOM()方法只能在render进程中调用,这里我们需要发送消息让render进程去获取DOM

二、Render和Browser进程通信,获取DOM

  1. 首先需要让我们的App可以处理Render进程的事务,需要让SimpleApp继承自CefRenderProcessHandler 并且实现方法GetRenderProcessHandler()
  virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler()
	  OVERRIDE { return this; }
  1. 实现进程间通信的接口OnProcessMessageReceived(...)
bool SimpleApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message)
    if (message->GetName() == "get_dom") {
        // 页面加载完成,访问DOM 进行下一步操作
        browser->GetMainFrame()->VisitDOM(new DomVisitTestor());
    return false;
  1. 其次也是最重要的一步让我们的程序接管Render进程。在cefsimple_win.cc 中的wWinMain稍作修改。
// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPTSTR    lpCmdLine,
                      int       nCmdShow) {
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);
  // Enable High-DPI support on Windows 7 or newer.
  CefEnableHighDPISupport();
  void* sandbox_info = NULL;
#if defined(CEF_USE_SANDBOX)
  // Manage the life span of the sandbox information object. This is necessary
  // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
  CefScopedSandboxInfo scoped_sandbox;
  sandbox_info = scoped_sandbox.sandbox_info();
#endif
  // SimpleApp implements application-level callbacks for the browser process.
// It will create the first browser instance in OnContextInitialized() after
// CEF has initialized.
  CefRefPtr<SimpleApp> app(new SimpleApp);
  // Provide CEF with command-line arguments.
  CefMainArgs main_args(hInstance);
  // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
  // that share the same executable. This function checks the command-line and,
  // if this is a sub-process, executes the appropriate logic.
  int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  // Specify CEF global settings here.
  CefSettings settings;
#if !defined(CEF_USE_SANDBOX)
  settings.no_sandbox = true;
#endif
  // Initialize CEF.
  CefInitialize(main_args, settings, app.get(), sandbox_info);
  // Run the CEF message loop. This will block until CefQuitMessageLoop() is
  // called.
  CefRunMessageLoop();
  // Shut down CEF.
  CefShutdown();
  return 0;

三、Render进程调试方法

到此呢程序已经可以正确获取到DOM了。 由于获取DOM的函数适在Render进程中的,直接在VS中调试启动的是Browser,因此调试起来较为麻烦。

  1. 生成的应用程序创建快捷方式,追加参数--renderer-startup-dialog --no-sandbox 在这里插入图片描述
  2. 双击快捷方式启动,程序会弹出一个对话框提示Render进程的进程ID
    在这里插入图片描述
  3. 使用VS的 附加到进程 功能选择上一步弹窗中的进程ID相同的进程附加在这里插入图片描述
  4. 点击第二步弹出的对话框上的确定,等待页面加载完成,断点就会命中,DOM获取成功。在这里插入图片描述在这里插入图片描述
在客户端的 JavaScript ,可以使用 navigator.userAgent 属性获取浏览器的 User-Agent,从而进行 User-Agent 检测。这样,在之后的代码调用 Date() 方法时,将会返回我们所创建的新的 Date 对象,从而实现了修改浏览器时间的效果。这样,当使用 ChromiumWebBrowser 访问网页时,CefSharp 会发送一个虚假的 User-Agent,从而欺骗客户端的 User-Agent 检测。 随便写的一个demo,需要以下支持: raize 下载地址:http://download.csdn.net/detail/bants/9861776 cef4delphi 下载地址:https://github.com/salvadordf/CEF4Delphi http://download.csdn.net/detail/bants/9862730 cef3 binaris : 32bit -> http://opensource.spotify.com/cefbuilds/cef_binary_3.3071.1634.g9cc59c8_windows32.tar.bz2 64bit -> http://opensource.spotify.com/cefbuilds/cef_binary_3.3071.1634.g9cc59c8_windows64.tar.bz2 CefSharp的SendMouseClickEvent,通过此函数发送鼠标点击事件。 操作方法 先借助jQuery获取指定DOM的偏移,然后发送SendMouseClickEvent完成模拟点击操作。 /// <summary> /// 模拟点击指定选择符DOM元素 /// </summary> /// <param name="selector"&gt... 有时你可能想在C++代码直接操作HTML的某个元素,比如改变某个按钮的状态(文字、颜色)等,此时可以使用CEF提供的CefDomVisitor、CefDOMDocument、CefDomNode这三个类 public bool OnFileDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, CefFileDialogMode mode, CefFileDialogFlags flags, string title, string defaultFilePath, List<string> acceptFilters, Hello,亲爱的小伙伴们,欢迎浏览“使用CefSharp和Javascript实现网络爬虫”。本篇是第2篇,介绍在实现爬虫过程会用到的Javascript和C#主要知识点。在使用CefSharp和Javascript实现网络爬虫过程,我使用到的C#和Javascript知识主要包括三个方面:一是Javascript的Dom操作;二是CefSharpJavascript和C#之间的调用和交互...