采集程序最简单的思路就是:获取页面代码——分析代码——获取需要的部分——写入数据库。
当然,在获取页面代码之前我们首先要获得被采集页面的url,这里我们从百度新闻获取某关键词最新新闻列表。
function get_baidu_news_url($str){
if(!$str) return;
$str = gbk($str);
//使用正则匹配出列表中的新闻URL
$html = utf8(file_get_contents('http://news.baidu.com/ns?tn=newstitle&cl=2&rn=20&word=' . urlencode($str)));
preg_match_all("/<a href=http:\/\/(.+?) mon=(.+?)>(.+?)<\/a>/is",$html,$match);
$urlarr = $match[1];
if($urlarr){
//URL前面补上http://
array_walk($new_urlarr, create_function('&$v', '$v = "http://".$v ;'));
cache_write($cachename, $new_urlarr, CACHE_PATH);
}
return $new_urlarr;
}
拿到新闻页面的URL之后,下一步就是采集页面上的新闻,当然这一步要针对各个网站定制不同的匹配规则,这里以新浪为例。新浪新闻以“<!– 正文内容 begin –>”开始,“<!– 正文内容 end –>”结束,所以匹配正文的正则为
preg_match_all("/<!-- 正文内容 begin -->([\s|\S]*?)<!-- 正文内容 end -->/is",$html,$match);
同理,匹配标题的正则为
preg_match_all("/<h1 id=\"artibodyTitle\"(.*?)>(.+?)<\/h1>/is",$html,$title_match);
函数完整代码:
function news_content_sina($url){
if(!$url) return;
$html = utf8(file_get_contents($url));
preg_match_all("/<!-- 正文内容 begin -->([\s|\S]*?)<!-- 正文内容 end -->/is",$html,$match);
preg_match_all("/<h1 id=\"artibodyTitle\"(.*?)>(.+?)<\/h1>/is",$html,$title_match);
$title = $title_match[2][0];
$content = news_content_format($match[1][0]);
if($title && $content) return compact('url','title','content');
}
上面方法中用到了 news_content_format(),这个方法是用来格式化采集到的正文,去掉js、css、iframe、注释以及站内链接,下面代码中可以看到,我们去除了站内链接但保留了其他的<a>标签链接,这样就可以避免某些重要外链丢失影响新闻完整性,比如某考试报名地址链接。
function news_content_format($content){
$search = array ("'<script[^>]*?>.*?</script>'si", // 去掉 javascript
"'<style[^>]*?>.*?</style>'si", // 去掉 css
"'<iframe[^>]*?>.*?</iframe>'si", // 去掉 iframe
"'<!--[/!]*?[^<>]*?>'si", // 去掉 注释 标记
"'<a(.*?) href=(.*?)(sina.com|weibo.com)(.*?)>(.*?)<\/a>'si", // 去掉 内部 链接
);
$replace = array ("","","","","","\${5}");
$content = preg_replace($search, $replace, $content);
$content = strip_tags($content, '<p> <br> <img> <table> <tr> <td> <strong> <a>');
return $content;
}
到这里,采集的功能基本上就完成了,但是还有一点要注意,就是新闻中的图片如果也需要采集到本地的话,就要用到下面这个方法。
function getimage($body){
global $img_dir,$img_webhost;//本站图片目录、主机
if(!empty($body)){
$body = stripslashes($body);
$img_array = array();
//匹配出采集内容中的图片地址
preg_match_all("/(src|SRC)=[\"|'|]{0,}(http:\/\/(.*)\.(gif|jpg|jpeg|bmp|png))/isU",$body,$img_array);
$img_array = array_unique($img_array[2]);
set_time_limit(0);
//定义图片名,创建目录
$imgPath = $img_dir."/".strftime("%Y%m%d",time());
$imgUrl = "http://".$img_webhost."/".$imgPath;
$milliSecond = strftime("%H%M%S",time());
if(!is_dir($imgPath)) @mkdir($imgPath,0777);
foreach($img_array as $key =>$value)
{
$value = trim($value);
//抓取图片并保存
$get_file = @file_get_contents($value);
$rndFileName = $imgPath."/".$milliSecond.$key.".".substr($value,-3,3);
$fileurl = $imgUrl."/".$milliSecond.$key.".".substr($value,-3,3);
if($get_file)
{
$fp = @fopen($rndFileName,"w");
@fwrite($fp,$get_file);
@fclose($fp);
}
$body = ereg_replace($value,$fileurl,$body);
}
return $body;
}
写入数据库等常规的操作在这里就不再赘述。