为了账号安全,请及时绑定邮箱和手机立即绑定

CefSharp网页元素点击

CefSharp网页元素点击

C#
跃然一笑 2021-11-14 17:06:49
我正在尝试对某些页面元素(如 btn 或链接)进行简单的点击。我编写了 2 个通过 xpath 和 CSS 选择器单击的函数。这两个功能在浏览器的开发者控制台中都可以完美运行,但在 CEF 中部分不起作用。代码完美地点击来自开发者控制台和 Cef 的简单链接代码完美地点击了来自开发者控制台的确切按钮,但不会从 CEF 中点击。出于某种原因,它只是忽略它......怎么会这样?js代码完全一样!...    public void Click(string xpath)    {        var js = "document.evaluate(\"" + xpath + "\", document, null, XPathResult.ANY_TYPE, null).iterateNext().click();";        EvaluateJavascript(js);    }    public void ClickCss(string css)    {        var js = "document.querySelector('"+ css + "').click()";        EvaluateJavascript(js);    }    public async Task EvaluateJavascript(string script)    {        JavascriptResponse javascriptResponse = await Browser.GetMainFrame().EvaluateScriptAsync(script);        if (!javascriptResponse.Success)        {            throw new JavascriptException(javascriptResponse.Message);        }    }细节: 使用的点击代码:_browser.ClickCss("#upload-container a");再一次:相同的 js 代码在浏览器开发控制台中完美运行,但由于某种原因在 CEF 中不起作用。顺便说一下,我已经在 Chrome 中测试了 JS 代码。所以 WebEngine 在这两种情况下都是一样的。PS:也适用于我模拟将某些特定文件拖放到某些特定 Web 元素的过程。但是我没有找到任何关于此的信息,不适用于 Cef,不适用于 Js,不适用于 JQuery ... =(
查看完整描述

2 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

问题在于 JS 代码的安全限制。


问题的解决方法是:


使用 JS 代码获取按钮/链接的坐标

使用 CEF 模拟点击操作:


public void MouseClick(int x, int y)

{

    Browser.GetBrowser().GetHost().SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);

    Thread.Sleep(15);

    Browser.GetBrowser().GetHost().SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None);

}


查看完整回答
反对 回复 2021-11-14
?
狐的传说

TA贡献1804条经验 获得超3个赞

上面的答案工作正常。我只是想补充一些我认为非常重要的信息......



获取 DOM 元素的位置,并模拟鼠标点击(和移动):


// get button's position

string jsonString = null;

var jsReponse = await chromiumWebBrowser1.EvaluateScriptAsync(

@"(function () {

    var bnt = document.getElementById('pnnext');

    bnt.focus();

    var bntRect = bnt.getBoundingClientRect();

    return JSON.stringify({ x: bntRect.left, y: bntRect.top });

})();"

);

if (jsReponse.Success && jsReponse.Result != null)

    jsonString = (string)jsReponse.Result;


// send mouse click event

if (jsonString != null)

{

    var jsonObject = JObject.Parse(jsonString);

    var xPosition = (int)jsonObject["x"] + 1;  // add +1 pixel to the click position

    var yPosition = (int)jsonObject["y"] + 1;  // add +1 pixel to the click position


    var host = chromiumWebBrowser1.GetBrowser().GetHost();

    host.SendMouseMoveEvent(xPosition, yPosition, false, CefEventFlags.None);

    Thread.Sleep(50);

    host.SendMouseClickEvent(xPosition, yPosition, MouseButtonType.Left, false, 1, CefEventFlags.None);

    Thread.Sleep(50);

    host.SendMouseClickEvent(xPosition, yPosition, MouseButtonType.Left, true, 1, CefEventFlags.None);

}

1 -到目前为止,在 CefSharp 上获取 DOM 元素位置的最佳方法是执行自定义 JavaScript并解析结果。这就是上面代码第一段的目的。它通过其 ID(在加载的网页的 HTML 结构中定义)获取元素,然后获取其相对于视口的位置,然后将其返回给 C# 代码。回到 C#,我们使用 Newtonsoft 的JObject.Parse方法解析它。


2 - 单击发生在指定的x和y坐标处,但要知道该坐标是相对于浏览器组件窗口(视口)的,这一点非常重要。因此,如果您的 Web 浏览器组件只有100px高,并且您发送一个单击命令进行y协调,因为150px单击将发生但在 Web 浏览器之外,因此不在网页中。


3 - 查看点击是否真的被执行的一个技巧,以及确切的位置,是将其从 更改MouseButtonType.Left为MouseButtonType.Right。这样做,如果网页没有限制,你就能看到“鼠标右键菜单”。如果您在外部单击,您可能会在操作系统上看到“鼠标右键菜单” (此处为 Windows,我能够看到我使用此技巧在组件外部单击)。


4 - 有时(特别是在反爬虫环境中)还需要模拟鼠标移动。我使用SendMouseMoveEvent第一行中所示的方法进行操作。


5 - 如果您在组件中加载了一个非常高的页面,并且您需要单击真正超出组件边界的按钮,则需要滚动网页。您可以按照上面的示例代码执行一些 JavaScript,或者您可以使用以下代码执行此操作:



模拟鼠标滚动(鼠标滚轮事件):


// send scroll command

// (mouse position X, mouse position Y, how much to scroll X, how much to scroll Y, events)

chromiumWebBrowser1.GetBrowser().GetHost().SendMouseWheelEvent(10, 10, 0, -100, CefEventFlags.None); 

Thread.Sleep(300);

参数的最大部分是不言自明的,但这里最重要的部分是第3和第4个参数,分别是“滚动X多少”和“Y滚动多少”。要向下滚动,只需使用负值,向上滚动则使用正值。在上面的代码中,它水平(x轴)不滚动(零像素),垂直(y轴)向下滚动 100 像素。


您可以在 a 中使用此代码loop来滚动您需要的数量。我将它与 JavaScript 代码结合使用来检索按钮的位置,检测它是否在视口上,或者我是否需要再次发送滚动事件


查看完整回答
反对 回复 2021-11-14
  • 2 回答
  • 0 关注
  • 2127 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信