从正则到 BERT详解Python如何判断文本是否为标题

 更新时间:2026年04月20日 08:32:56   作者:detayun  
在做文档解析(PDF/Word)或者清洗用户生成内容(UGC)时,我们经常面临一个尴尬的问题,怎么知道哪句是标题,哪句是正文,本文将从规则匹配到深度学习,层层递进,带你搞定这个问题

在做文档解析(PDF/Word)或者清洗用户生成内容(UGC)时,我们经常面临一个尴尬的问题:拿到了一堆文本,怎么知道哪句是标题,哪句是正文?

比如这段数据:

“2023年全球AI市场规模达到1000亿美元。根据最新报告,增长主要来自生成式AI。”

哪一句是标题?人类一眼就能看出来,但机器怎么判断?今天我们就从规则匹配深度学习,层层递进,带你搞定这个问题。

方案一:基于启发式规则(Heuristics)—— 简单粗暴,无需训练

对于格式比较规范的文本(如新闻、Markdown、简单的爬虫数据),我们可以利用标题的统计学特征来写规则。

标题的常见特征

  1. 长度较短:通常在 10-30 个字符之间。
  2. 首字母大写:英文标题通常首词大写(Title Case)。
  3. 结尾无标点:很多标题结尾没有句号(。或.),或者只有感叹号/问号。
  4. 包含数字/年份:如 “2023年…”、“Top 10…”。
  5. 词汇特征:包含 “揭秘”、“指南”、“报告”、“分析” 等高频标题词。

代码实现

import re

def is_title_heuristic(text, threshold=30):
    """
    基于启发式规则判断是否为标题
    """
    # 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年中国经济发展报告",      # 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 '是正文'}")

优点:速度极快,无需数据,逻辑可解释。

缺点:误报率高(比如英文句子首字母大写会被误判),对口语化标题无效。

方案二:基于传统机器学习(TF-IDF + 分类器)—— 中等精度

如果我们有一批已经标注好的数据(哪些是标题,哪些是正文),就可以用机器学习来找规律。标题和正文的词频分布是不同的:

  • 标题:名词、动词多,虚词少,信息密度大。
  • 正文:连词、介词、代词多,句子结构完整。

我们可以用 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),
    ("如何优雅地删除 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)}")

优点:比纯规则准确,能学习到隐含模式。

缺点:需要标注数据,特征工程(尤其是中文分词)比较麻烦。

方案三:基于深度学习(BERT/Transformers)—— 工业级方案

如果你追求最高准确率,或者需要理解语义(比如区分“这是一个标题”这句话本身和真正的标题),必须上预训练模型。

我们可以使用 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年行业研究报告",
    "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发展趋势"))  # True (高相似度)
print(is_title_bert("今天中午吃了面条"))  # False (低相似度)
print(is_title_bert("Python 编程教程"))   # True

进阶玩法:如果你有数据,可以使用 BERT 微调。

  1. 准备正负样本各 5000+ 条。
  2. 使用 bert-base-chinese
  3. 在最后一层加一个 Linear Layer 做二分类。
  4. 训练 2-3 个 Epoch,准确率通常能达到 95%+。

优点:准确率极高,能理解语义,不需要复杂的特征工程。

缺点:计算资源消耗大(需要 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"发现标题: {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

总结与选型建议

场景推荐方案准确度性能难度
简单爬虫/日志清洗方案一:启发式规则⭐⭐⭐极快
聊天记录/短文本分类方案二:TF-IDF + LR⭐⭐⭐⭐⭐⭐
新闻/文章/专业文档方案三:BERT/Deep Learning⭐⭐⭐⭐⭐⭐⭐⭐⭐
网页/Markdown文件方案四:标签解析⭐⭐⭐⭐⭐⭐⭐

我的建议

  1. 先看来源:如果是 HTML,直接用 BeautifulSoup 抓 <h1>-<h6>,别用 NLP 模型杀鸡用牛刀。
  2. 混合使用:先用规则过滤掉明显的正文(如以句号结尾、长度超过 50),再用轻量级模型(如 FastText 或 Logistic Regression)对疑似标题进行二次确认。
  3. 不要迷信 AI:对于“今天天气真好”这种短句,AI 也很难判断它是标题还是正文,必须结合上下文(比如它是不是独立成行、字体是否加粗)。

到此这篇关于从正则到 BERT详解Python如何判断文本是否为标题的文章就介绍到这了,更多相关Python判断文本是否为标题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 探索Python Slice函数灵活而强大的序列切片技术

    探索Python Slice函数灵活而强大的序列切片技术

    Python中的Slice函数是一种强大且灵活的序列切片技术,用于从字符串、列表、元组等序列类型中提取子集,本文将深入研究Slice函数的功能和用法,提供详细的示例代码和解释,帮助读者更全面地了解和应用这一功能
    2024-01-01
  • 对Python中Iterator和Iterable的区别详解

    对Python中Iterator和Iterable的区别详解

    今天小编就为大家分享一篇对Python中Iterator和Iterable的区别详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • Python+wxPython实现文件内容搜索工具

    Python+wxPython实现文件内容搜索工具

    在本篇文章中,我们将介绍如何使用 wxPython 库创建一个简单的文件搜索工具,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-08-08
  • python实现web方式logview的方法

    python实现web方式logview的方法

    这篇文章主要介绍了python实现web方式logview的方法,涉及Python基于web模块操作Linux命令的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • Python基于matplotlib绘制栈式直方图的方法示例

    Python基于matplotlib绘制栈式直方图的方法示例

    这篇文章主要介绍了Python基于matplotlib绘制栈式直方图的方法,涉及Python使用matplotlib进行图形绘制的相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • flask框架渲染Jinja模板与传入模板变量操作详解

    flask框架渲染Jinja模板与传入模板变量操作详解

    这篇文章主要介绍了flask框架渲染Jinja模板与传入模板变量操作,结合实例形式详细分析了flask框架模板相关原理、模板渲染、传入参数等相关操作技巧与注意事项,需要的朋友可以参考下
    2020-01-01
  • python通过pil模块获得图片exif信息的方法

    python通过pil模块获得图片exif信息的方法

    这篇文章主要介绍了python通过pil模块获得图片exif信息的方法,实例分析了Python中pil模块的使用技巧,非常具有实用价值,需要的朋友可以参考下
    2015-03-03
  • Python编写简化版的文字冒险游戏的实例代码

    Python编写简化版的文字冒险游戏的实例代码

    Python编写简化版的文字冒险游戏:迷失的宝藏,这个文字冒险游戏包含了游戏开发的基本要素:游戏状态管理、玩家输入处理、游戏逻辑和循环,通过扩展游戏的内容和功能,可以制作出更复杂、更有趣的游戏,希望这个实例代码能够激发你对游戏编程的兴趣和创造力!
    2024-05-05
  • Python的进制转换和ASCLL转换你了解吗

    Python的进制转换和ASCLL转换你了解吗

    这篇文章主要为大家详细介绍了Python的进制转换和ASCLL转换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • python数字图像处理图像的绘制详解

    python数字图像处理图像的绘制详解

    这篇文章主要为大家介绍了python数字图像处理图像的绘制示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06

最新评论