1

我收到一个非常不规则的 HTML 文件。

<tr class="" rel="30887721">
    <td class="leftborder timestamp" rel="1472298782"> 
        <span class="updatets "> 9mins </span> 
    </td> 
    <td> 
        <span>
            <style>
                .NFK2{display:none}
                .gPwA{display:inline}
                .Zb70{display:none}
                .vFY2{display:inline}
            </style>
            <span style="display:none">54</span>
            <span class="NFK2">54</span>
            <div style="display:none">54</div>
            <span class="vFY2">124</span>
            <span style="display: inline">.</span>
            <span class="7">240</span>
            <span class="235">.</span>
            <div style="display:none">17</div>
            <span class="NFK2">62</span>
            <span></span>
            <span style="display:none">121</span>
            <span></span>
            <span style="display: inline">187</span>
            <span style="display:none">190</span>
            <span class="Zb70">190</span>
            <span class="NFK2">197</span>
            <span></span>
            <span style="display: inline">.</span>
            <span class="248">80</span>
            <div style="display:none">152</div>
            <span style="display:none">166</span>
            <div style="display:none">166</div>
        </span>
    </td> 
    <td> 80 </td> 
    <td style="text-align:left" class="country" rel="cn"> 
        <span style="white-space:nowrap;"> 
            <img src="/images/1x1.png" style="width: 16px; height: 11px; margin-right: 5px;" class="flags-cn" alt="flag "/> 
            China 
        </span> 
    </td> 
    <td> 
        <div class="progress-indicator response_time" style="width: 114px" value="1314" levels="speed" rel="1314"> 
            <div class="indicator" style="width: 87%; background-color: rgb(0, 173, 173)"></div> 
        </div> 
    </td> 
    <td> 
        <div class="progress-indicator connection_time" style="width: 114px" title="" rel="427" value="427" levels="speed"> 
            <div class="indicator" style="width: 91%; background-color: rgb(0, 173, 173)"></div> 
        </div> 
    </td> 
    <td> HTTP </td> 
    <td nowrap> High +KA </td>
</tr>
<tr class="altshade" rel="30887719"> 
    <td class="leftborder timestamp" rel="1472298723"> 
        <span class="updatets "> 10mins </span> 
    </td> 
    <td> 
        <span> 
            <style>
                .ZQOg{display:none}
                .hAKN{display:inline}
                .sZYH{display:none}
                .euLE{display:inline}
                .pnDV{display:none}
                .yf2r{display:inline}
            </style>
            <span style="display:none">30</span>
            <div style="display:none">30</div>
            <span class="yf2r">124</span>
            <span style="display: inline">.</span>
            <span style="display:none">62</span>
            <span style="display: inline">244</span>
            <span style="display: inline">.</span>
            <span class="pnDV">6</span>
            <div style="display:none">6</div>
            <span class="ZQOg">39</span>
            <div style="display:none">39</div>
            <span style="display:none">71</span>
            <div style="display:none">71</div>
            <span style="display:none">103</span>
            <span class="sZYH">103</span>
            <span></span>
            <span class="euLE">157</span>
            <span style="display:none">188</span>
            <div style="display:none">188</div>
            <div style="display:none">208</div>
            <span style="display:none">220</span>
            <div style="display:none">220</div>
            <span class="sZYH">231</span>
            <span style="display:none">241</span>
            <span class="hAKN">.</span>
            <span class="sZYH">26</span>
            <span></span>
            <span class="sZYH">31</span>
            <span></span>
            <span style="display:none">66</span>
            <div style="display:none">66</div>
            <span style="display:none">84</span>
            <span class="pnDV">84</span>
            <span></span>
            <span style="display:none">166</span>
            <span class="sZYH">166</span>
            <div style="display:none">166</div>
            <span style="display:none">207</span>
            <span></span>
            <span style="display: inline">209</span>
            <span class="sZYH">212</span>
            <div style="display:none">212</div>
            <span style="display:none">241</span>
            <span class="pnDV">241</span> 
        </span> 
    </td> 
    <td> 80 </td> 
    <td style="text-align:left" class="country" rel="hk"> 
        <span style="white-space:nowrap;"> 
            <img src="/images/1x1.png" style="width: 16px; height: 11px; margin-right: 5px;" class="flags-hk" alt="flag "/> 
            Hong Kong 
        </span> 
    </td> 
    <td> 
        <div class="progress-indicator response_time" style="width: 114px" value="1165" levels="speed" rel="1165"> 
            <div class="indicator" style="width: 88%; background-color: rgb(0, 173, 173)"></div> 
        </div> 
    </td> 
    <td> 
        <div class="progress-indicator connection_time" style="width: 114px" title="" rel="287" value="287" levels="speed"> 
            <div class="indicator" style="width: 94%; background-color: rgb(0, 173, 173)"></div> 
        </div> 
    </td> 
    <td> HTTP </td> 
    <td nowrap> High +KA </td>
</tr>

我需要提取该文件 TD 中的每个文本,结果应该是这样的:

9mins    124.240.187.80    80    China        HTTP    High +KA
10mins   124.244.157.209   80    Hong Kong    HTTP    High +KA

为了得到这个结果,我面临很多问题。
第一个是因为无效的标记,比如跨度内跨度,跨度内跨度,等等......
第二个是因为它需要一些实时解析,以评估其中的<style>标签。

Style 标签和 Style 属性说明了哪些元素应该出现,哪些不应该出现。

我正在使用 C# + CsQuery 来提取这个结果,但是,直到现在,还没有成功。

CQ dom = CQ.Create(text);
CQ tr = dom.Select("table tr");
foreach(var item in tr)
{
    string lastCheck = tr.Select("td:eq(0)").Text(); //9mins
    string ip = tr.Select("td:eq(1)").Text();
    string port = tr.Select("td:eq(2)").Text(); //80
    string country = tr.Select("td:eq(3)").Text(); //China
    string protocol = tr.Select("td:eq(6)").Text(); //HTTP
    string anonymity = tr.Select("td:eq(7)").Text(); //High + KA
}

IP var 返回如下内容:

".Yj0s{display:none}\n.YSE7{display:inline}\n.zURn{display:none}\n.odWZ{display:inline}637891919292106106137183183183188245245254.85135.166.117177214214225"

如果我更改 IP var 以获取 HTML:

string ip = tr.Select("td:eq(1)").Html();

它返回如下内容:

" <span> <style>.PLBz{display:none}\n.hjVo{display:inline}</style><span class=\"PLBz\">92</span><div style=\"display:none\">92</div><span style=\"display:none\">114</span><span class=\"PLBz\">114</span><div style=\"display:none\">114</div><span class=\"hjVo\">122</span><span class=\"PLBz\">240</span><div style=\"display:none\">240</div>.96<span style=\"display:none\">175</span><span class=\"PLBz\">175</span><div style=\"display:none\">191</div><span style=\"display:none\">229</span><span class=\"PLBz\">229</span><div style=\"display:none\">229</div><span style=\"display:none\">241</span><span></span><span class=\"80\">.</span><div style=\"display:none\">22</div><span style=\"display:none\">38</span><div style=\"display:none\">38</div><span class=\"hjVo\">59</span><span class=\"PLBz\">156</span><div style=\"display:none\">156</div>.<span style=\"display:none\">18</span><span class=\"PLBz\">18</span><div style=\"display:none\">18</div><span class=\"PLBz\">45</span><div style=\"display:none\">45</div>104<span class=\"PLBz\">145</span><span></span><span style=\"display:none\">150</span><span class=\"PLBz\">150</span><div style=\"display:none\">150</div><span style=\"display:none\">178</span><div style=\"display:none\">178</div><span></span><span class=\"PLBz\">252</span><div style=\"display:none\">252</div> </span> "

如何让 IP 显示正确的值?

4

1 回答 1

1

我认为您需要在这里做几件事:

  • 从 DOM 中删除任何带有style="display:none". 这可以在 CsQuery 中相当容易地完成:

    dom.Select("*:hidden").Remove();
    
  • 解析元素的内容<style>并移除由于元素内的声明而未显示的<style>元素。与其使用正则表达式来做到这一点,不如让我们正确地做事。让我们使用ExCSS来解析 CSS。这是一个采用 CsQuery 选择器的方法,使用 ExCSS 解析所有<style>元素并删除样式设置的所有元素display: none

        void RemoveElementsHiddenByStyles(CQ selector)
        {
            var parser = new Parser();
            foreach (IDomElement style in selector.Select("style"))
            {
                StyleSheet stylesheet = parser.Parse(style.InnerText);
                foreach (StyleRule styleRule in stylesheet.StyleRules)
                {
                    if (styleRule.Declarations.Any(d => d.Name == "display" && d.Term.ToString() == "none"))
                    {
                        selector.Select(styleRule.Selector.ToString()).Remove();
                    }
                }
            }
        }
    

    一旦<style>解析了每个元素的内容,就可以将其删除。

    请注意逐行执行此操作,以防一行中的样式声明与另一行中的样式声明冲突。

  • 从结果元素文本中删除所有空格。我会留给你写一个合适的RemoveAllWhitespace方法。 这个答案可能会有所帮助。

综上所述,我们有以下几点:

        CQ dom = CQ.Create(text);
        dom.Select("*:hidden").Remove();
        CQ rows = dom.Select("table tr");
        foreach (var item in rows)
        {
            CQ row = CQ.Create(item);
            RemoveElementsHiddenByStyles(row);
            row.Select("style").Remove();
            string lastCheck = row.Select("td:eq(0)").Text().Trim(); //9mins
            string ip = RemoveAllWhitespace(row.Select("td:eq(1)").Text()); //124.240.187.80
            string port = row.Select("td:eq(2)").Text().Trim(); //80
            string country = row.Select("td:eq(3)").Text().Trim(); //China
            string protocol = row.Select("td:eq(6)").Text().Trim(); //HTTP
            string anonymity = row.Select("td:eq(7)").Text().Trim(); //High + KA
        }

另请注意,我已避免将其tr用作变量名:在您的代码tr中包含所有行的列表,但在循环的主体中,它看起来好像您将它用于单个行。

于 2016-08-28T11:43:50.437 回答