服务器之家

专注于服务器技术!
当前位置:首页 > 脚本编程 > PHP

织梦采集侠自动提取网页标题原理及PHP源码

发布时间:2014-11-14 来源:服务器之家

     我这几天看了下织梦采集侠的源码,发现有很多成熟的技术,比如这个采集网站文章的题目,源码一会再上,先做简单解释:


     首先,很多人会一直会认为这不是很简单,就是<title>标签中的内容嘛,不是很容易获取吗?其实不然,很多的title部分不一定放文章的题目,很多的网站还加入了关键字,而且一定加入网站名。


     如:“php采集网站的title_php采集_EnEnBa Blog”,对于一个采集者来说此文章只需要“php采集网站的title”就可以了,“_php采集_EnEnBa Blog”部分不是我们想要的。要过渡掉。


     还有就是可以从文章的标题标签中找出来,如h1 h2 h3 等标签,很多建站者注意了这些标签的权重,很容易也写出正则获取。但是也有例外,人家没有写<h1>这些标签呢,此方法不适用所有网站。

 

织梦采集侠就考虑了以上的两种情况并写出了很完美的解决方案。
1、首先获取页面下的所有<title>和<h……>标签
2、对比title 和 <h……>中的内容。如果一样的部分就返回<h……>中的内容
3、如果没有<h……>的内容,对title部分按分割符进行分割,常用的标题分隔有 “-”、“—”、“_”、“>”、“|” ,返回最长的字符串。

 

演示:http://enenba.com/tool/get_title/

上源码吧,从采集侠源码中提取的,注意编码为utf-8,

 


<?php
/**
 * 采集文章的题目
 * @param string  $html  需要采集的html源代码
 * @param int $maxlen    最大题目长度
 * @return   string
 */
function TT($html,$maxlen) {
        if (preg_match("/<title>(.*)</title>/isU", $html, $t)) {
                if (preg_match_all("/<h([1-3])(?:[^>]*)>(.*)</h\1>/isU", $html, $ts)) {
                        foreach($ts[2] as $vt) {
                                if (strpos($t[1], $vt) !== false) return $vt;
                        }
                }
                $t[1] = str_replace(array('-', '—', '_', '>'), '|', $t[1]);
                $splits = explode('|', $t[1]);
                $l = 0;
                foreach ($splits as $tp) {
                        $len = strlen($tp);
                        if ($l < $len) {
                                $l = $len;
                                $tt = $tp;
                        }
                }
                $tt = trim(str_replace('"', '"', cn_substr(html2text($tt), $maxlen)));
                return $tt;
        }
        return false;
}
/**
 *  HTML转换为文本
 *
 * @param    string  $str 需要转换的字符串
 * @param    string  $r   如果$r=0直接返回内容,否则需要使用反斜线引用字符串
 * @return   string
 */
function html2text($str,$r=0) {
        $str = preg_replace("/<sty(.*)\/style>|<scr(.*)\/script>|<!--(.*)-->/isU", "", $str);
        $alltext = "";
        $start = 1;
        for($i = 0;$i < strlen($str);$i++) {
                if ($start == 0 && $str[$i] == ">") {
                        $start = 1;
                } else if ($start == 1) {
                        if ($str[$i] == "<") {
                                $start = 0;
                                $alltext .= " ";
                        } else if (ord($str[$i]) > 31) {
                                $alltext .= $str[$i];
                        }
                }
        }
        $alltext = str_replace(" ", " ", $alltext);
        $alltext = preg_replace("/&([^;&]*)(;|&)/", "", $alltext);
        $alltext = preg_replace("/[ ]+/s", " ", $alltext);
        if($r==0){
                return $alltext;
        }else {
                $r = SpHtml2Text(stripslashes($alltext));
                return addslashes($r);
        }
}

/**
 * utf-8中文截取,单字节截取模式
 *
 * @access public
 * @param string $str 需要截取的字符串
 * @param int $slen 截取的长度
 * @param int $startdd 开始标记处
 * @return string
 */

function cn_substr($str, $length, $start = 0) {
        if (strlen($str) < $start + 1) {
                return '';
        }
        preg_match_all("/./su", $str, $ar);
        $str = '';
        $tstr = '';
        for($i = 0; isset($ar[0][$i]); $i++) {
                if (strlen($tstr) < $start) {
                        $tstr .= $ar[0][$i];
                } else {
                        if (strlen($str) < $length + strlen($ar[0][$i])) {
                                $str .= $ar[0][$i];
                        } else {
                                break;
                        }
                }
        }
        return $str;
}
?>

测试使用:


<?php
//以下为测试内容
$url = 'http://enenba.com/?post=85';
$httptype = function_exists('curl_init');
if (!$httptype) {
        $html = file_get_contents($url);
} else {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $html = curl_exec($ch);
        if ($html === false) echo "cURL Error: " . curl_error($ch);
}
$r = TT($html,120);
//输出
if($r){
echo '此文章的题目为:《'.$r.'》';
}else{
echo '无信息';
}
?>

phpcms采集侠有精简版:

 


function cjx_gettt($str){
        if(preg_match("/<title>(.*)</title>/isU", $str, $t)){
        if(preg_match_all("/<h([1-3])>(.*)</h\1>/isU", $str, $ts))
            foreach($ts[2] as $vt)
                if(strpos($t[1],$vt)!==false) return $vt;
        $t[1] = str_replace(array('-','—','|'),'_',$t[1]);
                $splits = explode('_', $t[1]);
                $l = 0;
                foreach ($splits as $tp){
                        $len = strlen($tp);
                        if ($l < $len){$l = $len;$tt = $tp;}
                }
        $tt = trim(htmlspecialchars($tt));
        if(strlen($tt)>20) return $tt;
        }
        return false;
}

热点推荐