【问题标题】:Get links of a html document in order按顺序获取html文档的链接
【发布时间】:2013-12-16 22:04:35
【问题描述】:

我想获取 HTML 文档的所有链接。这不是问题,但显然它会将所有链接按字母顺序排列,然后将它们一个一个存储在一个数组中。我希望链接按原始顺序(不是字母顺序)。

那么有没有可能获得第一个找到的链接,存储它,然后是第二个,...?我已经尝试过使用 HtmlAgilityPack 和 Webbrowser-Control 方法,但它们都按字母顺序排列。原始顺序对于以后的用途很重要。

我听说使用 Regex 可能是可行的,但我找到了足够多的答案,他们说您不应该将其用于 HTML 解析。那我该怎么做呢?

这是 Webbrowser-Control 代码,我尝试使用它来获取链接并将它们存储到数组中:

    private void btnGet_Click(object sender, EventArgs e)
    {
        HtmlWindow mainFrame = webFl.Document.Window.Frames["mainFrame"];
        HtmlElementCollection links = mainFrame.Document.Links;

        foreach (HtmlElement link in links)
        {
            string linkText = link.OuterHtml;
            if (linkText.Contains("puzzle"))
            {
                arr[i] = linkText;
                i++;
            }
        }
    }

提前谢谢你, 奥帕克

【问题讨论】:

  • 尝试使用 for 循环而不是 foreach 进行迭代。它可能会起作用
  • 当然不会,foreach 不会自动破坏元素的顺序。 . .
  • 您要使用哪种类型的页面?它必须适用于所有页面还是您有特定的目标?因为如果您只能坚持使用 XHTML 页面,那么您可以将它们视为 xml 并为此使用 linq to XML,从而绕过其他库并编写非常简单的代码
  • 据我所知,返回之前既不知道 HtmlAgilityPack 也不知道 HtmlDocument 订单元素。您是否绝对确定订单与 HTML 不匹配,并且您在某处没有某种 OrderBy/Sort 代码?

标签: c# html regex webbrowser-control html-agility-pack


【解决方案1】:

您可以通过使用HTML DOM API 遍历 DOM 树来获得正确的顺序。以下代码执行此操作。注意,我使用dynamic 来访问 DOM API。这是因为 WebBrowser 的 HtmlElement.FirstChild/HtmlElement.NextSibling 不能用于此目的,因为它们会为 DOM 文本节点返回 null。

private void btnGet_Click(object sender, EventArgs e)
{
    Action<object> walkTheDom = null;
    var links = new List<object>();

    // element.FirstChild / NextSibling don't work as they stop at DOM text nodes

    walkTheDom = (element) =>
    {
        dynamic domElement = element;
        if (domElement.tagName == "A")
            links.Add(domElement);
        for (dynamic child = domElement.firstChild; child != null; child = child.nextSibling)
        {
            if (child.nodeType == 1) // Element node?
                walkTheDom(child);
        }
    };

    walkTheDom(this.webBrowser.Document.Body.DomElement);

    string html = links.Aggregate(String.Empty, (a, b) => a + ((dynamic)b).outerHtml + Environment.NewLine);
    MessageBox.Show(html);
}

[更新] 如果您确实需要为&lt;A&gt; 标签获取HtmlElement 对象列表,而不是dynamic 原生元素,使用@987654331 的小技巧仍然可以@:

private void btnGet_Click(object sender, EventArgs e)
{
    // element.FirstChild / NextSibling don't work because they stop on DOM text nodes

    var links = new List<HtmlElement>();
    var document = this.webBrowser.Document;
    dynamic domDocument = document.DomDocument;
    Action<dynamic> walkTheDom = null;

    walkTheDom = (domElement) =>
    {
        if (domElement.tagName == "A")
        {
            // get HtmlElement for the found <A> tag
            string savedId = domElement.id;
            string uniqueId = domDocument.uniqueID;
            domElement.id = uniqueId;
            links.Add(document.GetElementById(uniqueId));
            if (savedId != null)
                domElement.id = savedId;
            else
                domElement.removeAttribute("id");
        }
        for (var child = domElement.firstChild; child != null; child = child.nextSibling)
        {
            if (child.nodeType == 1) // is an Element node?
                walkTheDom(child);
        }
    };

    // walk the DOM for <A> tags
    walkTheDom(domDocument.body);

    // show the found tags
    string combinedHtml = links.Aggregate(String.Empty, (html, element) => html + element.OuterHtml + Environment.NewLine);
    MessageBox.Show(combinedHtml);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-28
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多