HtmlAgilityPack HtmlWeb使用说明
HtmlAgilityPack 是一款非常不错的html dom parser,用c#语言编写。利用它将Internet上down下来的html页面进行规格化处理,让原本对语义支持并不好的html文档格式变为更严谨的Xhtml格式,甚至可以转换为xml格式;并使用xpath来选择、处理dom中的element。下面笔者把 HtmlAgilityPack 的一个htmlWeb类单独拿出来说明一下,这是个不错的httpwebrequest实例,对研究.Net平台 上 c#语言的同学会有一些启发。
一、获取 HtmlAgilityPack 源代码
我们可以使用NuGet Package 获取bin格式的dll文件,Html Agility Pack 项目是一个开源项目寄存在codeplex上,大家可以直接从下面的网址访问 http://htmlagilitypack.codeplex.com/ 并下载源代码。
如果不是学习的目的,而是直接应用,建议从NuGet Package上获得最新的dll文件,并在自己的项目中引用。
二、 中文乱码的问题受到的启发
HtmlAgilityPack固然好用,但对中文gbk编码的支持似乎并不好。我们在使用HtmlWeb类加载中文Uri时,如果Uri的编码是GB2312,那么就会出现乱码,解决的方法有两种可供选择。
HtmlWeb htw = new HtmlWeb();
htw.OverrideEncoding = Encoding.GetEncoding(“gb2312″);
htw.Load(“http://www.cnphp.info”, “GET”);
//使用htmlWeb类加载Uri时,设置.OverrideEncoding属性
htmlWeb类并不能很好识别gb2312编码的网页,似乎是对httpwebrequest的处理不当造成的;设置.OverrideEncoding属性后确实可以解决问题,但似乎不够好,因为对于大量处理html下载时,网页编码不可能只是gbk格式,如果是utf-8或big5,如此设置,反而会人为造成识别为乱码。我们查看下HtmlWeb类的源代码,找到如下:
bool html = IsHtmlContent(resp.ContentType);
- Encoding respenc = !string.IsNullOrEmpty(resp.ContentEncoding)
- ? Encoding.GetEncoding(resp.ContentEncoding)
- : null;
修改为:
System.Text.Encoding respenc;
if ((resp.ContentEncoding != null) && (resp.ContentEncoding.Length > 0))
{
respenc = System.Text.Encoding.GetEncoding(resp.ContentEncoding);
}
else if ((resp.CharacterSet != null) && (resp.CharacterSet.Length > 0))//根据Content-Type中获取的charset编码
{
if (string.Compare(resp.CharacterSet, “ISO-8859-1″, true, System.Globalization.CultureInfo.InvariantCulture) == 0)
respenc = System.Text.Encoding.GetEncoding(“GB2312″);
else
respenc = System.Text.Encoding.GetEncoding(resp.CharacterSet);
}
else
{
respenc = System.Text.Encoding.GetEncoding(“GB2312″);
}
如此,中文乱码问题可以解决。
三、 下载Gzip压缩网页出错
由于受到流量、网速的限制,网络上70%以上的页面都会使用gzip压缩的方式来传输,HtmlAgilityPack 中的HtmlWeb类碰到这类网页就会出错,原因是它没有对httpwebrequest的Accept-Encoding进行处理。HtmlWeb 中 PreRequestHandler,用来处理发送之前的httpwebrequest。在此修改即可。
hw.PreRequest += new HtmlWebHelper.PreRequestHandler(PreRequest);
bool PreRequest(HttpWebRequest request)
{
request.Headers[HttpRequestHeader.AcceptEncoding] = “gzip, deflate”;
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
request.CookieContainer = new CookieContainer();
return true;
}
处理完后,我们就可放心使用了^_^。