Obtención de InnerText ignorando el nodo de script utilizando Html Agility Pack en C #

c# html-agility-pack html-parsing

Pregunta

Tengo la siguiente página de la que quiero obtener una lista de servidores proxy de una tabla:

http://proxy-list.org/spanish/search.php?search=&country=any&type=any&port=any&ssl=any

Cada fila en la tabla es un elemento ul. Mi problema es cuando obtengo el primer elemento li cuya clase asociada es "proxy" del elemento ul. Quiero obtener la IP y el puerto, así que realizo un texto interno, pero como el elemento li tiene un nodo secundario de script, devuelve el texto del nodo de script.

Abajo una imagen de la estructura de la página:

introduzca la descripción de la imagen aquí

He intentado a continuación el código usando Html Agility Pack y LINQ:

WebClient webClient = new WebClient();
string page = webClient.DownloadString("http://proxy-list.org/spanish/search.php?search=&country=any&type=any&port=any&ssl=any");

HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(page);

List<List<string>> table = doc.DocumentNode.SelectSingleNode("//div[@class='table']")
            .Descendants("ul")
            .Where(ul => ul.Elements("li").Count() > 1)
            .Select(ul => ul.Elements("li").Select(li =>
                {
                    string result = string.Empty;
                    if (li.HasClass("proxy"))
                    {
                        HtmlNode liTmp = li.Clone();
                        liTmp.RemoveAllChildren();
                        result = liTmp.InnerText.Trim();
                    }
                    else
                    {
                        result = li.InnerText.Trim();
                    }
                    return result;
                }).ToList()).ToList();

Puedo obtener una lista en la que cada elemento es una lista que contiene los campos (Proxy, País, Tipo, Velocidad, HTTPS / SSL) pero el campo proxy está siempre vacío. Tampoco estoy llegando a todas las columnas "País" y "Ciudad".

Respuesta aceptada

Esto se debe a que esos valores se inyectan en el DOM mediante JavaScript después de cargar la página. En realidad, el valor dentro del Proxy() es una representación de Base64 de lo que está buscando.

En la imagen que ha publicado sobre el valor MTQ4LjI0My4zNy4xMDE6NTMyODE= decodifica a 148.243.37.101:53281

La cadena analizada sin procesar que está alimentando al paquete Agility solo contiene el campo Proxy ...

    <div class=\ "table-wrap\">\r\n
        <div class=\ "table\">\r\n
            <ul>\r\n
                <li class=\ "proxy\">
                    <script type=\ "text/javascript\">
                        Proxy('MTM4Ljk3LjkyLjI0OTo1MzgxNg==')
                    </script>
                </li>\r\n
                <li class=\ "https\">HTTP</li>\r\n
                <li class=\ "speed\">29.5kbit</li>\r\n
                <li class=\ "type\">
                    <strong>Elite</strong>
                </li>\r\n
                <li class=\ "country-city\">\r\n
                    <div>\r\n
                        <span class=\ "country\" title=\ "Brazil\">
                            <span class=\ "country-code\">
                                <span class=\ "flag br\"></span>
                                <span class=\ "name\">BR Brasil</span>
                            </span>
                        </span>
                        <!--\r\n                     -->
                        <span class=\ "city\">
                            <span>Rondon</span>
                        </span>\r\n </div>\r\n </li>\r\n </ul>\r\n
            <div class=\ "clear\"></div>\r\n

Utilizando el siguiente código:

        HttpClient client = new HttpClient();
        var docResult = client.GetStringAsync("http://proxy-list.org/spanish/search.php?search=&country=any&type=any&port=any&ssl=any").Result;
        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(docResult);
        Regex reg = new Regex(@"Proxy\('(?<value>.*?)'\)", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        var stuff = doc.DocumentNode.SelectSingleNode("//div[@class='table']")
        .Descendants("li")
        .Where(x => x.HasClass("proxy"))
        .Select(li =>
        {
            return li.InnerText;
        }).ToList();

        foreach (var item in stuff)
        {
            var match = reg.Match(item);
            var proxy = Encoding.Default.GetString(System.Convert.FromBase64String(match.Groups["value"].Value));
            Console.WriteLine($"{item}\t\tproxy = {proxy}");
        }

Yo obtengo: introduzca la descripción de la imagen aquí



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é