2011-04-15 84 views
1

我需要創建一個html解析器,它給出一個博客URL,它返回一個列表,幷包含頁面中的所有帖子。Html解析器獲取博客文章

  • I.e.如果網頁上有10個職位,它 應該返回的10個div的, 其中每個div包含H1和 一個p

我不能使用其RSS提要的列表,因爲我需要知道用戶的具體情況,如果它有任何廣告,圖片等,相比之下,一些博客只是對其內容進行了總結,而Feed卻有它,反之亦然。

無論如何,我已經做了一個下載它的源,並搜索HTML類似的內容,它對一些博客非常好,但對其他人不適用。

我不認爲我可以製作解析器,它可以解析所有博客的100%,但我希望儘可能做到最好。

什麼應該是最好的方法?查找ID爲「post」,「content」的標籤?尋找p標籤?等等等等等......

在此先感謝您的幫助!

回答

1

「儘可能好」最終證明是「最合理的」,並且您可以定義什麼是合理的。您可以通過查看常見博客工具(WordPress,LiveJournal等)如何生成其頁面以及爲每個博客專門編碼來獲得大量博客。

因爲每個博客工具都有自己的格式,所以一般情況下是一個非常棘手的問題。您可以使用「標準」標識符(如「發佈」,「內容」等)來推斷事物,但這是值得懷疑的。

您也會遇到廣告困難。很多廣告都是用JavaScript生成的。所以下載頁面只會給你JavaScript代碼而不是生成的HTML。如果您確實想要識別廣告,則必須標識生成它們的JavaScript代碼。或者,您的程序將不得不執行JavaScript來創建最終的DOM。然後你遇到類似於上面的問題:弄清楚某些特定的HTML是否是廣告。

有些啓發式方法有些成功。查看Identifying a Page's Primary Content以獲取類似問題的答案。

2

我不認爲你會成功的。您可能能夠解析一個博客,但是如果博客引擎改變了內容,它將不再起作用。我也不認爲你可以編寫一個通用的解析器。你甚至可能會取得部分成功,但這將會是一個空靈的成功,因爲在這種情況下,一切都很容易出錯。如果你需要內容,你應該使用RSS。如果你需要存儲(簡單地存儲)它的外觀,你也可以做到這一點。但從它看起來的方式解析?我沒有看到具體的成功。

1

使用HTML Agility包。這是一個爲此製作的HTML解析器。

+0

HTML敏捷包只解析HTML。它無助於確定哪些部分是主要內容,哪些部分是廣告或典型樣板。 – 2011-04-15 21:52:14

+0

我正在使用它與當前的解析器=) – Bruno 2011-04-15 21:54:14

0

我剛剛爲我們公司的博客使用wordpress做了這樣的事情。這對我們很有好處,因爲我們的wordress博客多年來一直沒有改變,但其他人的看法是正確的,如果你的html改變很多,解析就成爲一個麻煩的解決方案。

這裏是我的建議:

使用的NuGet安裝RestSharp和HtmlAgilityPack。然後下載fizzler並在您的項目中包含這些引用(http://code.google.com/p/fizzler/downloads/list)。

以下是我用於在我的網站上實現博客搜索的一些示例代碼。

using System; 
using System.Collections.Generic; 
using Fizzler.Systems.HtmlAgilityPack; 
using RestSharp; 
using RestSharp.Contrib; 

namespace BlogSearch 
{ 
    public class BlogSearcher 
    { 
     const string Site = "http://yourblog.com"; 

     public static List<SearchResult> Get(string searchTerms, int count=10) 
     {    
      var searchResults = new List<SearchResult>(); 

      var client = new RestSharp.RestClient(Site); 
      //note 10 is the page size for the search results 
      var pages = (int)Math.Ceiling((double)count/10); 

      for (int page = 1; page <= pages; page++) 
      { 
       var request = new RestSharp.RestRequest 
            { 
             Method = Method.GET, 
             //the part after .com/ 
             Resource = "page/" + page 
            }; 

       //Your search params here 
       request.AddParameter("s", HttpUtility.UrlEncode(searchTerms)); 

       var res = client.Execute(request); 

       searchResults.AddRange(ParseHtml(res.Content)); 
      } 

      return searchResults; 
     } 

     public static List<SearchResult> ParseHtml(string html) 
     {    
      var doc = new HtmlAgilityPack.HtmlDocument(); 
      doc.LoadHtml(html); 
      var results = doc.DocumentNode.QuerySelectorAll("#content-main > div"); 

      var searchResults = new List<SearchResult>(); 
      foreach(var node in results) 
      { 
       bool add = false; 
       var sr = new SearchResult(); 

       var a = node.QuerySelector(".posttitle > h2 > a"); 
       if (a != null) 
       { 
        add = true; 
        sr.Title = a.InnerText; 
        sr.Link = a.Attributes["href"].Value; 
       } 

       var p = node.QuerySelector(".entry > p"); 
       if (p != null) 
       { 
        add = true; 
        sr.Exceprt = p.InnerText; 
       } 

       if(add) 
        searchResults.Add(sr); 
      } 

      return searchResults; 
     } 


    } 

    public class SearchResult 
    { 
     public string Title { get; set; } 
     public string Link { get; set; } 
     public string Exceprt { get; set; } 
    } 
} 

祝你好運, 埃裏克