首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 從文章內容智能提取標題:基於標點符號與長度的啟發式算法

     編輯:PHP 相關知識

核心邏輯解析

從純文本內容中提取潛在標題,利用中文標點符號作為邊界,篩選長度適中(5-30 字)的片段,隨機選取一個作為標題。

完善後的代碼實現

<?php
/**
 * 從內容中智能提取標題
 * @param string $content 文章內容(已去除 HTML 標籤)
 * @param int $minLen 最小長度
 * @param int $maxLen 最大長度
 * @return string|null 提取的標題或 null
 */
function extractTitleFromContent($content, $minLen = 5, $maxLen = 30) {
    // 1. 全角轉半角(統一標點處理)
    $content = fullWidthToHalfWidth($content);
    
    // 2. 移除 HTML 標籤(防干擾)
    $content = strip_tags($content);
    
    // 3. 正則匹配:標點符號包裹的文本片段
    // [\x{3000}-\x{303F}\x{FF00}-\x{FFEF}] 覆蓋中日韓標點
    // 也可使用 \p{P} 匹配所有 Unicode 標點(需 u 修飾符)
    $pattern = '/[\p{P}\p{S}]([^\p{P}\p{S}]{' . $minLen . ',' . $maxLen . '})[\p{P}\p{S}]/u';
    
    if (preg_match_all($pattern, $content, $matches)) {
        // $matches[1] 包含所有捕獲組(不含邊界標點)
        $candidates = $matches[1];
        
        // 4. 可選:過濾低質量候選(純數字、重複字符、過多標點等)
        $candidates = array_filter($candidates, function($title) {
            // 過濾純數字
            if (preg_match('/^[\d\s\.\,\%\+\-\*\/]+$/', $title)) return false;
            // 過濾重複字符佔比過高
            $uniqueChars = count(array_unique(mb_str_split($title)));
            if ($uniqueChars / mb_strlen($title) < 0.3) return false;
            return true;
        });
        
        if (!empty($candidates)) {
            // 5. 隨機選取(或按位置權重:首段優先)
            return $candidates[array_rand($candidates)];
        }
    }
    
    return null;
}

/**
 * 全角轉半角(優化版:使用映射表而非巨大數組)
 */
function fullWidthToHalfWidth($str) {
    static $map = null;
    if ($map === null) {
        $map = [];
        // 數字 0-9 → 0-9
        for ($i = 0; $i <= 9; $i++) {
            $map[mb_chr(0xFF10 + $i)] = (string)$i;
        }
        // 大寫 A-Z → A-Z
        for ($i = 0; $i < 26; $i++) {
            $map[mb_chr(0xFF21 + $i)] = chr(0x41 + $i);
        }
        // 小寫 a-z → a-z
        for ($i = 0; $i < 26; $i++) {
            $map[mb_chr(0xFF41 + $i)] = chr(0x61 + $i);
        }
        // 常用標點
        $punctMap = [
            '(' => '(', ')' => ')', '〔' => '[', '〕' => ']', '【' => '[', '】' => ']',
            '〖' => '[', '〗' => ']', '"' => '"', '"' => '"', ''' => "'", ''' => "'",
            '{' => '{', '}' => '}', '《' => '<', '》' => '>',
            '%' => '%', '+' => '+', '-' => '-', '~' => '~',
            ':' => ':', '。' => '.', '、' => ',', ',' => ',', ';' => ';',
            '?' => '?', '!' => '!', '…' => '...', '‖' => '|',
            '"' => '"', ''' => "'", '|' => '|', '〃' => '"',
            ' ' => ' ', '$' => '$', '@' => '@', '#' => '#', '^' => '^', '&' => '&', '*' => '*',
        ];
        $map = array_merge($map, $punctMap);
    }
    return strtr($str, $map);
}

// 測試
$content = "這是一段測試內容。標題候選一:這是一個不錯的標題!另一個候選:PHP 開發技巧分享。結束。";
$title = extractTitleFromContent($content);
echo "提取標題: " . ($title ?? '無') . "\n";
// 可能輸出: "這是一個不錯的標題" 或 "PHP 開發技巧分享"

算法優化方向

維度當前方案進階方案
邊界識別標點符號結合 NLP 分句(如 jieba-php、Stanford CoreNLP)
候選評分隨機選取TF-IDF、TextRank、位置權重(首段加分)、關鍵詞覆蓋率
質量過濾簡單正則語言模型困惑度、標題分類器(FastText/BERT)
多語言中文標點Unicode 通用標點屬性 \p{P} + 語言檢測

生產環境建議架構


內容輸入
    ↓
HTML 清洗 → 純文本
    ↓
語言檢測(中/英/日/韓...)
    ↓
分句(jieba / NLTK / Kuromoji / MeCab)
    ↓
候選生成(長度 5-50,首段優先,含關鍵詞加分)
    ↓
特徵提取(長度、位置、關鍵詞密度、標題詞特徵、實體識別)
    ↓
評分模型(LR / XGBoost / BERT fine-tune)
    ↓
Top-K 輸出 → 業務邏輯選擇或人工審核

常見問題與避坑

  • 編碼不一致:確保源內容、正則、PHP 文件均為 UTF-8,否則 u 修飾符失效
  • 標點邊界缺失:首尾無標點的片段無法匹配,需補充 ^([^\p{P}]{5,30})[\p{P}] 和 [\p{P}]([^\p{P}]{5,30})$
  • 英文內容:空格分詞而非標點,需單獨處理邏輯
  • 性能:大文本先截取前 5000 字符處理,標題通常在前段

擴展:基於 TextRank 的無監督關鍵句提取


// 依賴 composer require jieba/jieba-php
use Fukuball\Jieba\Jieba;
use Fukuball\Jieba\Finalseg;

Jieba::init();
Finalseg::init();

function textRankKeywords($text, $topK = 5) {
    $jieba = new Jieba();
    $words = $jieba->extractTags($text, $topK);
    return $words; // 返回權重排序的關鍵詞
}

// 結合標題生成:取 Top 3 關鍵詞組合或作為標題標籤
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved