HtmlAgilityPack是一个开源的html解析器,底层是通过将html格式转成标准的xml格式文件来实现的(使用dot net里的XPathDocument等xml相关类),可以从这里下载:http://htmlagilitypack.codeplex.com。可以通过指定xpath路径提取需要的内容,上面那个网站也提供了一个自动生成xpath路径的工具HAP Explorer。缺点和上面使用mshtml com组件一样,内存占用非常大,会耗光所有物理内存。

3、使用SgmlReader

SgmlReader也是一个开源的解析器,可以从这里下载(微软自己网站上的那个不完整,缺少一些文件)。用这个工具先将html文件转成标准的xml格式文件,再通过制定xpath路径来提取所需要的内容(xpath路径可以通过上面的那个工具生成)。下面一个简单的示例代码:
XPathDocument pathDoc = null;
using (SgmlReader sgmlReader = new SgmlReader())
{
sgmlReader.DocType = "HTML";
sgmlReader.InputStream = new StringReader(html);
using (StringWriter stringWriter = new StringWriter())
{
using (XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter))
{
while (!sgmlReader.EOF)
{
xmlWriter.WriteNode(sgmlReader, true);
}
string xml = stringWriter.ToString().Replace("xmlns=\"http://www.w3.org/1999/xhtml\"", "");
pathDoc = new XPathDocument(new StringReader(xml));
}                    
}
}
//提取出整个table
string xpath = "//div[@class=\"infoList\"]/table";//xpath表达式
XPathNavigator nav = pathDoc.CreateNavigator();
XPathNodeIterator nodes = nav.Select(xpath);
if (!nodes.MoveNext())
{
return;
}
nodes = nodes.Current.Select("//tr");
if (!nodes.MoveNext()) return;
string str = "";
while (nodes.MoveNext())
{
//遍历所有行
XPathNodeIterator tdNode = nodes.Current.Select("./td");
while (tdNode.MoveNext())
{
//遍历列
str += tdNode.Current.Value.Trim() + " ";
}
str += "\r\n";  
}
//输出结果
Console.WriteLine(str);

如果要提取图片的src,xpath写成这样://div[@class=\"infoList\"]/img/@src

注意:

上面的这行 stringWriter.ToString().Replace("xmlns=\"http://www.w3.org/1999/xhtml\"", "");

使用SgmlReader转换后的html会在根元素<html>自动加上命名空间http://www.w3.org/1999/xhtml,变成这样:
<html xmlns="http://www.w3.org/1999/xhtml">

如果不把这个xmlns="http://www.w3.org/1999/xhtml"移走,那么

XPathNodeIterator nodes = nav.Select(xpath);

这条语句将取不出来内容,也即是nodes.MoveNext()的值将会是false,网上很多例子里都没有提到这点

例子中的html样本:
<html>
<head>
<title>示例Test</title>
</head>
<body>
<div id="a1" class="a1">
<div class="infoList" id="infoList">
<div class="clearit"></div>
<table cellspacing="0">
<tr>
<td>甲A</td>
<td class="td2">09-25 00:00</td>
</tr>
<tr>
<td>德乙</td>
<td class="td2">09-26 10:10</td>
</tr>
</table>
<img src="http://www.aaaa.com/images/b234.jpg" alt="图片1" title="图片1">
</div>
</div>
</doby>
</html>

使用SgmlReader的好处就是内存占用稳定,在俺实际使用中内存上下浮动不会超过20M(2个线程,间隔60秒抓取一个新页面,7*24小时不间断的后台服务程序)。不足就是html转成xml格式耗时间

最新文章

  1. ASP.NET MVC5+EF6+EasyUI 后台管理系统(81)-数据筛选(万能查询)
  2. 深入理解javascript原型和闭包(5)——instanceof
  3. 【iCore3双核心板】发布 iCore3 硬件手册!
  4. UML类图分析
  5. TM4C123G红外触摸屏:开发板好不容易实现了原理,放到专家设计的板子上无法运行,于是专家跑路项目黄了
  6. .net4缓存笔记
  7. Android调用Sqlite数据库时自动生成db-journal文件的原因
  8. Cron表达式说明
  9. 关于AfterLogic WebMail 的.net版无法上传控件的解决办法
  10. 折叠Collapse插件
  11. C++程序设计与语言(特别版) -- 导论
  12. HTML5编程之旅系列一:HTML5 Geolocation 初探
  13. Linux学习笔记之六————Linux常用命令之系统管理
  14. 9 Web开发——springmvc自动配置原理
  15. u-boot移植(五)---代码修改---时钟修改、SDRAM
  16. 转:&quot;为自动填充列调整大小期间不能执行此操作&quot;解决办法 .
  17. haproxy prometheus 监控docker-compose 运行试用
  18. LibreOJ 6281 数列分块入门5
  19. HDU 4081 Qin Shi Huang&amp;#39;s National Road System(最小生成树/次小生成树)
  20. 每天五个java相关面试题(7)--线程篇

热门文章

  1. Maven学习——安装与修改Maven的本地仓库路径
  2. IOS内存警告处理
  3. 烂泥:LVM学习之逻辑卷LV及卷组扩容VG
  4. 用SecureCRT在windows和CentOS间上传下载文件
  5. oracle 11g dataguard创建的简单方法
  6. log4j日志优先级导致的不输出日志
  7. Armstrong数
  8. cri-o 与 cni的集成分析
  9. 怎样用ZBrush中的Curves和Insert笔刷创建四肢
  10. web前端笔试题总结