杨中科 向HtmlAgilityPack道歉:解析HTML还是你好用

摘要:
去年写过一篇文章《解析HTML最好的类还是微软自己的》,回复中有朋友提到可以使用HtmlAgilityPack来进行HTML的解析。因此决定还是换用向HtmlAgilityPack实现。那么如何解决HtmlAgilityPack得到的InnerText中有残留的script、样式的问题呢,在google上搜索“HtmlAgilityPackscriptinnerText”找到了stackoverflow上的这篇文章《C#:HtmlAgilityPackextractinnertext》代码如下:foreachscript.Remove();foreachstyle.Remove();stringinnerText=doc.DocumentNode.InnerText;原来这样简单呀,就是把所有的script、style标签从dom树中去掉。经过这次使用HtmlAgilityPack得出结论:还是HtmlAgilityPack强大!!!

去年写过一篇文章《解析HTML最好的类还是微软自己的》,回复中有朋友提到可以使用HtmlAgilityPack来进行HTML的解析。当时只是匆匆的测试了一下,发现HtmlAgilityPack得到的InnerText中有很多的不干净的script、样式内容,就断定“不是很满意,解析DiscuzNT!论坛的帖子页面的时候有问题,没法正确得到Body.InnerText的内容,有很多残留html、js代码夹杂在其中,解析的不是很好。”

杨中科 向HtmlAgilityPack道歉:解析HTML还是你好用第1张

传智播客.net培训学院内部有一个工具是我开发的,其中的HTML解析部分就是我使用MSHTML完成的,但是今天发现这个软件一个Bug,是MSHTML的HTMLDocumentClass在多线程并发时候有时候会造成死锁。MSHTML是工作在UI线程中的(如果不把DesignMode设置为On,则HTML中的javascript会被执行就是证明),并不是一个干净的、独立的HTML解析组件,因此出现这样的问题很难调试。因此决定还是换用向HtmlAgilityPack实现。

那么如何解决HtmlAgilityPack得到的InnerText中有残留的script、样式的问题呢,在google上搜索“HtmlAgilityPack script innerText”找到了stackoverflow上的这篇文章《C#: HtmlAgilityPack extract inner text》

代码如下:

复制代码
foreach(var script in doc.DocumentNode.Descendants("script").ToArray())
script.Remove();
foreach(var style in doc.DocumentNode.Descendants("style").ToArray())
style.Remove();
string innerText = doc.DocumentNode.InnerText;
复制代码

原来这样简单呀,就是把所有的script、style标签从dom树中去掉(为了解决迭代器在工作时不能从集合中Remove元素的问题,使用ToArray()转换为数组再遍历)。

这样操作发现还是有残留的script:

<!--[if IE]>
<script language="JavaScript"> var objmain = document.getElementById("main"); function updatesize(){ var bodyw = window.document.body.offsetWidth; var w=(bodyw<=790?"790px":"100%"); objmain.style.width=w; } updatesize(); window.onresize = updatesize; </script>
<![endif]-->

仔细一看原来是带条件注释的script,因此用下面的方法去掉所有的注释节点:

代码如下:

复制代码
foreach(var script in doc.DocumentNode.Descendants("script").ToArray())
script.Remove();
foreach(var style in doc.DocumentNode.Descendants("style").ToArray())
style.Remove();
foreach (var comment in doc.DocumentNode.SelectNodes("//comment()").ToArray())
comment.Remove();//新增的代码
string innerText = doc.DocumentNode.InnerText;
复制代码

解释:HtmlAgilityPack是使用XPath语法,"//comment()"在XPath中表示“所有注释节点”,关于XPath的详细用法请参考XPath的资料。

其他可能有用的技术点:
1、获取网页title:doc.DocumentNode.SelectSingleNode("//title").InnerText;
解释:XPath中“//title”表示所有title节点。SelectSingleNode用于获取满足条件的唯一的节点。

2、获取所有的超链接:doc.DocumentNode.Descendants("a")

3、获取name为kw的input,也就是相当于getElementsByName():
var kwBox = doc.DocumentNode.SelectSingleNode("//input[@name='kw']");

解释:"//input[@name='kw']"也是XPath的语法,表示:name属性等于kw的input标签。

经过这次使用HtmlAgilityPack得出结论:还是HtmlAgilityPack强大!!!再见MSHTML!

免责声明:文章转载自《杨中科 向HtmlAgilityPack道歉:解析HTML还是你好用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇二、Nginx配置实例C#的post请求 捕获错误代码的内容下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Ajax请求中,contentType和dataType的区别

contentType: (默认: "application/x-www-form-urlencoded") 发送信息至服务器时内容编码类型。默认值适合大多数情况。如果你明确地传递了一个content-type给 $.ajax() 那么他必定会发送给服务器(即使没有数据要发送). 其他可选的类型有:form-data x-www-form-orlencod...

前端知识小总结2

(暂时撇开内容、样式、行为的分离) 一: 1-语义化及语义化标签 标签的语义化,是指在看到标签名的情况下基本能理解它所代表的含义,比较直观,便于浏览器的解析和阅读。 语义化的优点, (1)为了在没有css的情况下,页面也能呈现出很好地内容结构、代码结构(2)有利于用户体验(3)有利于SEO和搜索引擎建立良好的沟通。(4)方便其他设备解析以意义的方式来渲染网...

margin的深入理解

第一部分:margin--基础知识 要介绍margin的基础知识,我们不可回避地要谈到css盒子模型(Box Model),一般而言,css盒子模型是用来设计和布局的。它本质上是一个盒子,包括:外边距(margin)、边框(border)、内边距(padding)以及最中间的内容(content)。下图即为盒子模型(这里只谈W3C规范的标准盒模型,而不谈I...

HTML fieldset和legend标签

此标签是成对出现的,以<fieldset>开始,以</fieldset>结束 一个表单可以有多个<fieldset>,每对<fieldset>为一组,每组的内容描述可以使用<legend>说明 CSS实例:用fieldset、legend实现文字写在边线上的效果: 这是一个非常不错的效果,在...

潭州课堂25班:Ph201805201 爬虫基础 第六课 选择器 bs4 (课堂笔记)

HTML解析库BeautifulSoup4 BeautifulSoup 是一个可以从HTML或XML文件中提取数据的Python库,它的使用方式相对于正则来说更加的简单方便,常常能够节省我们大量的时间。 BeautifulSoup也是有官方中文文档的:https://www.crummy.com/software/BeautifulSoup/bs4/doc...

[转]Jsoup(一)Jsoup详解(官方)

原文地址:http://www.cnblogs.com/zhangyinhua/p/8037599.html 一、Jsoup概述 1.1、简介     jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,  可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。 1.2、J...