一.    什么是数据采集
几年前,除几个大门户网站以外,基本上都是个人网站。资讯分散,内容也并不多。几年后,商业网站越来越多,资讯需要大量集中,即便有足够的财力聘请大量的文字编辑,也未必能满足无时无刻变化的信息资源。
咨讯采集已成了让所有网站经营者青睐的技术。本文针对PHP语言简单谈一些数据采集的知识。
首先说资讯结构,咨讯结构一般为[分类标题式],例如搜狐新闻分类为:
 
排行 | 国内 | 国际 | 社会 | 军事 | 日月谈 | 地方 | 在线阅读
访谈 | 专题 | 图吧 | 论坛 | 文字版 | 导航 | RSS | 视频
 
进入国内新闻:我们会看到最新的20条新闻标题列表
 
·阿扁宣称大陆要并吞台湾 国台办评其未停止台独
·李维一:台借汪老丧礼搞权谋 两岸包机应常态化
·中国铁路第六次大提速:101全部准备到位
·淮南“1-5煤与瓦斯突出事故仍有12名工人被困
·西安经济在副省级城市排倒数 一把手提发展要点
·高法称要让百姓告状有门 统一行使死刑核准权
·我国驻马来西亚副领事遭当地男子无辜殴打受伤
·国台办评陈水扁元旦讲话 “台独”分裂并未停止
·新疆雪灾造成22万人被困() 未来10天持续降雪
·去年中国向20国提供援助 雪中送炭获得国际盛赞
·北京06年区县两会开幕 委员建议洗车业全用中水
·北京西站春运加开54对临客 上海票价21日起涨价
·深发展否认前行长周林被拘捕 报道严重失实()
·深圳出台新年1号文件:大学生可以个人身份入户
·教育部实施即时动态监管 监控直属高校资金流动
·湖北大学原副校长受贿案庭审 夫妻对视泪双流
 
我们需要对每个分类下的新闻标题列表以及它们的内容作自动收集,就是最简单新闻采集器。
二.    得到网页内容
(1).   网页内容
得到新闻网页内容可以使用多种函数,例如:fopen(),file_get_contents();
<?
$doc = file_get_contents("http://news.sohu.com/n241303906.shtml");
echo $doc;
?>
(2).   切割网页内容
可以使用以下函数切割网页中的内容,大意是把网页按照两个标签切成三部分,取中间的部分。例如ABCDEF,我们知道CE可以取D
<?php
function get_sub_content($str, $start, $end){
        if ( $start == '' || $end == '' ){
               return;
        }
        $str = explode($start, $str);
        $str = explode($end, $str[1]);
        return $str[0];
}
?>
三.    分析文章列表
(1).   布局
文章列表的大概布局如下:
标题
标题
标题
 
[ 翻页 上一页 <1 2 3> 下一页 ]  [ 更多>>> ]
 
使用函数get_sub_content()找到html中的文章列表,所以采集的很多地方需要用到它,我们最好把它放在公用函数库里面供更多页面调用。使用正则表达式得到每一个标题。我也封装好了一个函数:
       //取得代码中所有链接
        function get_all_url($code){
                preg_match_all('/<as+href=["|']?([^>"' ]+)["|']?s*[^>]*>([^>]+)</a>/i',$code,$arr);
               return array('name'=>$arr[2],'url'=>$arr[1]);
        }
 
当你去的当前页的所有文章后,可以进一步对翻页和更多这样常见的功能进行分析。
四.    分析文章本身
(1).   布局
一般新闻都包含以下内容:
标题
作者 日期 来源
正文
[附件]
 
例如:
 
深发展否认前行长周林被拘捕 报道严重失实()
 
作者:小周时间:2006010609:54 来源:搜狐新闻
 
中国台湾网16消息据台媒报道,中国国民党中央政策会副执行长张荣恭5日说,陈水扁5日再发谬论批评大陆,就是希望借两岸气氛重新紧绷、拉抬低落的声望。而国民党主席马英九在获悉陈水扁此文后也表示,陈水扁的言论是错误的,让许多台湾民众都无法同意。
后面略
 
(2).   提取信息
我们使用get_sub_content ()函数,使用作者:时间:进行切割后得到的就是小周。代码如下:
<?
//$doc应该是从页面中读取到的全部网页内容。
$author = get_sub_content($doc, "作者:", "时间:");
$author = trim($author);
echo $author;
?>
输入结果为:
小周
 
标题前后没有特殊标志,我们很难判断,但是标题可以从新闻标题列表中得到。所以新闻页面中只提取作者,日期,来源,内容即可。
项目
开始标志
结束标志
内容
作者
作者:
时间:
小周
日期
时间:
来源:
2006010609:54
来源
来源:
[空格]
搜狐新闻
 
日期提取出来后要经过处理,而且你要想想怎样才能应付不同网站的日期格式。
关于内容的提取要具体分析页面内的html
例如,www.phpe.net 某文章的HTML代码片断如下:
        <tr><td style="word-wrap:break-word; font-size: 14px; line-height: 160%"><P><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 15pt">PHP中的字符串操作功能是比较多的,重要的有以下这些: &nbsp; <BR><BR><STRONG>(1)echo,print,printf,sprintf&nbsp; <BR></STRONG>前两个函数是输出字符串.字符串中如果有变量名则被替换成其值. &nbsp;
<td style="word-wrap:break-word; font-size: 14px; line-height: 160%"> 一句我用Ctrl+F搜过了在全文只出现过一次,所以我可以将这句作为内容的开始标志,我们也可以找到文章明显的结束标志,如下:
    </script>
    </td></tr>
        <tr><td align="RIGHT">(责任编辑:超越PHP)</td></tr>
      </table>
 
<td align="RIGHT">(责任编辑:超越PHP)</td></tr>这句在全html中也出现了只一次。我们用上面自定义的函数get_sub_content()就可以得到文章的内容。
(3).   关于附件
如果我们只采集了文章内容,而这篇文章中有图片和链接,就很难完美了。因为你采集到自己站点中,链接会失效,图片也不一定能出来,除非作者用的绝对路径,所以你进一步要对文章中出现的所有链接和图片进行分析,并下载图片。
如果链接是特殊后缀如.doc, .zip, .tgz等还要对相应附件进行下载。然后统一改变成相对于你站点的路径替换到文章里。一般附件我们使用时间作为文件名,来保证不重名。当然要精确到微秒级。
 
五.    总结
采集器要做的通用,不能仅仅只能采集一个站点,而应该可以对多个站点进行采集,同时要针对自己网站现有的分类和采集分类作对应。如果想做的更好一些,应该可以提供给第三方使用。否则只能算网站的采集功能,而采集器应该是一个完整产品。