Logo

C#下解析html页面的几种方式

photo

2024年06月25日

写网页抓取应用的时候经常需要解析html页面,此时就需要html解析器。当然可以自己从零开始写一个全新的html parser,但是对于一般的网页分析,使用现成的解析器可能更好(可靠性、稳定性、性能)。

java平台下sourceforge上有一个开源的解析器,可以从这里下载:http://htmlparser.sourceforge.net。但是在dot net平台下一直没有很好的开源html解析器,因此通常dot net平台下一般有下面几种解析html网页的方式:

1、使用微软的mshtml com组件

这种大概在c++语言下用的最多,dot net下也可以使用,添加对mshtml com组件的引用。使用mshtml com的优势是可以运行网页里的java script脚本,有的网站做得很变态,网页的最终内容是通过网页的onload事件里的java script脚本实时生成的,网页文件里根本就没有所需要的正常内容;但是也有个缺点,在俺的实际使用中,发现用mshtml com会导致内存占用持续上升,直到所有物理内存耗光,dot net的垃圾回收机制看来没起作用

2、使用HtmlAgilityPack

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格式耗时间

4、自己写html解析器

这种方式就不详细说了,每个人的实现都不相同。

橙子主题打折出售

其实我不卖,主要是这里是放广告的,所以就放了一个
毕竟主题都没做完,卖了也是坑.

购买它
所有附件
该文章没有附件.
本文为原创文章,请注意保留出处!

留言板

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

热门文章

修复群晖Synology Drive client右键菜单缺失问题 本教程主要解决windows10右键菜单中没有SynologyDrive菜单的问题,整体思路是找到...修复群晖SynologyDriveclient右键菜单缺失问题 作者:Pastore Antonio
1980 浏览量
docker如何查看一个镜像内部的目录结构及其内部都有哪些文件 前言:有时候我们会在docker上下载一个镜像,或者是上传一个镜像到docker上,甚至有时候就是在...docker如何查看一个镜像内部的目录结构及其内部都有哪些文件 作者:Pastore Antonio
1922 浏览量
Adobe Acrobat Pro 激活 这里记录了一些AdobeAcrobat的激活教程和组件。浏览量:1,806 作者:Pastore Antonio
1649 浏览量
追寻日出,找回自己 为什么我要去追寻日出?其实我是一个很懒的人,每次都起不来,直到有一次我在租房中睡到了大天亮,阳光照...追寻日出,找回自己 作者:Pastore Antonio
1606 浏览量
Swagger2 接口多级分组方法 swagger无疑是Java开发的最佳伴侣,接口非常方便调试;当然也有用Postman,因人而异吧...Swagger2接口多级分组方法 作者:Pastore Antonio
1522 浏览量