Получить ссылки на html-документ для упорядочения

c# html html-agility-pack regex webbrowser-control

Вопрос

Я хочу получить все ссылки 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++;
            }
        }
    }

Заранее спасибо, Opak

Популярные ответы

Вы можете получить правильный порядок, пройдя дерево DOM с помощью HTML DOM API . Следующий код делает это. Обратите внимание: я использую dynamic доступ к API DOM. Это связано с тем, что HtmlElement.FirstChild HtmlElement.NextSibling WebBrowser HtmlElement.FirstChild / HtmlElement.NextSibling не работает для этой цели, поскольку они возвращают значение null для текстовых узлов DOM.

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);
}

[UPDATE] Если вам действительно нужно получить список объектов HtmlElement для тэгов <A> вместо dynamic собственных элементов, это все еще возможно с помощью небольшого трюка с использованием GetElementById :

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);
}


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow