PHP采集程序相关

采集程序最简单的思路就是:获取页面代码——分析代码——获取需要的部分——写入数据库。

当然,在获取页面代码之前我们首先要获得被采集页面的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;
 }

写入数据库等常规的操作在这里就不再赘述。

发表评论

电子邮件地址不会被公开。