获取博客帖子的Html解析器

时间:2011-04-15 21:37:41

标签: c# .net blogs html-parsing

我需要创建一个html解析器,给定一个博客网址,它会返回一个列表,其中包含页面中的所有帖子。

  • 即。如果一个页面有10个帖子,那么 应该返回10个div的列表, 其中每个div包含 h1 p

我无法使用其rss Feed,因为我需要确切了解用户的样子,如果它有任何广告,图片等,相比之下,某些博客只有其内容的摘要和Feed这一切,反之亦然。

无论如何,我已经制作了一个下载其Feed,并在html中搜索类似内容的内容,它对某些博客非常有效,但对其他博客则无效。

我认为我不能创建一个适用于它解析的100%博客的解析器,但我想尽可能做到最好。

最佳方法应该是什么?查找id属性等于“post”,“content”的标签?寻找p标签?等等等......

提前感谢您的帮助!

4 个答案:

答案 0 :(得分:2)

我认为你不会在这方面取得成功。您可能能够解析一个博客,但如果博客引擎更改了内容,它将不再起作用。我也认为你不能写一个通用的解析器。你甚至可能部分成功,但这将是一个空灵的成功,因为在这种情况下一切都是如此容易出错。如果您需要内容,则应使用RSS。如果你需要存储(只是存储)它的外观,你也可以这样做。但按照它看起来的方式解析?我没有看到具体的成功。

答案 1 :(得分:1)

使用HTML Agility包。它是为此而制作的HTML解析器。

答案 2 :(得分:1)

“最好的可能”原来是“最合理的”,你可以定义什么是合理的。您可以通过查看常见的博客工具(WordPress,LiveJournal等)如何生成他们的页面以及专门针对每个博客的代码来获取大量博客。

一般情况是一个非常棘手的问题,因为每个博客工具都有自己的格式。您可以使用“标准”标识符(如“帖子”,“内容”等)来推断事物,但这是值得怀疑的。

您也会遇到广告问题。很多广告都是使用JavaScript生成的。因此,下载页面将只提供JavaScript代码而不是生成的HTML。如果您确实要识别广告,则必须确定生成广告的JavaScript代码。或者,您的程序必须执行JavaScript才能创建最终的DOM。然后你面临一个与上述类似的问题:弄清楚某些特定的HTML是否是一个广告。

有一些启发式方法有些成功。查看Identifying a Page's Primary Content以获取类似问题的答案。

答案 3 :(得分: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; }
    }
}
祝你好运, 埃里克