一 本系列随笔概览及产生的背景

本系列开篇受到大家的热烈欢迎,这对博主是莫大的鼓励,此为本系列第二篇,希望大家继续支持,为我继续写作提供动力。

自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受广大博客写作和阅读爱好者的喜爱。同时也不乏一些技术爱好者咨询我,这个软件里面各种实用的功能是如何实现的。

该软件使用.NET技术开发,为回馈社区,现将该软件中用到的核心技术,开辟一个专栏,写一个系列文章,以飨广大技术爱好者。

本系列文章除了讲解网络采编发用到的各种重要技术之外,也提供了不少问题的解决思路和界面开发的编程经验,非常适合.NET开发的初级,中级读者,希望大家多多支持。

很多初学者常有此类困惑,“为什么我书也看了,C#相关的各个方面的知识都有所了解,但就是没法写出一个像样的应用呢?”,

这其实还是没有学会综合运用所学知识,锻炼出编程思维,建立起学习兴趣,我想该系列文章也许会帮到您,但愿如此。

开发环境:VS2008

本节源码位置:https://github.com/songboriceboy/GetWebContent

源码下载办法:安装SVN客户端(本文最后提供下载地址),然后checkout以下的地址:https://github.com/songboriceboy/GetWebContent

系列文章提纲如下:

二 第二节主要内容简介(如何使用C#语言获得任意站点博文的正文及标题)

使用C#语言获得任意站点博文的正文及标题的解决方案演示demo如下图所示:可执行文件下载

三 基本原理

要想获取任意网页文章的正文及标题,我们除了要利用上一节提到的HtmlAgilityPack.dll程序集之外,还要借助于另外一个实用的程序集Fizzler.dll(http://fizzlerex.codeplex.com/)

HtmlAgilityPack是通过xpath来解析html元素,相对来说还是稍微麻烦些;Fizzler提供了类似css选择器的方式来解析html元素,非常符合我们的习惯。

通常对于某篇文章,我们只想保留文章的正文(去掉广告,侧边栏等四周的网页布局元素),接下来,我们就来看一下操作步骤,这里我们需要借助一下强大的浏览器工具。

1.使用firefox浏览器或chrome浏览器打开我们想要提取正文的网页,firefox要安装firebug插件,chrome直接按F12,这里我们以firefox举例:

比如,打开我们上一节的博文(http://www.cnblogs.com/ice-river/p/4110799.html),如下图所示:

首先右上角的小虫子图标在我们安装完firebug插件后出现,点击它,浏览器下端弹出调试界面,在调试界面中,点击我红线框起来的图标(一蓝色方框,上面有个箭头),此时你会发现网页中的各个元素都变为可框选的,我们框选正文之后,会发现在下面的调试界面对应的div元素被高亮选中,我们对该div元素(博客园这里是div#cnblogs_post_body)右键,弹出右键菜单,如下图所示:

我们点击[复制css路径菜单项],此时我们粘贴板中就得到了正文的css路径[html body div#home div#main div#mainContent div.forFlow div#topics div.post div.postBody div#cnblogs_post_body]

对于Fizzler来说,我们只需要提供最后部分的div#cnblogs_post_body即可(大家记住,我们只需要从获得的css路径长字符串中从后往前看,拿到最后一个空格之后的字符串,这里是div#cnblogs_post_body

把这个字符串填入到我们demo的[正文css路径]部分,如下图所示:

其实对应于Fizzler来讲,只需一行代码:

  1. IEnumerable<HtmlNode> NodesMainContent = htmlDoc.DocumentNode.QuerySelectorAll(this.textBoxCssPath.Text);

是不是很简单?

对于其他技术博客,大家可以自行练习,检验是否理解了我上面所说的方法,这里给出几个常见技术博客的正文Css路径答案:

  1. 站点 ---> CSS路径
  2. "Cnblogs" ---> "div#cnblogs_post_body"
  3. "Csdn" ---> "div#article_content.article_content"
  4. "51CTO" ---> "div.showContent"
  5. "Iteye" ---> "div#blog_content.blog_content"
  6. "ItPub" ---> "div.Blog_wz1"
  7. "ChinaUnix" ---> "div.Blog_wz1"

好了,回过头来我们讲讲本节demo中的重点代码:

获取博客正文标题:

  1. private void GetTitle()
  2. {
  3. string strContent
  4. = m_wd.GetPageByHttpWebRequest(this.textBoxUrl.Text, Encoding.UTF8);
  5. HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument
  6. {
  7. OptionAddDebuggingAttributes = false,
  8. OptionAutoCloseOnEnd = true,
  9. OptionFixNestedTags = true,
  10. OptionReadEncoding = true
  11. };
  12.  
  13. htmlDoc.LoadHtml(strContent);
  14. string strTitle = "";
  15. HtmlNodeCollection nodes = htmlDoc.DocumentNode.SelectNodes("//title");
  16. // Extract Title
  17. if (!Equals(nodes, null))
  18. {
  19. strTitle = string.Join(";", nodes.
  20. Select(n => n.InnerText).
  21. ToArray()).Trim();
  22. }
  23. strTitle = strTitle.Replace("博客园", "");
  24. strTitle = Regex.Replace(strTitle, @"[|/\;:*?<>&#-]", "").ToString();
  25. strTitle = Regex.Replace(strTitle, "[\"]", "").ToString();
  26. this.textBoxTitle.Text = strTitle.TrimEnd();
  27. }

主要流程是首先用我们上一节给出的 WebDownloader类获取到网页的源代码,然后通过下面一行代码获取网页标题:

  1. HtmlNodeCollection nodes = htmlDoc.DocumentNode.SelectNodes("//title");

这里的借助了HtmlAgilityPack的SelectNodes函数提取网页中的title元素,注意一般的格式良好网页都具有title元素,因为这样方便搜索引擎索引收录我们的文章,下图解释下什么是title元素

大家注意上图,我用红笔圈出的2个地方,应该不言自明了吧,不解释。

获取博客正文内容:

  1. private void GetMainContent()
  2. {
  3. string strContent
  4. = m_wd.GetPageByHttpWebRequest(this.textBoxUrl.Text, Encoding.UTF8);
  5. HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument
  6. {
  7. OptionAddDebuggingAttributes = false,
  8. OptionAutoCloseOnEnd = true,
  9. OptionFixNestedTags = true,
  10. OptionReadEncoding = true
  11. };
  12.  
  13. htmlDoc.LoadHtml(strContent);
  14.  
  15. IEnumerable<HtmlNode> NodesMainContent = htmlDoc.DocumentNode.QuerySelectorAll(this.textBoxCssPath.Text);
  16.  
  17. if (NodesMainContent.Count() > )
  18. {
  19. this.richTextBox1.Text = NodesMainContent.ToArray()[].OuterHtml;
  20. this.webBrowser1.DocumentText = this.richTextBox1.Text;
  21. }
  22. }

很简单就是调用htmlDoc.DocumentNode.QuerySelectorAll函数,参数传入我们上面讲到的正文div的css路径,最后NodesMainContent.ToArray()[0].OuterHtml中保存的就是网页正文内容的源代码,放到richTextBox1.Text里显示html源代码,放到webBrowser1.DocumentText里显示网页内容。

四 下节预告

网页的抓取主要分为3步:

1.通过分页链接抓取到全部文章链接集合(第一节内容)

2.通过每一个文章链接获取到文章的标题及正文(本节内容)

3.从文章正文中解析出全部图片链接,并将文章的全部图片下载到本地(下节内容)

这3步有了,之后你就想怎么折腾就怎么折腾了,各种加工处理,生成pdf,chm,静态站点,远程发布到其他站点等等(请继续关注本系列文章,并不吝点一下推荐,您的支持是我写作的最大动力)。

作者:宋波
出处:http://www.cnblogs.com/ice-river/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

网络采集软件核心技术剖析系列(2)---如何使用C#语言获得任意站点博文的正文及标题的更多相关文章

  1. 网络采集软件核心技术剖析系列(7)---如何使用C#语言搭建程序框架(经典Winform界面,顶部菜单栏,工具栏,左边树形列表,右边多Tab界面)

    一 本系列随笔概览及产生的背景 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受广大博客写作和阅读爱好者的喜爱.同时也不乏一些技术爱好者咨询我,这个软件里面各种实用的功能是如何实现的. 该软件 ...

  2. 网络采集软件核心技术剖析系列(6)---将任意博主的全部博文下载到SQLite数据库中并通过Webbrower显示(将之前的内容综合到一起)

    一 本系列随笔目录及本节代码下载 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受广大博客写作和阅读爱好者的喜爱.同时也不乏一些技术爱好者咨询我,这个软件里面各种实用的功能是如何实现的. 该软 ...

  3. 网络采集软件核心技术剖析系列(5)---将任意博主的全部博文下载到内存中并通过Webbrower显示(将之前的内容综合到一起)

    一 本系列随笔概览及产生的背景 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受广大博客写作和阅读爱好者的喜爱.同时也不乏一些技术爱好者咨询我,这个软件里面各种实用的功能是如何实现的. 该软件 ...

  4. 网络采集软件核心技术剖析系列(4)---使用C#语言如何将html网页转换成pdf(html2pdf)

    一 本系列随笔概览及产生的背景 本系列开篇受到大家的热烈欢迎,这对博主是莫大的鼓励,此为本系列第四篇,希望大家继续支持,为我继续写作提供动力. 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受 ...

  5. 网络采集软件核心技术剖析系列(3)---如何使用C#语言下载博文中的全部图片到本地并可以离线浏览

    一 本系列随笔概览及产生的背景 本系列开篇受到大家的热烈欢迎,这对博主是莫大的鼓励,此为本系列第三篇,希望大家继续支持,为我继续写作提供动力. 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受 ...

  6. 《SDN核心技术剖析和实战指南》第一章小结

    第一章主要是概况.新技术有一个特点是,每家都有不同的说法.这里我只说说我比较认同的部分. SDN的核心概念大概有两个:转发面与控制面分离.开发可编程化.书里还说逻辑上集中控制,其实这个就可以从转发与控 ...

  7. WorldWind源码剖析系列:星球球体的加载与渲染

    WorldWind源码剖析系列:星球球体的加载与渲染 WorldWind中主函数Main()的分析 在文件WorldWind.cs中主函数Main()阐明了WorldWind的初始化运行机制(如图1所 ...

  8. 《SDN核心技术剖析和实战指南》2.3 OF-CONFIG配置管理协议小结

    OpenFlow协议定义了交换机和控制器交换数据的方式和规范,但并没有定义如何配置和管理必需的网络参数和网络资源,OF-CONFIG的提出就是为了对OpenFlow提供配置管理支持.如下图所示,OF- ...

  9. 采用VSPD、ModbusTool模拟串口、MODBUS TCP设备进行Python采集软件开发

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 不少仪器/设备都提供了数据采集的接口,其中不少是串口或网络的MODBUS/TCP协议. 串口是比较简单 ...

随机推荐

  1. C++ 智能指针的简单实现

    智能指针的用处:在c++中,使用普通指针容易造成堆内存的泄露问题,即程序员会忘记释放,以及二次释放,程序发生异常时内存泄漏等问题,而使用智能指针可以更好的管理堆内存.注意,在这里智能指针是一个类而非真 ...

  2. rest service技术选型

    MySql workbench下载 http://dev.mysql.com/downloads/workbench/ 最好的8个 Java RESTful 框架 http://colobu.com/ ...

  3. bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑——倍增floyd

    Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力跑的地点 自然是在牧场中现有的T(2 <= T < ...

  4. 使用SpringMVC解决Ajax跨域问题

    package com.mengyao.system.filter; import java.io.IOException; import javax.servlet.FilterChain; imp ...

  5. Ring0层创建事件,Ring3层接收

    在学习驱动过程中,一个很重要的内容就是Ring3层与Ring0层的通信,方法有很多种,互斥体,信号量,文件等等,用的比较普遍的,还是事件.所以在学习的过程中,做了一个简单的Demo,主要是体会一下方法 ...

  6. C++学习笔记之——内联函数,引用

    本文为原创作品,转载请注明出处 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing/ 作者:晨凫 ...

  7. Yeelight介绍

    1. 介绍 Yeelight是小米生态链中的WiFi智能灯泡,本文介绍它的接入和控制实现: Yeelight使用的是自定义的私有协议,该协议采用了类似SSDP的发现机制和基于JSON的控制命令 2. ...

  8. Java==与equals方法的区别

    摘自:http://www.cnblogs.com/dolphin0520/p/3592500.html 1.对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等: 如果作用于引 ...

  9. 在另一个文本框显示input file选择的文件名字

    javascript 获取文件域 (type=file) 的完整路径一直是很麻烦的问题,问题主要出在一些浏览器基于安全性考虑而不能正常获取到文件域中选中图片的决对路径,尤其一些基于webkit的浏览器 ...

  10. Selenium2+python自动化21-TXT数据参数化【转载】

    前言      在17篇我们讲了excel数据的参数化,有人问了txt数据的参数化该怎么办呢,下面小编为你带你txt数据参数化的讲解 一.以百度搜索为例,自动搜索五次不同的关键字.输入的数据不同从而引 ...