原文:http://www.cnblogs.com/rupeng/archive/2012/02/07/2342012.html

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

传智播客.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还是你好用相关推荐

  1. 一级计算机电子表格试题,计算机一级考试电子表格题都是出什么样的题目或题型?以及幻灯片?【excel一级考试题目及解析】...

    急求计算机一级word,excel,ppt的考试操作题啊? 因为我在这方面已经考过,也有经验,我建议最好还是去买一个这个程序的光碟回家好好的学习练习几十遍后,一般是可以考的合格.如果不学习就很难说咯! ...

  2. 爬虫基础学习 转【http://www.cnblogs.com/huangxincheng/archive/2012/11/08/2759752.html】

    这一篇我们聊聊在页面抓取时应该注意到的几个问题. 一:网页更新 我们知道,一般网页中的信息是不断翻新的,这也要求我们定期的去抓这些新信息,但是这个"定期"该怎么理解,也就是多长时间 ...

  3. 从统计局抓取2016年最新的全国区县数据!!

    using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System. ...

  4. .NET Core 实现定时抓取博客园首页文章信息并发送到邮箱

    前言 大家好,我是晓晨.许久没有更新博客了,今天给大家带来一篇干货型文章,一个每隔5分钟抓取博客园首页文章信息并在第二天的上午9点发送到你的邮箱的小工具.比如我在2018年2月14日,9点来到公司我就 ...

  5. .net core 实现简单爬虫—抓取博客园的博文列表

    一.介绍一个Http请求框架HttpCode.Core HttpCode.Core 源自于HttpCode(传送门),不同的是 HttpCode.Core是基于.net standard 2.0实现的 ...

  6. ASP.NET Core 快速入门(实战篇)

    上篇讲了<asp.net core在linux上的环境部署>.今天我们将做几个小玩意实战一下.用到的技术和工具有mysql.websocket.AngleSharp(爬虫html解析).n ...

  7. 文章推荐列表(个人收藏)

    const限定修饰符用法总结 C/C++ cpper 0 3 2011-11-28 11:37 win32 c++编写系统服务程序 C/C++ cpper 0 2 2011-11-28 11:34 V ...

  8. Android Netty的使用-入门指南

    前言 很久没更新博客了,主要是 最近发生的事情太多了.开始学习~ Netty使用步骤 前言 简要 解码器介绍(需要了解的) 粘包/拆包 LineBasedFrameDecoder(行解码器) Deli ...

  9. .NET平台常见技术框架整理汇总

    使用.NET平台开发有段时间了,在网上资料的基础上做了进一步整理,汇集了.NET平台常见的技术框架. 参考资料: 基于.NET平台常用的框架整理 .NET开源框架列表 1.知识网络 2.分类清单 2. ...

最新文章

  1. 团队项目第一阶段冲刺站立会议1(4月18日)
  2. (第四篇)Vue生命周期
  3. bzoj1115: [POI2009]石子游戏Kam
  4. TagHelper是怎么实现的
  5. python编写自制编译器_编译器构造-编译Python
  6. linux中如何查看某个端口是否被占用,LINUX中如何查看某个端口是否被占用
  7. Python正则表达式指南上半部
  8. django自带调试服务器的使用
  9. 老李分享知识:性能测试之TPS和吞吐率
  10. python自学网站-自学Python网站推荐 从入门到精通
  11. mysql可靠性优先策略
  12. Flink作业问题分析和调优实践
  13. mock.js那点事(上)
  14. Atitit 朋友圈 微博 之道 朋友圈的dos and donts
  15. 解决ueditor编辑器图片在线管理图片无法显示
  16. SAP 开发者Access Key 与对象修改Access Key
  17. 显示器扩展后左右如何设置?
  18. (十三) Oracle函数
  19. Android学习笔记-传感器开发之利用传感器和Tween开发简易指南针
  20. echarts中国地图分七大区

热门文章

  1. vue-route动态路由
  2. ECMAScript6入门--Class对象
  3. centos6.7部署solr-6.3.0
  4. c/c++文件I/O函数学习--不断补充
  5. linux centos使用xrdp远程界面登陆
  6. Thread Dump 和Java应用诊断(转)
  7. Hubble.net 简介及与Lucene.net 对比测试
  8. Golang —— goroutine(协程)和channel(管道)
  9. JDK源码分析-Integer
  10. Linux虚拟化介绍