別在迷戀正則表達式解析html了,好嗎?


  近段時間在論壇上面興起了一股正則之風,不論做什么都喜歡用正則

  你在后台解析json格式字符串,必須要用正則,好吧,你可能不知道用JavaScriptSerializer類,

  你解析類似www.xxx.com?a=a1&b=b2&c=c3的querystring參數,必須用正則,好吧,你也可能不知道string.split方法

  你解析html你還必須用正則,好吧,這就真沒有必要了,因為在解析html用到正則的時候你很多時候就不得不用到平衡組,你很有可能卡在這里

  正則的強大性與通用性就不提了,一般的處理完全夠用了,你完全可以自己去“系統”的學習(注:系統學習正則),在配上RegexBuddy或者在線的正則(注:附注會提到內容)的工具就可以掌握一些常用的用法

  但是去解析html,還是用專業的庫去解析吧,雖然條條大路通羅馬,你真沒必要以鐵人三項的精神去做用正則死嗑html。

  其實解析html的庫有滿多不錯的,如HtmlAgilityPack又或者Jumony以及Java的解析庫htmlparser(有.net版的),下面列一個小例子:

   地址:http://feedback.ebay.com/ws/eBayISAPI.dll?ViewFeedback2&ftab=AllFeedback&userid=paragad&iid=-1&de=off&items=25&interval=0&mPg=151

  

    抓取評論區的:回復內容,購買人名字,購買時間

    引用:HtmlAgilityPack庫

    

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;

namespace AnaHtml
{
    class Program
    {
        static void Main(string[] args)
        {
            HtmlWeb html = new HtmlWeb();
            var content = from page in html.Load("http://feedback.ebay.com/ws/eBayISAPI.dll?ViewFeedback2&ftab=AllFeedback&userid=paragad&iid=-1&de=off&items=25&interval=0&mPg=151")
//Skip(1)排除標題行 where((x,index)=>index%2==0)選取相應的內容行 .DocumentNode.SelectSingleNode("//table[@class='FbOuterYukon']").Elements("tr").Skip(1).Where((x, index) => index % 2 == 0) let row = page where row != null select new { Content = row.ChildNodes[1].InnerText,
//注意,任何時候的SelectSingleNode方法都是以整個document為前提的,個人覺得應該當前的節點為前擔 Id =row.ChildNodes[2].SelectSingleNode(row.ChildNodes[2].XPath+"//div[1]//a[1]//span[1]").InnerHtml, Retime = row.ChildNodes[3].InnerText }; foreach (var item in content) { Console.WriteLine("\r\n Content:{0} Id={1} Time={2} ", item.Content, item.Id,item.Retime); } Console.Read(); } } }

  整個結構清晰自然,利用Xpath的來進行選取相當方便,輕易就可以抓取內容。

 

附注: 

一,正則相關

1.30分鍾搞定正則(了然正則的基礎知識點)

2.正則達人的博客

3.正則工具RegexBug

 

二,解析庫:

 XPath簡明介紹
 XPath 使用路徑表達式來選取 XML 文檔中的節點或節點集。節點是通過沿着路徑 (path) 或者步 (steps) 來選取的。
 下面列出了最有用的路徑表達式:
 nodename:選取此節點的所有子節點。 
 /:從根節點選取。 
 //:從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。 
 .:選取當前節點。 
 ..:選取當前節點的父節點。
 例如有下面一段XML:
 

<?xml version="1.0" encoding="utf-8"?> 

 <Articles> 

 <Article> 

   <Title>在ASP.NET中使用Highcharts js圖表</title> 

   <Url>http://zhoufoxcn.blog.51cto.com/792419/537324</Url> 

   <CreateAt type="en">2011-04-07</price> 

 </Article> 

 <Article> 

   <Title lang="eng">Log4Net使用詳解(續)</title> 

   <Url>http://blog.csdn.net/zhoufoxcn/archive/2010/11/23/6029021.aspx</Url> 

   <CreateAt type="zh-cn">2010年11月23日</price> 

 </Article> 

 <Article> 

   <Title>J2ME開發的一般步驟</title> 

   <Url>http://blog.csdn.net/zhoufoxcn/archive/2011/06/12/6540223.aspx</Url> 

   <CreateAt type="zh-cn">2011年06月12日</price> 

 </Article> 

 <Article> 

  1.    <Title lang="eng">PowerDesign高級應用</title> 
  2.    <Url>http://zhoufoxcn.blog.51cto.com/792419/166415</Url> 
  3.    <CreateAt type="zh-cn">2007-09-08</price> 
  4.  </Article> 
  5.  </Articles> 


  針對上面的XML文件,我們列出了帶有謂語的一些路徑表達式,以及表達式的結果:
 /Articles/Article[1]:選取屬於Articles子元素的第一個Article元素。 
 /Articles/Article[last()]:選取屬於Articles子元素的最后一個Article元素。 
 /Articles/Article[last()-1]:選取屬於Articles子元素的倒數第二個Article元素。 
 /Articles/Article[position()<3]:選取最前面的兩個屬於 bookstore 元素的子元素的Article元素。 
 //title[@lang]:選取所有擁有名為lang的屬性的title元素。 
 //CreateAt[@type='zh-cn']:選取所有CreateAt元素,且這些元素擁有值為zh-cn的type屬性。 
 /Articles/Article[Order>2]:選取Articles元素的所有Article元素,且其中的Order元素的值須大於2。 
 /Articles/Article[Order<3]/Title:選取Articles元素中的Article元素的所有Title元素,且其中的Order元素的值須小於3。
 
 HtmlAgilityPack API簡明介紹
 在HtmlAgilityPack中常用到的類有HtmlDocument、HtmlNodeCollection、
HtmlNode和HtmlWeb等。
 其流程一般是先獲取HTML,這個可以通過HtmlDocument的Load()或LoadHtml()來加載靜態內容,或者也可以HtmlWeb的Get()或Load()方法來加載網絡上的URL對應的HTML。
 得到了HtmlDocument的實例之后,就可以用HtmlDocument的DocumentNode屬性,這是整個HTML文檔的根節點,它本身也是一個HtmlNode,然后就可以利用HtmlNode的SelectNodes()方法返回多個HtmlNode的集合對象HtmlNodeCollection,也可以利用HtmlNode的SelectSingleNode()方法返回單個HtmlNode。

轉自=>周公博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM