手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表Tag:采集

hongyin163:网页信息抓取实现

突然怀念起几年前,walkerlee、hihiyou、我还在为了NC进行打拼,也曾为了某个正则几乎通宵不睡在测试。其实在NC前已经有过多款的采集软件,但其实都是属于功能单一情况,如:开花石头的逆向小偷等。NC只是一款整合了一起功能的采集软件,也算是开创了先河吧?反正自那以后,采集程序越来越多,先是剑枫,然后是小蜜蜂,再后来是火车头,采集软件越来越多之后,随之而来的就是性能问题,采用WEB方式的采集,不可避免的就是性能。你没有办法控制一个WEB页面不会超时,而且PHP由于自身的执行方式,也就不可能是多线程执行,后来大多数人,采用了iframe的方式,让一个页面打开十个左右的iframe然后根据执程的ID来进行判断。

过去的事情,总是让人怀念,在看到这个作者写类似的采集时,感慨的同时,留一份备份,以作纪念

原文:http://www.cnblogs.com/hongyin163/archive/2009/02/11/1388615.html
内容:

最近公司需要开发一个简历导入功能,类似博客搬家或者邮箱搬家,之前抓取信息是利用火车采集器,但是简历导入功能需要用户登陆以后才能获取简历数据,无奈只好自己开发了。

首先是遇到的问题是:如何实现模拟登陆?

我们知道一般的网站都是通过Cookies来维护状态的,我抓的网站也是支持利用Cookies来验证用户的,构造一个post数据包,向服务器提 交数据,在配置火车采集器的时候,也是要先利用WSockExpert.exe工具获得Post数据包,之后修改用户名和密码,向服务器提交的。

提交了登陆数据后还没完成登陆,虽然服务器会返回登陆后的页面数据,但是如果在进入其他的链接页面,还是不允许的,因为服务器每次都需要通过你提交 过去Cookies来验证你是否登陆,在asp.net里,利用Cookies存储身份验证票证,每次都需要向服务器提交的,初学asp.net总是弄不 明它的form验证机制,它封装了太多信息,虽然用几行代码就能实现验证,后来看了些web开发基础知识才弄明白,在这个你需要保存上次登陆后返回的 Cookies,在下次有其他请求时带上这个Cookies就可以了,怎么带上呢?下面是我在.net里的实现,很简单!

利用HttpWebRequest类的CookieContainer来保存,这个CookieContainer会保存服务器回传的 Cookies,但是前提是你在初始化HttpWebRequest的时候,记得实例化这个CookieContainer,一般的请求不需要实例它的, 简单的代码如下:

 httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(URL);            
  httpWebRequest.CookieContainer = new CookieContainer();
  httpWebRequest.ContentType = "application/x-www-form-urlencoded";
 httpWebRequest.Method = "POST"

 为了能全局使用这个CookieContainer ,你可以把它作为全局变量,这样在下次request的时候将其赋给CookieContainer 属性就行了。

详细了解CookieContainer 见:http://msdn.microsoft.com/zh-cn/vstudio/system.net.cookiecontainer(VS.80).aspx

维护了这个CookieContainer 后,我们就可以访问登陆后的页面了,模拟登陆问题解决。

其次遇到的问题自然是:如果从网页上获得想要的信息?

 要在网页抓取信息,实现起来最简单,同时也是最繁琐的方法,那就是模板方法获取了,从火车采集器的配置过程看出来,它也就是用这种方法而已,不过 人家能把抓取器做成成熟的产品,并且热卖,这个比不了,所以成功与否不完全取决于技术,火车采集器虽然配置起来挺繁琐,但是用起来还不错。

用这种方式你需要做个一个模板,你需要知道目标网页的结构,知道要找的信息在什么地方,之后记录在它的前面和后面的字符串,你可以利用截取字符串的 方式获得目标信息,也可以利用正则标式获得,要保证前面和后面的字符串是唯一的,很简单,计算一下,或者匹配一下就可以获得目标信息,但是实际做起来还是 会遇到一些问题:

下面是我遇到问题;

1.首先我是想利用正则表达式匹配,但是模块里设置的前缀和后缀里有回车换行\r\n,结果总是匹配不成功,我正则的功底很差,最后知道怎么回事了,把\r\n替换成(\s*),问题解决,您可以想出为什么了吧?

2.利用字符串截取方式获取,在正则还不是很精通,用这种方式最保险了,但是在截取字符串前记得调整下目标页代码,从xml配置文件里读取的前缀和 后缀中可能有回车和换行,但是回车换行在不同系统里字符表现是不一样的,Windows里是\r\n,Linux里是\n,所以要记得统一。

3.前后缀不唯一,有时在页面里有两个不同的目标信息,但却有相同的前缀,比如:

<td width="25%" class="ResTbLfPd">数据库</td>
<td width="25%" class="ResTbLfPd">软件工程师</td>

如果用相同的前缀就比较难截到想要的信息了,我想了个办法,当然方法可能比较笨,但是问题解决了,也是火车给我的启示,利用多个字符串定位目标信息,比如我想抓去 软件工程师 ,前缀就是:

<td width="25%" class="ResTbLfPd">*</td>
<td width="25%" class="ResTbLfPd">

在信息可能不同的地方用*代替,类似通配符,这样利用*将一个字符串切割为两个,先找到第一个,之后以这个索引位置为起点,再找第二个字符串,这样就可以定位到最终的信息了,同样可以用多个字符串三个或更多,这样实现是解决了问题,希望有更好的方式,希望以后会改进。

4.在抓取信息的时候还可以利用MITHtmlPparser,这是一个开源的类库,在codeproject找搜到的,将网页内的所以标签都分析出来,如果获取信息不是很多、很碎的话,用这个也比较好用,只需知道那个最终要得到信息在那个标签里,然后直接取出就行了。

好了,希望在新的一年里能学到更多,能经得住考验!

Tags: 采集