c# - 基本对象 WebView 如何在 HTML 树中导航?

标签 c# html

我正在使用 Essential 对象库来读取网站。

我之前曾使用 Windows Forms WebBrowser 完成此操作,但这次该网站无法使用 Windows Forms WebBrowser 运行,因此我不得不更改为 EO WebView。

纪录片太差了,我找不到答案。

在 Windows 窗体 Web 浏览器中,您有一个 HtmlElementCollection,原则上它是 HtmlElement 的列表。 在这些元素上,您可以读出属性或创建 InvokeMember("Click") 并浏览子/父元素。

EO WebView 中与此 HtmlElementCollection/HtmlElement 等效的是什么? 如何浏览 HTML 树?

顺便说一句:我将它与 C# 一起使用。

最佳答案

请参阅文档:here , here , here .

本质上,你必须依赖执行 JavaScript 的能力。

您可以通过多种方式访问​​文档 JavaScript 对象:

JSObject document = (JSObject)_webView.EvalScript("document");

//or: Document document = _webView.GetDOMWindow().document;   

GetDOMWindow() 返回一个 EO.WebBrowser.DOM.Document 实例;该类型派生自 JSObject 并提供一些额外的属性(例如,有一个 body 属性可以获取 EO.WebBrowser.DOM.Element< 类型的 BODY 元素)。
但总的来说,这些提供的 API 并没有丰富多少。

你可以像这样使用 JSObject:

// access a property on the JavaScript object:
jsObj["children"]    

// access an element of an array-like JavaScript object:
var children = (JSObject)jsObj["children"];
var first = (JSObject)children[0];

// (note that you have to cast; all these have the `object` return type)

// access an attribute on the associated DOM element
jsObj.InvokeFunction("getAttribute", "class")

// etc.

这一切都有点繁琐,但是您可以编写一些扩展方法来让您的生活更轻松(但是,请参阅下面有关性能的注释):

public static class JSObjectExtensions
{
    public static string GetTagName(this JSObject jsObj)
    {
        return (jsObj["tagName"] as string ?? string.Empty).ToUpper();
    }

    public static string GetID(this JSObject jsObj)
    {
        return jsObj["id"] as string ?? string.Empty;
    }

    public static string GetAttribute(this JSObject jsObj, string attribute)
    {
        return jsObj.InvokeFunction("getAttribute", attribute) as string ?? string.Empty;
    }

    public static JSObject GetParent(this JSObject jsObj)
    {
        return jsObj["parentElement"] as JSObject;
    }

    public static IEnumerable<JSObject> GetChildren(this JSObject jsObj)
    {
        var childrenCollection = (JSObject)jsObj["children"];
        int childObjectCount = (int)childrenCollection["length"];
        for (int i = 0; i < childObjectCount; i++)
        {
            yield return (JSObject)childrenCollection[i];
        }
    }

    // Add a few more if necessary
}

然后你可以这样做:

private void TraverseElementTree(JSObject root, Action<JSObject> action)
{
    action(root);
    foreach(var child in root.GetChildren())
        TraverseElementTree(child, action);
}

以下是如何使用此方法的示例:

TraverseElementTree(document, (currentElement) =>
{
    string tagName = currentElement.GetTagName();
    string id = currentElement.GetID();
    if (tagName == "TD" && id.StartsWith("codetab"))
    {
        string elementClass = currentElement.GetAttribute("class");
        // do something...
    } 
});

但是,这又有点繁琐 - 虽然这似乎工作得相当好,但您需要进行一些实验以找到可能导致错误的任何棘手部分,并找出如何修改方法来实现它更稳定。

性能说明

另一种选择是使用 JavaScript 进行大部分元素处理,并仅返回需要在 C# 代码中使用的值。根据逻辑的复杂程度,这在某些情况下可能会更有效,因为它会导致单个浏览器引擎往返,因此如果性能成为问题,则需要考虑。 (请参阅“性能”部分 here。)

关于c# - 基本对象 WebView 如何在 HTML 树中导航?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61455398/

相关文章:

c# - ASP.Net Core MVC 中的本地化不起作用 - 无法找到资源文件

C# 如何判断 IEnumerable 是否可变?

c# - Asp.net 强制保存详细信息 View /表单 View

c# - 通过 C# 将小数坐标转换为度、分和秒

javascript - Jquery 没有按要求删除所有内容

html/templates - 用 <br> 替换换行符

javascript - 如何获取表单输入值并插入div内部html

c# - 哪种语言习语/范式/特性使得添加对 "type providers"的支持变得困难?

php - 当数据发送到 mySQL 时如何将数据添加到特定表单元素

html - 在 DIV 中垂直居中 UL