C #에서 Html Agility Pack을 사용하여 InnerText를 스크립트 노드 무시하기

c# html-agility-pack html-parsing

문제

다음 테이블에서 프록시 서버 목록을 얻고 싶습니다.

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

테이블의 각 행은 ul 요소입니다. 내 문제는 관련 클래스가 ul 요소에서 "프록시"인 첫 번째 li 요소를 얻을 때입니다. InnerText를 수행 할 수 있도록 IP와 Port를 얻고 싶지만 li 요소에 스크립트 자식 노드가 있으면 스크립트 노드의 텍스트를 반환합니다.

페이지 구조의 이미지 아래 :

여기에 이미지 설명을 입력하십시오.

나는 HTML Agility Pack과 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();

나는 각 항목이 필드 (Proxy, Paes, Tipo, Velocidad, HTTPS / SSL)를 포함하는 목록 인 목록을 얻을 수 있지만 필드 프록시는 항상 비어 있습니다. 또한 저는 "País"와 "Ciudad"란을 전혀 얻지 못하고 있습니다.

수락 된 답변

이러한 값은 페이지로드 후 JavaScript에 의해 DOM에 주입되기 때문입니다. 실제로 Proxy() 내부의 값은 찾고있는 Base64 표현입니다.

이미지에서 MTQ4LjI0My4zNy4xMDE6NTMyODE= 값으로 게시 148.243.37.101:53281

Agility 팩에 입력하는 원시 구문 분석 문자열에는 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

다음 코드를 사용하여 :

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

나는 얻다: 여기에 이미지 설명을 입력하십시오.



Related

아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow