【问题标题】:Why is EvaluateScriptAsync returning an empty expando object in CefSharp为什么 EvaluateScriptAsync 在 CefSharp 中返回一个空的 expando 对象
【发布时间】:2019-08-31 13:09:00
【问题描述】:

我正在尝试使用 CefSharp 在 C# 中编写应用程序。我的意图是获取给定页面上的所有链接,例如,

https://wixlabs---dropbox-folder.appspot.com/index?instance=lp5CbqBbK6JUFzCW2hXENEgT4Jn0Q-U1-lIAgEbjeio.eyJpbnN0YW5jZUlkIjoiYjNiNzk5YjktNjE5MS00ZDM0LTg3ZGQtYjY2MzI1NWEwMDNhIiwiYXBwRGVmSWQiOiIxNDkyNDg2NC01NmQ1LWI5NGItMDYwZi1jZDU3YmQxNmNjMjYiLCJzaWduRGF0ZSI6IjIwMTgtMDEtMjJUMTg6Mzk6MjkuNjAwWiIsInVpZCI6bnVsbCwidmVuZG9yUHJvZHVjdElkIjpudWxsLCJkZW1vTW9kZSI6ZmFsc2V9&target=_top&width=728&compId=comp-j6bjhny1&viewMode=viewer-seo

当我加载页面并打开开发工具并执行时

document.getElementsByTagName('a');

在开发工具中,我得到 374 个结果。接下来我从 BrowserLoadingStateChanged 执行以下代码:-

private async Task ProcessLinksAsync()
        {
            var frame = browser.GetMainFrame();
            var response = await frame.EvaluateScriptAsync("(function() { return document.getElementsByTagName('a'); })();", null);
            ExpandoObject result = response.Result as ExpandoObject;

            Console.WriteLine("Result:" + result);//What do I do here?
        }

我得到了一个似乎什么都没有的 expando 对象。我这样说是因为我使用了断点并检查了对象。我已经经历了https://keyholesoftware.com/2019/02/11/create-your-own-web-bots-in-net-with-cefsharp/https://github.com/cefsharp/CefSharp/wiki/General-Usage#javascript-integration 和关于 SO 的问题,但无法解决我的问题。 我在这里做错了吗? 我的实际意图是获取链接,然后导航到它们。 提前致谢。

编辑: 我在浏览器和开发工具中使用了以下脚本,都返回 187 个结果,这是正确的。

(function() { 
    var links=document.getElementsByClassName('file-link'); 
    var linksArray = new Array(); 
    for (var i = 0; i < links.length; i++) { 
        linksArray[i] = String(links[i].href); 
    } 
    return linksArray; 
})(); 

但在我的应用程序中,我得到一个长度为 0 的数组。

EDIT-2: 我使用以下代码获取 DOM:-

public void OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
        {
            ContextCreated?.Invoke(this, frame);
            const string script = "document.addEventListener('DOMContentLoaded', function(){ alert(document.links.length); });";

            frame.ExecuteJavaScriptAsync(script);
        }

对于我尝试过的所有其他网站,代码都是成功的,除了上面提到的 URL。任何人都可以告诉我在开发工具中加载 DOM 并且完全可访问时可能出现的问题。所以,我想我的代码中可能缺少一些东西。 再次感谢。

【问题讨论】:

  • getElementsByTagName 的返回类型是什么?类型是数组吗?我问这个知道这两个问题的答案,我认为如果你还不知道,那么研究答案很重要。
  • 请原谅我的无知。我基本上是一个不精通 Web 技术的桌面开发人员。但是这个项目要求我使用网络技术。所以我想知道你是否可以指导我一点。请参阅上面的编辑。我觉得我做错了什么,但机器人很确定在哪里。再次感谢。
  • 我刚刚发现预期的页面没有加载。我刚刚发现这个 Gist 似乎很相关。gist.github.com/amaitland/40394439ddefdf4e66b7
  • 行为看起来有点奇怪。我使用 url 初始化浏览器并获取页面已加载的消息。然后我执行 browser.Load() 并获取之前加载的页面,该页面可能当时没有加载。我有什么特别需要做的吗?
  • 我尝试了上面链接中的代码,但找不到 NavStateChangedEventArgs 和 browser.NavStateChanged。

标签: javascript c# cefsharp chromium-embedded


【解决方案1】:

您需要等待页面加载。此外,如果页面使用 ajax 加载数据,您需要稍等片刻才能加载数据。然后你需要将结果塑造成一个自定义的 javascript 对象。

ChromiumWebBrowser browser;
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    browser = new ChromiumWebBrowser(
        "https://google.com/"); // Tried with your URL. 
    browser.LoadingStateChanged += Browser_LoadingStateChanged;
    browser.Dock = DockStyle.Fill;
    Controls.Add(browser);
}

private async void Browser_LoadingStateChanged(object sender,
    LoadingStateChangedEventArgs e)
{
    if (!e.IsLoading)
    {
        await Task.Delay(5000); //Just for pages which use ajax loading data
        var script = @"
        (function () {
            var data = document.getElementsByTagName('a');
            return Array.from(data, a => ({href:a.href, innerText:a.innerText}));
        })();";
        var result = await browser.EvaluateScriptAsync(script);
        var data = (IEnumerable<dynamic>)result.Result;

        MessageBox.Show(string.Join("\n", data.Select(x=>$"{x.href}").Distinct()));
    }
}

【讨论】:

猜你喜欢
  • 2020-08-02
  • 2020-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
  • 2016-06-04
  • 2021-08-10
相关资源
最近更新 更多