Ottieni link di un documento html in ordine

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

Domanda

Voglio ottenere tutti i link di un documento HTML. Questo non è un problema, ma a quanto pare mette tutti i link in ordine alfabetico prima di memorizzarli in un array uno per uno. Voglio avere i collegamenti nell'ordine originale (non in ordine alfabetico).

Quindi c'è qualche possibilità di ottenere il primo link trovato, memorizzarlo, poi il secondo, ...? Ho già provato a utilizzare HtmlAgilityPack e i metodi di controllo Webbrowser, ma entrambi li ordiniamo alfabeticamente. L'ordine originale è importante per scopi successivi.

Ho sentito che potrebbe essere possibile con Regex, ma ho trovato abbastanza risposte, in cui dicono che non dovresti usarlo per l'analisi HTML. Quindi, come posso farlo?

Ecco il codice Webbrowser-Control, ho provato a utilizzare per ottenere i collegamenti e memorizzarli in un array:

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

Grazie in anticipo, Opak

Risposta popolare

Puoi ottenere l'ordine corretto camminando sull'albero DOM utilizzando l' API DOM HTML . Il seguente codice fa questo. Nota, utilizzo dynamic per accedere alle API DOM. Questo perché WebBrowser s' HtmlElement.FirstChild / HtmlElement.NextSibling non funzionano per questo scopo, che tornano null per Dom nodi di testo.

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

[AGGIORNAMENTO] Se hai davvero bisogno di ottenere un elenco di oggetti HtmlElement per i tag <A> , invece di elementi nativi dynamic , è ancora possibile con un piccolo trucco usando 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);
}


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché