none
如何parse HTML中需要的資料出來 RRS feed

  • 問題

  • 想請問一下大家,假設有一段資料如下:

    <ul id="my_ul">
    	<li id="txtA">ValueA</li>
    	<li id="txtBB">ValueB1 <br> ValueB2 </li>
    	<li id="txt__CCC">ValueC1 & ValueC2</li>
    </ul>

    需求的步驟為:

    1. 先找出id為my_ul的ul tag
    2. 找出ul tag中的所有<li>的id屬性,以及該<li>裡面的值。

    說一下原本的作法,我原本的作法是用XDocument去parse這一段,然後取li的片段出來,透過Attribute跟Value去取id屬性和<li>裡面的值。

    但碰到了兩個問題:

    1. <li>裡面的值,可能有<br>這類沒有結尾的tag。
    2. <li>裡面的值,可能有&等不能被XDocument parse的符號。

    不曉得各位前輩有沒有建議的方式,來達成這樣的需求。


    若您的程式碼有SQL injection的問題,在修改完畢之前,我不願意給您任何解答。因為解決了您的程式問題,造成更大的系統漏洞問題,還不如讓程式壞掉。

    請參考:SQL injection簡介與解決方式

    常用資源參考:


    小弟的blog: In 91,wiki: my wiki

    2012年3月13日 上午 11:49

解答

  • 我也來一個,不過可讀性看來比不上Html Agility Pack

    string html = @"
    <ul id=""my_ul"">
    	<li id=""txtA"">ValueA</li>
    	<li id=""txtBB"">ValueB1 <br> ValueB2 </li>
    	<li id=""txt__CCC"">ValueC1 & ValueC2</li>
    </ul>";
    Match m = Regex.Match(
        html, 
        "<ul.*?id=\"my_ul\".*?>(.*?<li.*?id=\"(?<id>.+?)\".*?>(?<value>.+?)</li>)+.*?</ul>", 
        RegexOptions.Singleline | RegexOptions.IgnoreCase
    );
    
    for (int i = 0; i < m.Groups["id"].Captures.Count; i++) {
        string id = m.Groups["id"].Captures[i].Value;
        string value = m.Groups["value"].Captures[i].Value;
    }

    • 已標示為解答 91MVP 2012年3月13日 下午 04:28
    2012年3月13日 下午 04:21
  • 分享一下目前用第三方元件:Html Agility Pack 的解決方式

                HtmlDocument document = new HtmlDocument();
                document.LoadHtml("HTML區塊的內容");
                var ulElement = document.DocumentNode.SelectNodes("//ul[@id=\"my_ul\"]");
                foreach (var item in ulElement)
                {
                    var liElements = item.SelectNodes("li");
    
                    foreach (var li in liElements)
                    {
                        var id = li.Attributes["id"].Value;
                        var value = li.InnerHtml;
                        Console.WriteLine("id:{0}, content:{1}", id, value);
                    }
    
                }


    若您的程式碼有SQL injection的問題,在修改完畢之前,我不願意給您任何解答。因為解決了您的程式問題,造成更大的系統漏洞問題,還不如讓程式壞掉。

    請參考:SQL injection簡介與解決方式

    常用資源參考:


    小弟的blog: In 91,wiki: my wiki

    • 已標示為解答 91MVP 2012年3月13日 下午 02:00
    2012年3月13日 下午 12:17

所有回覆

  • 分享一下目前用第三方元件:Html Agility Pack 的解決方式

                HtmlDocument document = new HtmlDocument();
                document.LoadHtml("HTML區塊的內容");
                var ulElement = document.DocumentNode.SelectNodes("//ul[@id=\"my_ul\"]");
                foreach (var item in ulElement)
                {
                    var liElements = item.SelectNodes("li");
    
                    foreach (var li in liElements)
                    {
                        var id = li.Attributes["id"].Value;
                        var value = li.InnerHtml;
                        Console.WriteLine("id:{0}, content:{1}", id, value);
                    }
    
                }


    若您的程式碼有SQL injection的問題,在修改完畢之前,我不願意給您任何解答。因為解決了您的程式問題,造成更大的系統漏洞問題,還不如讓程式壞掉。

    請參考:SQL injection簡介與解決方式

    常用資源參考:


    小弟的blog: In 91,wiki: my wiki

    • 已標示為解答 91MVP 2012年3月13日 下午 02:00
    2012年3月13日 下午 12:17
  • 我也來一個,不過可讀性看來比不上Html Agility Pack

    string html = @"
    <ul id=""my_ul"">
    	<li id=""txtA"">ValueA</li>
    	<li id=""txtBB"">ValueB1 <br> ValueB2 </li>
    	<li id=""txt__CCC"">ValueC1 & ValueC2</li>
    </ul>";
    Match m = Regex.Match(
        html, 
        "<ul.*?id=\"my_ul\".*?>(.*?<li.*?id=\"(?<id>.+?)\".*?>(?<value>.+?)</li>)+.*?</ul>", 
        RegexOptions.Singleline | RegexOptions.IgnoreCase
    );
    
    for (int i = 0; i < m.Groups["id"].Captures.Count; i++) {
        string id = m.Groups["id"].Captures[i].Value;
        string value = m.Groups["value"].Captures[i].Value;
    }

    • 已標示為解答 91MVP 2012年3月13日 下午 04:28
    2012年3月13日 下午 04:21
  • 我也來一個,不過可讀性看來比不上Html Agility Pack

    string html = @"
    <ul id=""my_ul"">
    	<li id=""txtA"">ValueA</li>
    	<li id=""txtBB"">ValueB1 <br> ValueB2 </li>
    	<li id=""txt__CCC"">ValueC1 & ValueC2</li>
    </ul>";
    Match m = Regex.Match(
        html, 
        "<ul.*?id=\"my_ul\".*?>(.*?<li.*?id=\"(?<id>.+?)\".*?>(?<value>.+?)</li>)+.*?</ul>", 
        RegexOptions.Singleline | RegexOptions.IgnoreCase
    );
    
    for (int i = 0; i < m.Groups["id"].Captures.Count; i++) {
        string id = m.Groups["id"].Captures[i].Value;
        string value = m.Groups["value"].Captures[i].Value;
    }

    阿尼真的太威了,拜一下,拜一下...

    若您的程式碼有SQL injection的問題,在修改完畢之前,我不願意給您任何解答。因為解決了您的程式問題,造成更大的系統漏洞問題,還不如讓程式壞掉。

    請參考:SQL injection簡介與解決方式

    常用資源參考:


    小弟的blog: In 91,wiki: my wiki

    2012年3月13日 下午 04:29
  • 如果要顯示在網頁上的話,別忘了好朋友jQuery + Ajax

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1">
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script src="Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
        <script type="text/javascript">
            $(document).ready(init);
    
            function init() {
    
    
                var str = " <ul id=\"my_ul\"><li id=\"txtA\">ValueA</li><li id=\"txtBB\">ValueB1<br>ValueB2 </li><li id=\"txt__CCC\">ValueC1 & ValueC2</li></ul>";
                str += str;
                //假設str是用Ajax取得的字串
                
                /*用$("#my_ul")只會選到一個*/
                $(str).filter("ul#my_ul").each(function (i) {
    
                    $(this).children("li").each(function (j) {
    
                        var id = $(this).attr("id");
                        var value = $(this).html();
                        alert("id:" + id + ", content:" + value);
    
                    });
    
    
                });
    
            }
        </script>
    </head>
    <body>
         
    </body>
    </html>
    


    2012年3月15日 下午 04:12
  • 謝謝您的建議,但我的需求完全不是如此的方向囉。

    比較像是讀HTML範本檔來作parse,用來控制新頁面的layout跟content。

    而非單純client端的處理,或是單純的想讀出某些片段來呈現。


    若您的程式碼有SQL injection的問題,在修改完畢之前,我不願意給您任何解答。因為解決了您的程式問題,造成更大的系統漏洞問題,還不如讓程式壞掉。

    請參考:SQL injection簡介與解決方式

    常用資源參考:


    小弟的blog: In 91,wiki: my wiki

    2012年3月15日 下午 04:50