從正則到?BERT詳解Python如何判斷文本是否為標題
在做文檔解析(PDF/Word)或者清洗用戶生成內容(UGC)時,我們經常面臨一個尷尬的問題:拿到了一堆文本,怎么知道哪句是標題,哪句是正文?
比如這段數據:
“2023年全球AI市場規(guī)模達到1000億美元。根據最新報告,增長主要來自生成式AI。”
哪一句是標題?人類一眼就能看出來,但機器怎么判斷?今天我們就從規(guī)則匹配到深度學習,層層遞進,帶你搞定這個問題。
方案一:基于啟發(fā)式規(guī)則(Heuristics)—— 簡單粗暴,無需訓練
對于格式比較規(guī)范的文本(如新聞、Markdown、簡單的爬蟲數據),我們可以利用標題的統計學特征來寫規(guī)則。
標題的常見特征
- 長度較短:通常在 10-30 個字符之間。
- 首字母大寫:英文標題通常首詞大寫(Title Case)。
- 結尾無標點:很多標題結尾沒有句號(。或.),或者只有感嘆號/問號。
- 包含數字/年份:如 “2023年…”、“Top 10…”。
- 詞匯特征:包含 “揭秘”、“指南”、“報告”、“分析” 等高頻標題詞。
代碼實現
import re
def is_title_heuristic(text, threshold=30):
"""
基于啟發(fā)式規(guī)則判斷是否為標題
"""
# 1. 長度檢測:太長肯定不是標題,太短可能是廢話
if len(text) > threshold or len(text) < 4:
return False
# 2. 結尾標點檢測:如果以句號、逗號結尾,大概率是正文
if text.endswith(('。', '.', ',', '.', ';', ';')):
return False
# 3. 數字/年份特征:包含年份或列表數字(如 1. 2. 3.)
if re.search(r'\d{4}年|第[\d一二三四五六七八九十]+章|Top \d+', text):
return True
# 4. 英文 Title Case 檢測 (簡單版)
# 檢查首字母是否大寫,且長度大于1
if text[0].isupper() and len(text) > 1:
# 簡單的概率判斷:如果大寫字母占比過高(全大寫標題除外),可能是標題
upper_ratio = sum(1 for c in text if c.isupper()) / len(text)
if 0.2 < upper_ratio < 0.8:
return True
# 5. 關鍵詞匹配
title_keywords = ['報告', '指南', '揭秘', '分析', '研究', '新聞', 'Review', 'Guide', 'Analysis']
if any(keyword in text for keyword in title_keywords):
return True
return False
# 測試
test_cases = [
"2023年中國經濟發(fā)展報告", # True
"這是一個普通的句子。", # False
"How to Learn Python in 30 Days", # True
"今天天氣不錯", # False (太短且無特征)
"揭秘:DeepSeek 的核心技術" # True
]
for t in test_cases:
print(f"{t:30} -> {'是標題' if is_title_heuristic(t) else '是正文'}")
優(yōu)點:速度極快,無需數據,邏輯可解釋。
缺點:誤報率高(比如英文句子首字母大寫會被誤判),對口語化標題無效。
方案二:基于傳統機器學習(TF-IDF + 分類器)—— 中等精度
如果我們有一批已經標注好的數據(哪些是標題,哪些是正文),就可以用機器學習來找規(guī)律。標題和正文的詞頻分布是不同的:
- 標題:名詞、動詞多,虛詞少,信息密度大。
- 正文:連詞、介詞、代詞多,句子結構完整。
我們可以用 TF-IDF 提取特征,用 邏輯回歸(Logistic Regression) 或 SVM 分類。
代碼實現 (使用 scikit-learn)
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import joblib
# 1. 模擬數據集 (實際應用中需要幾千條真實數據)
data = [
("深度學習入門教程", 1),
("根據最新的統計數據顯示", 0),
("2024年投資策略分析", 1),
("他昨天去了公園,玩得很開心。", 0),
("Python 編程最佳實踐", 1),
("這是一段用于測試的正文內容。", 0),
("如何優(yōu)雅地刪除 Emoji", 1),
("在自然語言處理中,數據清洗非常重要。", 0),
]
texts = [d[0] for d in data]
labels = [d[1] for d in data] # 1=標題, 0=正文
# 2. 特征工程:TF-IDF (注意:中文需要先分詞,這里為了演示用 char level)
vectorizer = TfidfVectorizer(analyzer='char', ngram_range=(2, 3)) # 使用字符級N-gram捕捉結構
X = vectorizer.fit_transform(texts)
# 3. 訓練模型
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.2, random_state=42)
clf = LogisticRegression()
clf.fit(X_train, y_train)
# 4. 預測
def predict_is_title(text):
vec = vectorizer.transform([text])
return clf.predict(vec)[0] == 1
# 測試
new_text = "2024年宏觀經濟展望"
print(f"'{new_text}' 是標題嗎? {predict_is_title(new_text)}")
new_text_2 = "我們需要進一步觀察市場的反應。"
print(f"'{new_text_2}' 是標題嗎? {predict_is_title(new_text_2)}")
優(yōu)點:比純規(guī)則準確,能學習到隱含模式。
缺點:需要標注數據,特征工程(尤其是中文分詞)比較麻煩。
方案三:基于深度學習(BERT/Transformers)—— 工業(yè)級方案
如果你追求最高準確率,或者需要理解語義(比如區(qū)分“這是一個標題”這句話本身和真正的標題),必須上預訓練模型。
我們可以使用 Hugging Face 的 transformers 庫,加載一個中文文本分類模型(或者自己微調一個)。
核心思路
將問題轉化為二分類任務(Binary Classification)。輸入文本,輸出 [標題, 正文] 的概率。
代碼實現 (使用 Transformers Pipeline)
首先安裝庫:
pip install transformers torch
使用現成的情感分析模型改造成“標題檢測”比較麻煩,最好是 fine-tune 一個。但如果只是做 Demo,我們可以用零樣本分類(Zero-shot classification)或者直接用一個通用的文本匹配模型。
這里展示一個更實用的思路:利用句子向量相似度。
from sentence_transformers import SentenceTransformer, util
# 加載預訓練模型 (中文)
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
# 定義一些“典型標題”的模板
title_templates = [
"2023年行業(yè)研究報告",
"Python 入門指南",
"如何高效學習",
"深度學習技術分析",
"新聞早知道"
]
# 計算模板的嵌入向量
template_embeddings = model.encode(title_templates)
def is_title_bert(text, threshold=0.6):
"""
通過計算文本與標題模板的語義相似度來判斷
"""
text_embedding = model.encode(text)
# 計算與所有模板的最大相似度
max_score = 0
for tpl_emb in template_embeddings:
score = util.cos_sim(text_embedding, tpl_emb).item()
if score > max_score:
max_score = score
return max_score > threshold
# 測試
print(is_title_bert("2024年AI發(fā)展趨勢")) # True (高相似度)
print(is_title_bert("今天中午吃了面條")) # False (低相似度)
print(is_title_bert("Python 編程教程")) # True
進階玩法:如果你有數據,可以使用 BERT 微調。
- 準備正負樣本各 5000+ 條。
- 使用
bert-base-chinese。 - 在最后一層加一個 Linear Layer 做二分類。
- 訓練 2-3 個 Epoch,準確率通常能達到 95%+。
優(yōu)點:準確率極高,能理解語義,不需要復雜的特征工程。
缺點:計算資源消耗大(需要 GPU 訓練,CPU 推理也較慢),模型體積大。
方案四:基于上下文結構(HTML/Markdown 特有)
如果你處理的是網頁或 Markdown 文件,不要只看文本內容,要看標簽!這是最準確的方法。
1. HTML 解析 (BeautifulSoup)
from bs4 import BeautifulSoup
html = """
<h1>這是主標題</h1>
<p>這是正文段落。</p>
<h2>這是副標題</h2>
<div class="content">這里也是正文</div>
"""
soup = BeautifulSoup(html, 'html.parser')
for tag in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']):
print(f"發(fā)現標題: {tag.get_text()} (層級: {tag.name})")
2. Markdown 解析
檢查行首是否有 #、## 等符號,或者是否有下劃線 ===。
import re
def is_markdown_title(line):
# 匹配 # 標題
if re.match(r'^#{1,6}\s+', line):
return True
# 匹配 Setext 風格標題 (下劃線)
if re.match(r'^=+$|^--+$', line):
return True
return False
總結與選型建議
| 場景 | 推薦方案 | 準確度 | 性能 | 難度 |
|---|---|---|---|---|
| 簡單爬蟲/日志清洗 | 方案一:啟發(fā)式規(guī)則 | ??? | 極快 | ? |
| 聊天記錄/短文本分類 | 方案二:TF-IDF + LR | ???? | 快 | ?? |
| 新聞/文章/專業(yè)文檔 | 方案三:BERT/Deep Learning | ????? | 慢 | ???? |
| 網頁/Markdown文件 | 方案四:標簽解析 | ????? | 快 | ?? |
我的建議
- 先看來源:如果是 HTML,直接用 BeautifulSoup 抓
<h1>-<h6>,別用 NLP 模型殺雞用牛刀。 - 混合使用:先用規(guī)則過濾掉明顯的正文(如以句號結尾、長度超過 50),再用輕量級模型(如 FastText 或 Logistic Regression)對疑似標題進行二次確認。
- 不要迷信 AI:對于“今天天氣真好”這種短句,AI 也很難判斷它是標題還是正文,必須結合上下文(比如它是不是獨立成行、字體是否加粗)。
到此這篇關于從正則到 BERT詳解Python如何判斷文本是否為標題的文章就介紹到這了,更多相關Python判斷文本是否為標題內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python3導入CSV文件的實例(跟Python2有些許的不同)
今天小編就為大家分享一篇Python3導入CSV文件的實例(跟Python2有些許的不同),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06

