Obtener enlaces de un documento html en orden

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

Pregunta

Quiero obtener todos los enlaces de un documento HTML. Esto no es un problema, pero aparentemente pone todos los enlaces en orden alfabético antes de almacenarlos uno por uno. Quiero tener los enlaces en orden original (no en orden alfabético).

Entonces, ¿hay alguna posibilidad de obtener el primer enlace encontrado, almacenarlo, luego el segundo, ...? Ya intenté usar HtmlAgilityPack y los métodos de control del navegador web, pero ambos los ordenan alfabéticamente. El pedido original es importante para fines posteriores.

Escuché que podría ser posible con Regex, pero he encontrado suficientes respuestas, donde dicen que no se debe usar para el análisis de HTML. Entonces, ¿cómo puedo hacerlo?

Aquí está el código de control del navegador web, que intenté usar para obtener los enlaces y almacenarlos en una matriz:

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

Gracias de antemano, Opak

Respuesta popular

Puede obtener el orden correcto recorriendo el árbol DOM usando API DOM de HTML . El siguiente código hace esto. Tenga en cuenta, yo uso dynamic para acceder a la API DOM. Esto se debe a WebBrowser 's HtmlElement.FirstChild / HtmlElement.NextSibling no funcionan para este fin, ya que regresan null para los nodos de texto 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);
}

[ACTUALIZACIÓN] Si realmente necesita obtener una lista de objetos HtmlElement para etiquetas <A> , en lugar de elementos nativos dynamic , todavía es posible con un pequeño truco 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);
}


Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué