Python 如何判断文本是否是标题?从正则到 BERT 的全攻略

张开发
2026/4/17 19:27:26 15 分钟阅读

分享文章

Python 如何判断文本是否是标题?从正则到 BERT 的全攻略
在做网页爬虫、**文档解析PDF/Word或者清洗用户生成内容UGC**时我们经常面临一个尴尬的问题拿到了一堆文本怎么知道哪句是标题哪句是正文比如这段数据“2023年全球AI市场规模达到1000亿美元。根据最新报告增长主要来自生成式AI。”哪一句是标题人类一眼就能看出来但机器怎么判断今天我们就从规则匹配到深度学习层层递进带你搞定这个问题。方案一基于启发式规则Heuristics—— 简单粗暴无需训练对于格式比较规范的文本如新闻、Markdown、简单的爬虫数据我们可以利用标题的统计学特征来写规则。标题的常见特征长度较短通常在 10-30 个字符之间。首字母大写英文标题通常首词大写Title Case。结尾无标点很多标题结尾没有句号。或.或者只有感叹号/问号。包含数字/年份如 “2023年…”、“Top 10…”。词汇特征包含 “揭秘”、“指南”、“报告”、“分析” 等高频标题词。代码实现importredefis_title_heuristic(text,threshold30): 基于启发式规则判断是否为标题 # 1. 长度检测太长肯定不是标题太短可能是废话iflen(text)thresholdorlen(text)4:returnFalse# 2. 结尾标点检测如果以句号、逗号结尾大概率是正文iftext.endswith((。,,,,.,;,)):returnFalse# 3. 数字/年份特征包含年份或列表数字如 1. 2. 3.ifre.search(r\d{4}年|第[\d一二三四五六七八九十]章|Top \d,text):returnTrue# 4. 英文 Title Case 检测 (简单版)# 检查首字母是否大写且长度大于1iftext[0].isupper()andlen(text)1:# 简单的概率判断如果大写字母占比过高全大写标题除外可能是标题upper_ratiosum(1forcintextifc.isupper())/len(text)if0.2upper_ratio0.8:returnTrue# 5. 关键词匹配title_keywords[报告,指南,揭秘,分析,研究,新闻,Review,Guide,Analysis]ifany(keywordintextforkeywordintitle_keywords):returnTruereturnFalse# 测试test_cases[2023年中国经济发展报告,# True这是一个普通的句子。,# FalseHow to Learn Python in 30 Days,# True今天天气不错,# False (太短且无特征)揭秘DeepSeek 的核心技术# True]fortintest_cases:print(f{t:30}-{是标题ifis_title_heuristic(t)else是正文})优点速度极快无需数据逻辑可解释。缺点误报率高比如英文句子首字母大写会被误判对口语化标题无效。方案二基于传统机器学习TF-IDF 分类器—— 中等精度如果我们有一批已经标注好的数据哪些是标题哪些是正文就可以用机器学习来找规律。标题和正文的词频分布是不同的标题名词、动词多虚词少信息密度大。正文连词、介词、代词多句子结构完整。我们可以用TF-IDF提取特征用逻辑回归Logistic Regression或SVM分类。代码实现 (使用 scikit-learn)fromsklearn.feature_extraction.textimportTfidfVectorizerfromsklearn.linear_modelimportLogisticRegressionfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportaccuracy_scoreimportjoblib# 1. 模拟数据集 (实际应用中需要几千条真实数据)data[(深度学习入门教程,1),(根据最新的统计数据显示,0),(2024年投资策略分析,1),(他昨天去了公园玩得很开心。,0),(Python 编程最佳实践,1),(这是一段用于测试的正文内容。,0),(如何优雅地删除 Emoji,1),(在自然语言处理中数据清洗非常重要。,0),]texts[d[0]fordindata]labels[d[1]fordindata]# 1标题, 0正文# 2. 特征工程TF-IDF (注意中文需要先分词这里为了演示用 char level)vectorizerTfidfVectorizer(analyzerchar,ngram_range(2,3))# 使用字符级N-gram捕捉结构Xvectorizer.fit_transform(texts)# 3. 训练模型X_train,X_test,y_train,y_testtrain_test_split(X,labels,test_size0.2,random_state42)clfLogisticRegression()clf.fit(X_train,y_train)# 4. 预测defpredict_is_title(text):vecvectorizer.transform([text])returnclf.predict(vec)[0]1# 测试new_text2024年宏观经济展望print(f{new_text} 是标题吗?{predict_is_title(new_text)})new_text_2我们需要进一步观察市场的反应。print(f{new_text_2} 是标题吗?{predict_is_title(new_text_2)})优点比纯规则准确能学习到隐含模式。缺点需要标注数据特征工程尤其是中文分词比较麻烦。方案三基于深度学习BERT/Transformers—— 工业级方案如果你追求最高准确率或者需要理解语义比如区分“这是一个标题”这句话本身和真正的标题必须上预训练模型。我们可以使用 Hugging Face 的transformers库加载一个中文文本分类模型或者自己微调一个。核心思路将问题转化为二分类任务Binary Classification。输入文本输出[标题, 正文]的概率。代码实现 (使用 Transformers Pipeline)首先安装库pipinstalltransformers torch使用现成的情感分析模型改造成“标题检测”比较麻烦最好是 fine-tune 一个。但如果只是做 Demo我们可以用零样本分类Zero-shot classification或者直接用一个通用的文本匹配模型。这里展示一个更实用的思路利用句子向量相似度。fromsentence_transformersimportSentenceTransformer,util# 加载预训练模型 (中文)modelSentenceTransformer(paraphrase-multilingual-MiniLM-L12-v2)# 定义一些“典型标题”的模板title_templates[2023年行业研究报告,Python 入门指南,如何高效学习,深度学习技术分析,新闻早知道]# 计算模板的嵌入向量template_embeddingsmodel.encode(title_templates)defis_title_bert(text,threshold0.6): 通过计算文本与标题模板的语义相似度来判断 text_embeddingmodel.encode(text)# 计算与所有模板的最大相似度max_score0fortpl_embintemplate_embeddings:scoreutil.cos_sim(text_embedding,tpl_emb).item()ifscoremax_score:max_scorescorereturnmax_scorethreshold# 测试print(is_title_bert(2024年AI发展趋势))# True (高相似度)print(is_title_bert(今天中午吃了面条))# False (低相似度)print(is_title_bert(Python 编程教程))# True进阶玩法如果你有数据可以使用 BERT 微调。准备正负样本各 5000 条。使用bert-base-chinese。在最后一层加一个 Linear Layer 做二分类。训练 2-3 个 Epoch准确率通常能达到 95%。优点准确率极高能理解语义不需要复杂的特征工程。缺点计算资源消耗大需要 GPU 训练CPU 推理也较慢模型体积大。方案四基于上下文结构HTML/Markdown 特有如果你处理的是网页或 Markdown 文件不要只看文本内容要看标签这是最准确的方法。1. HTML 解析 (BeautifulSoup)frombs4importBeautifulSoup html h1这是主标题/h1 p这是正文段落。/p h2这是副标题/h2 div classcontent这里也是正文/div soupBeautifulSoup(html,html.parser)fortaginsoup.find_all([h1,h2,h3,h4,h5,h6]):print(f发现标题:{tag.get_text()}(层级:{tag.name}))2. Markdown 解析检查行首是否有#、##等符号或者是否有下划线。importredefis_markdown_title(line):# 匹配 # 标题ifre.match(r^#{1,6}\s,line):returnTrue# 匹配 Setext 风格标题 (下划线)ifre.match(r^$|^--$,line):returnTruereturnFalse总结与选型建议场景推荐方案准确度性能难度简单爬虫/日志清洗方案一启发式规则⭐⭐⭐极快⭐聊天记录/短文本分类方案二TF-IDF LR⭐⭐⭐⭐快⭐⭐新闻/文章/专业文档方案三BERT/Deep Learning⭐⭐⭐⭐⭐慢⭐⭐⭐⭐网页/Markdown文件方案四标签解析⭐⭐⭐⭐⭐快⭐⭐我的建议先看来源如果是 HTML直接用 BeautifulSoup 抓h1-h6别用 NLP 模型杀鸡用牛刀。混合使用先用规则过滤掉明显的正文如以句号结尾、长度超过 50再用轻量级模型如 FastText 或 Logistic Regression对疑似标题进行二次确认。不要迷信 AI对于“今天天气真好”这种短句AI 也很难判断它是标题还是正文必须结合上下文比如它是不是独立成行、字体是否加粗。希望这篇文章能帮你在 Python 中精准识别标题如果你有更好的特征工程技巧欢迎留言讨论。博客标签Python, NLP, 文本分类, 标题识别, 机器学习

更多文章