Obtenir les liens d'un document HTML dans l'ordre

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

Question

Je veux obtenir tous les liens d'un document HTML. Ce n’est pas un problème, mais apparemment, il place tous les liens dans un ordre alphabétique avant de les stocker dans un tableau un par un. Je veux avoir les liens dans l'ordre original (pas en ordre alphabétique).

Alors, y a-t-il une possibilité d'obtenir le premier lien trouvé, de le stocker, puis le second, ...? J'ai déjà essayé d'utiliser HtmlAgilityPack et les méthodes Webbrowser-Control, mais les deux sont classés par ordre alphabétique. La commande originale est importante pour les besoins ultérieurs.

J'ai entendu dire que cela pourrait être possible avec Regex, mais j'ai trouvé suffisamment de réponses, où ils disent qu'il ne faut pas l'utiliser pour l'analyse HTML. Alors, comment puis-je le faire?

Voici le code de Webbrowser-Control, que j'ai essayé d'utiliser pour obtenir les liens et les stocker dans un tableau:

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

Merci d'avance, Opak

Réponse populaire

Vous pouvez obtenir le bon ordre en parcourant l'arborescence DOM à l'aide de l' API HTML DOM . Le code suivant fait ceci. Remarque, j'utilise dynamic pour accéder à l'API DOM. C'est parce que WebBrowser de HtmlElement.FirstChild / HtmlElement.NextSibling ne fonctionnent pas à cet effet, car ils renvoient null pour les nœuds de texte 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);
}

[MISE À JOUR] Si vous avez vraiment besoin d'obtenir une liste d'objets HtmlElement pour les balises <A> , au lieu d'éléments dynamic natifs, vous GetElementById utiliser un petit truc en utilisant 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

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow