PHP 抽取網頁標題並剔除不相關的seo關鍵字
情境描述:
過往我們在抽取網頁標題的時候,都會直接抽取 之間的內容. 但實際情況是這樣,例如javaeye 的一篇文章 http://www.iteye.com/news/21643 , 的內容為 "10年軟體開發教會我最重要的10件事 - 非技術 - ITeye資訊", 但實際引用中我們期望的標題應該為 "10年軟體開發教會我最重要的10件事". 所以標題後面堆砌了很多不相關的關鍵字(應該是為了 seo 吧). 所以我們希望過濾掉這些關鍵字. 有下面的方法可以參考:
1. 尋找 h1 等標籤.(分析sina news 一些網站之後, 覺得不可行,會有很多幹擾)
2. 從全文去標題後,將 之間的內容切割(按 _ | -)為 a1,a2,a3,a4,然後從最長的片語a3開始從全文尋找. 如果尋找成功,那麼開始向左邊迭代查詢 a2,a1,直到查詢失敗為止 。左側失敗後,再繼續向右迭代,同理. (這裡我採用的是這種方法)
* @date: 2011-06-18 * Description: 給定一個網頁內容,提取網頁的標題. 提取的標題不包括 seo 關鍵字. * e.g: 一篇新聞標題的從直接抽取結果為 "大學英語四六級本周六開考 909萬人蔘考_新浪教育_新浪網", * 但我們希望的結果是:"大學英語四六級本周六開考 909萬人蔘考". * 適用範圍: 文章最終網頁標題的提取, 不包括專題頁等. */class TitlePurify{ private $matches_preg = '[-_\s|—]'; function getTitle($contents){/*{{{*/ $preg = "/]*>([\w|\t|\r|\W]*?)<\/title>/i"; preg_match($preg, $contents, $matches); if(count($matches)<=1){ return "標題抽取失敗"; } $title = $matches[1]; return $this->trimTitle($title, $contents); }/*}}}*/ function trimMeta($contents){/*{{{*/ // 首先去除 內容, 內容. $preg = "/]*>([\w|\t|\r|\W]*?)<\/title>/i"; $contents = preg_replace($preg, '', $contents); $preg = "/]*>/i"; $contents = preg_replace($preg, '', $contents); return $contents; }/*}}}*/ // 擷取長度最長的 item?所處的index. function getMaxIndex($titles){/*{{{*/ $maxItemIndex = 0; $maxLength = 0; $loop = 0; foreach($titles as $item){ if(strlen($item)>$maxLength){ $maxLength = strlen($item); $maxItemIndex = $loop; } $loop++; } return $maxItemIndex; }/*}}}*/ function trim($title, $titles, $contents, $maxItemIndex){/*{{{*/ [email protected] : 此處可最佳化contents // 如果尋找成功. result = tempTitle. $tempTitle = $titles[$maxItemIndex]; $result = $tempTitle; $count = count($titles); // while 從當前index 向左進行迭代(直到到達第一個或者匹配失敗才中止). $leftIndex = $maxItemIndex-1; while(true && $leftIndex>=0){ // tempTitle+左一個. preg_match("/({$this->matches_preg}+{$tempTitle})/i", $title, $matches); if(count($matches)>1){ // temp 用於匹配失敗後,進行復原. $temp = $titles[$leftIndex] . $matches[1]; $tempTitle = $titles[$leftIndex] . $matches[1]; // 繼續拿著 tempTitle 去匹配. preg_match("/$tempTitle/i", $contents, $matches); // 如果尋找失敗.... if(count($matches)<1){ $tempTitle = $temp; break; }else{ $result = $tempTitle; } }else{ //?正常情況下,?不會出現該情況. break; } $leftIndex--; } // match(current[i-1].[|-].tempTitle), 如果成功, tempTitle = match 成功的值,繼續. // while 左邊失敗後, 從右邊開始. $rightIndex = $maxItemIndex+1; while(true && ($rightIndex<=$count)){ preg_match("/({$tempTitle}{$this->matches_preg}+)/i", $title, $matches); if(count($matches)>1){ // temp 用於匹配失敗後,進行復原. $temp = $matches[1] . $titles[$rightIndex]; $tempTitle = $matches[1] . $titles[$rightIndex]; // 繼續拿著 tempTitle 去匹配. preg_match("/$tempTitle/i", $contents, $matches); // 如果尋找失敗.... if(count($matches)<1){ $tempTitle = $temp; break; }else{ $result = $tempTitle; } }else{ //?正常情況下,?不會出現該情況. break; } $rightIndex++; } return $result; }/*}}}*/ function trimTitle($title, $contents){/*{{{*/ $contents = $this->trimMeta($contents); // 配置切割標題的規則. $titles = preg_split("/$this->matches_preg/i", $title); $count = count($titles); //var_dump($titles);exit; // 將當前最長的 item 從全文尋找. $maxItemIndex = $this->getMaxIndex($titles); $tempTitle = $titles[$maxItemIndex]; preg_match("/$tempTitle/i", $contents, $matches); // 如果尋找失敗.... if(count($matches)<1){ return $title; } return $this->trim($title, $titles, $contents, $maxItemIndex); }/*}}}*/}// ------------- test code ------------------------------function convertEncoding($contents){ preg_match("/charset=([\w|\-]+);?/i", $contents, $match); $charset = isset($match[1])? $match[1] : 'UTF-8'; $contents = mb_convert_encoding($contents, 'UTF-8', $charset); return $contents;}$url = 'http://china.nba.com/news/4/2011/0617/61383331/10451.html';$contents = file_get_contents($url);$contents = convertEncoding($contents);$startTime = microtime();$purify = new TitlePurify();$title = $purify->getTitle($contents);$endTime = microtime();echo "標題: $title ";echo "cost: " . ($endTime-$startTime);?>