以前写了篇"百度视频采集"的思路简介,看到唯逐一个人留言希望我总结一下新闻采集。今天就拿博客园的热门文章采集做个例子。说明前我得声明一点,经过在博客园混了几个月后,发现博客园首页发布的文章一般都是高手,很有参考价值。可我是一个新手,我请大家此文章的任何质疑直接留言,由于您发现题目不说出来,可能我永远会以为自己写的是正确的。
下面进入正题。首先需要留意的是采集网页上数据的唯一方式是必须获取需要采集页面的源代码,这点想必大家很清楚。由于我们不知道对方网站的数据库服务器连接方式,我们只能在页面的源代码中找寻我们想要的东西。这无疑就是对大量字符串进行处理,那么我们如何处理这些含有大量html标记与内容的代码呢?可能解决题目的方式有很多种,但我以为用正则表达式来解决这个题目会很好。
通过上面的话,我谈到了两个知识点,我们来总结一下流程。
1.获取需要采集页面的源代码。
2.利用正则表达式处理这些代码中我们想要的内容。
下面做一些预备工作,写一个实体类存储文章的信息。例如:标题、作者、发布时间、浏览次数,等。
文章信息实体类
Code
[copy to clipboard]
CODE:
using System;
using System.Collections.Generic;
using System.Text;
namespace Plug.Article.Entity
{
/*summary
///采集文章信息,部分属性可留空。标题与地址如为空则默认赋值时引发异常
summary
[Serializable]
public class Article
{
private string category;
/*summary
///文章种别
summary public string Category
{
get{return category;}
set{category=value;}
}
private string url;
/*summary
///文章连接地址
summary public string Url
{
get
{
return url;
}
set
{
if(value==""||value.Length=0)
{
throw new ApplicationException("文章的连接地址不能为空!");
}
url=value;
}
}
private string title;
/*summary
///文章标题
summary public string Title
{
get
{
return title;
}
set
{
if(value==""||value.Length=0)
{
throw new ApplicationException("文章的标题不能为空!");
}
title=value;
}
}
private int views;
/*summary
///文章浏览次数
summary public int Views
{
get
{
return views;
}
set
{
views=value;
}
}
private int replys;
/*summary
///文章评论次数
summary public int Replys
{
get
{
return replys;
}
set
{
replys=value;
}
}
private string datatime;
/*summary
///文章发布日期
summary public string Datatime
{
get
{
return datatime;
}
set
{
datatime=value;
}
}
private string author;
/*summary
///文章作者
summary public string Author
{
get
{
return author;
}
set
{
author=value;
}
}
private string site;
/*summary
///文章作者网站、文章采集网站
summary public string Site
{
get
{
return site;
}
set
{
site=value;
}
}
}
}
获取采集网页源代码的方式,也很简单,我单独做成了一个类。
获取网页源代码
Code
[copy to clipboard]
CODE:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
namespace Plug.Article
{
/*summary
///网页操纵类
summary public class HTML
{
/*summary
///获取网页源代码
summary
///param ///returns/returns public string GetHTML(string url)
{
WebClient web=new WebClient();
byte buffer=web.DownloadData(url);
return Encoding.Default.GetString(buffer);
}
}
}
拿到源代码,该进入关键步骤了,写正则表达式采集数据。在采集之前我们需要了解网页源代码的特征,假如都不知道我们想要什么,恐怕无法写出正则表达式。我们要采集的页面是这个页面,博客园文章阅读排行榜。本日阅读排行、昨日阅读排行等信息。但我们要得到的只是如下信息:
·我在外资公司的2个月(阅读:1909)(评论:21)(2008-6-25 13:44)yesry
·为什么尽量避免使用触发器?(阅读:1490)(评论:15)(2008-6-25 03:35)凉面
·Discuz!NT系统架构分析(阅读:1391)(评论:18)(2008-6-25 12:35)韩龙
·硬盘那点事儿(阅读:1342)(评论:15)(2008-6-25 11:16)李战
只需要得到标题、阅读次数、评论、时间、作者即可。那么我们就来分析一下关键信息的源代码特征。
Code
[copy to clipboard]
CODE:
tr td ·a /td td height="20"
a /tr
这就是我们需要采集信息的源代码。在开始写正则表达式之前我需要说明一点,我们都知道,这些内容也是动态产生的。所以它们的格式肯定是固定的。这样我们就可以利用一个正则表达式正确的采集到该页面所有信息。我觉得没必要在这片文章中具体解释正则表达式的含义,由于这需要多练习。
Code
[copy to clipboard]
CODE:
Regex regexarticles=new Regex(".+·as+id=".+"href="(?url.+)"s+target="_blank"(?title.+)/a spans+class=".+"(阅读?views d+)).*(评论?reply d+)).*((?time.+))/span s*/td s*tds+height="d+"s+as+id=".+"href="(?blog.+)"(?author.+)/a");
这些让您可能阅读起来很吃力,但我想学过正则表达式的人会嘲笑我,由于我的正则写的不够灵活。我要为没有接触过正则表达式的朋友简单介绍下,我也只是刚入门。正则表达式就是通过描述字符串的特征来进行匹配。这也是我们为什么需要分析页面源代码的原因。至于怎么去匹配,实在也不难,我提供一些文章给各位参考。
正则表达式学习笔记:正则表达式30分钟入门:我就是通过这两篇文章入门,并利用正则表达式写出了我喜欢的程序。至于更多的文章可以去网络寻找。
上面说到的是关键的正则表达式,下面还需要说一下怎么去取。
采集关键代码
Code
[copy to clipboard]
CODE:
//网页操纵对象,我用来获取网页源码
HTML html=new HTML();
//对博客园逐日排行数据进行采集
string htmlcode=html.GetHTML("//提取博客园排行文章信息的正则表达式
Regex regexarticles=new Regex(".+·as+id=".+"href="(?url.+)"s+target="_blank"(?title.+)/a spans+class=".+"(阅读?views d+)).*(评论?reply d+)).*((?time.+))/span s*/td s*tds+height="d+"s+as+id=".+"href="(?blog.+)"(?author.+)/a");
//所有匹配表达式的内容
MatchCollection marticles=regexarticles.Matches(htmlcode);
/*遍历匹配内容
foreach(Match min marticles)
{
Entity.Article test=new Entity.Article();
test.Category="博客园热门文章";//设置分类
test.Title=m.Groups["title"].Value;//设置标题
test.Url=m.Groups["url"].Value;//设置连接
test.Views=int.Parse(m.Groups["views"].Value);//设置浏览次数
test.Replys=int.Parse(m.Groups["reply"].Value);//设置评论次数
test.Datatime=m.Groups["time"].Value;//设置发布时间
test.Author=m.Groups["author"].Value;//设置作者
test.Site=m.Groups["blog"].Value;//设置文章出处
list.Add(test);
}
MatchCollection marticles=regexarticles.Matches(htmlcode);
通过此句代码获取多个匹配的内容。
Code
[copy to clipboard]
CODE:
foreach(Match min marticles)
循环时需要用Match类取一条匹配内容,m.Groups["title"].Value取出指定分组中的信息,这个分组是指(?title.+),"?title"这就是给匹配内容分组为title的代码。代码就是这样了,没有什么技术含量,来总结一下做采集的一个流程吧。
1.取指定页面的源代码
2.分析源代码中我们想要获得内容的特征
3.通过特征写出正则表达式进行匹配
4.遍历匹配内容装入集合