给大家推荐几种实现网页数据抓取的方式

4043335 2010-05-28 10:29:03
相信所有个人网站的站长都有抓取别人数据的经历吧,目前抓取别人网站数据的方式无非两种方式:

一、使用第三方工具,其中最著名的是火车头采集器,在此不做介绍。

二、自己写程序抓取,这种方式要求站长自己写程序,可能对对站长的开发能力有所要求了。

本人起初也曾试着用第三方的工具抓取我所需要的数据,由于网上的流行的第三方工具不是不符合我的要求,就是过于复杂,我一时没有搞明白怎么用,后来索性决定自己写吧,现在本人基本上半天可以搞定一个网站(只是程序开发时间,不包括数据抓取的时间)。

经过一段时间的数据抓取生涯,也曾遇到了很多困难,其中最常见的一个就是关于分页数据的抓取问题,原因在于分数据分页的形式有很多种,下面我主要针对三种形式介绍一下抓取分页数据的方法,此类文章虽然在网上见过很多,但每次拿别人的代码总也总是有各种各样的问题,下面各种方式的代码都是能正确执行,并且我目前也正在使用中的。本文中代码实现是用C#语言来实现的,我想其他语言原理大致相同

下面切入正题:

第一种方式:URL地址中包含分页信息,这种形式是最简单的,这种形式使用第三方工具抓取也很简单,基本上不用写代码,对于我这种宁可自己花个半天时间写代码也懒得学第三方工具的人,还是通过自己写代码实现了;

这种方式就是通过循环生成数据分页的URL地址 如: 这样通过HttpWebRequest访问对应URL地址,返回对应页面的html文本,接下来的任务就是对字符串的解析,将需要的内容保存到本地数据库内;抓取的代码可参考下面:

public string GetResponseString(string url)
{

string _StrResponse = "";
HttpWebRequest _WebRequest = (HttpWebRequest)WebRequest.Create(url);
_WebRequest.UserAgent = "MOZILLA/4.0 (COMPATIBLE; MSIE 7.0; WINDOWS NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)";
_WebRequest.Method = "GET";
WebResponse _WebResponse = _WebRequest.GetResponse();
StreamReader _ResponseStream = new StreamReader(_WebResponse.GetResponseStream(), System.Text.Encoding.GetEncoding("gb2312"));
_StrResponse = _ResponseStream.ReadToEnd();
_WebResponse.Close();
_ResponseStream.Close();
return _StrResponse;
}

上面的代码可以返回对应页面的html内容的字符串,剩下的工作就是从这个字符串中获取自己关心的信息了。

第二种方式:可能是通过asp.net开发的网站常会遇到,它的分页控件通过post方式 提交分页信息到后台代码,如.net下Gridview自带的分页功能,当你点击分页的页码时,会发现URL地址没有变化,但页码变化了,页面内容也变化,仔细看会发现,把鼠标移到每个页码上的时候状态栏会显示 javascript:__dopostback("gridview","page1")等等 之类的代码,这种形式其实也不是很难,因为毕竟有地方得到页码的规律可寻。

我们知道http请求提交的方式有两种一种是get一种是Post,第一种方式是get方式,那么第二种方式就是post方式,具体提交的原理不必细说,不是本文的重点

抓取这种页面 需要注意asp.net页面的几个重要的元素

一、 __VIEWSTATE ,这个应该是.net特有的,也是让.net开发人员既爱又恨的东西,当你打开一个网站的某一个页面的时候,如果发现这个东西,而且后面还跟随着一大堆乱七八糟的字符的时候,那这个网站肯定是用asp.net写的了;

二、__dopostback方法,这个是asp.net页面自动生成一个javascript方法,包含两个参数,__EVENTTARGET,__EVENTARGUMENT,这两个参数可以参看页码对应的内容,因为点击翻页的时候,会将页码信息传给这两个参数。

三、__EVENTVALIDATION 这个也也应该是asp.net特有的东西

大家也不用 太关心这三个东西都是干什么的,只需要注意自己写代码抓取页面的时候 记得提交这三个元素就可以了。

和第一种方式一样,肯定要通过循环的方式是去拼凑_dopostback的两个参数,只需要拼其中包含了页码信息的参数即可。这里有一个需要注意的地方,就是在每次通过Post提交请求下一页的时候,先应得到当前页的__VIEWSTATE 信息和__EVENTVALIDATION信息,所以分页数据的第一页可采用第一种方式得到页码内容然后,同时取出对应的__VIEWSTATE 信息和__EVENTVALIDATION信息,然后再做循环处理下一页面,然后每抓取完一个页面,再记录下__VIEWSTATE 信息和__EVENTVALIDATION信息,为下一个页面post提交数据使用

参考代码如下:

for (int i = 0; i < 1000; i++)
{
System.Net.WebClient WebClientObj = new System.Net.WebClient();
System.Collections.Specialized.NameValueCollection PostVars = new System.Collections.Specialized.NameValueCollection();
PostVars.Add("__VIEWSTATE", "此处是您需要提前得到的信息");
PostVars.Add("__EVENTVALIDATION", "此处是您需要提前得到的信息");
PostVars.Add("__EVENTTARGET", "此处是__dopostback方法对应的参数");
PostVars.Add("__EVENTARGUMENT", "此处是__dopostback方法对应的参数");
WebClientObj.Headers.Add("ContentType", "application/x-www-form-urlencoded");
try
{
byte[] byte1 = WebClientObj.UploadValues("http://www.xxxx.cn/messagelist.aspx", "POST", PostVars);
string ResponseStr = Encoding.UTF8.GetString(byte1); //得到当前页面对应的html 文本字符串
GetPostValue(ResponseStr);//得到当前页面对应的 __VIEWSTATE 等上面需要的信息,为抓取下一页面使用
SaveMessage(ResponseStr);//保存自己关心的内容到数据库中
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}

第三种方式是最麻烦的,也是最恶心的,这种页面 在你翻页的过程中没有任何一个地方可以找到页码信息,这种方式费了我很大的力气,后来采用了一个比较狠的办法,用代码模拟手动翻页,这种方式应该可以处理任何形式的翻页数据,原理就是,用代码模拟人工点击翻页链接,用代码一页一页的翻页,然后一页一页的抓取。

如果想了解更多的信息 可访问 http://www.zxskb.com/bbs/3.html

这个是我个人站上 新建的一个站长随笔功能,我会定期发布一些我的个人心得,如果有兴趣的可以去看看,本贴算是我第一个随笔吧


...全文
1671 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
yanghailun_ 2010-05-30
  • 打赏
  • 举报
回复
接分......
tom_skypower 2010-05-28
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 jcgh1985 的回复:]
麻烦和难点在正则
[/Quote]
也可以不使用正则来处理数据
用dom
tom_skypower 2010-05-28
  • 打赏
  • 举报
回复
lz可以使用WebBrowser控件来完成

WebBrowser wb1 = null;
void wb1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.ToString() != wb1.Url.ToString())
{
return;
}
}
白s菜 2010-05-28
  • 打赏
  • 举报
回复
麻烦和难点在正则
dd__dd 2010-05-28
  • 打赏
  • 举报
回复
a82344626 2010-05-28
  • 打赏
  • 举报
回复
来接分的!
这个早知道了!
只是数据那要自己写正则表达式的!
我自己最近就做了一个!
准备“看雪论坛”转正后散分和发我做的源代码!我明天就可以转正了!
随便来庆祝一下!
哈哈
newdigitime 2010-05-28
  • 打赏
  • 举报
回复
[Quote=引用楼主 4043335 的回复:]
这种页面 在你翻页的过程中没有任何一个地方可以找到页码信息[/Quote]

有这种网?想看看,给个例子
newdigitime 2010-05-28
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 mamudelingling 的回复:]
我做过采集平常都用正则,不知道楼上说的dom是什么呢?
[/Quote]
XML DOM
HTML DOM
javascript或XML命令可以操作DOM
mamudelingling 2010-05-28
  • 打赏
  • 举报
回复
我做过采集平常都用正则,不知道楼上说的dom是什么呢?

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧