Python 3.12 文本数据提取实战:从政府工作报告中高效抓取 100+ 数字短句
Python 3.12 文本数据提取实战:从政府工作报告中高效抓取 100+ 数字短句
在数据分析的日常工作中,我们经常需要从非结构化文本中提取特定模式的信息。政府工作报告、企业年报这类文档往往包含大量有价值的数据指标,但人工提取既耗时又容易出错。本文将带你用Python 3.12构建一个健壮的文本提取流水线,不仅能解决大学编程题,更能应对真实业务场景。
1. 理解任务本质与数据特点
政府工作报告这类文档有几个显著特征:中文标点丰富、数字与文字混合表述、数据指标分散。我们需要处理的不仅是简单的字符串匹配,还要考虑中文文本处理的特殊性。
典型的数字短句可能长这样:
- "经济增长5.2%"
- "新增就业1206万人"
- "研发投入超过2.5万亿元"
这些短句中的数字可能是整数、小数、百分比,甚至包含单位符号。我们的解决方案需要兼容这些情况。
注意:中文全角标点与英文半角标点的处理是第一个技术难点,不正确的替换会导致后续分词异常。
2. 构建文本预处理流水线
2.1 标点符号标准化处理
首先需要建立一个完整的中文标点映射表。Python的str.maketrans()方法比循环替换更高效:
import re from collections import defaultdict # 构建中文标点转换表 chinese_punctuation = '"#$%&'()*+,-/:;<=>@[\]^_`{|}~⦅⦆「」、\u3000、〃〈〉《》「」『』【】〔〕〖〗〘〙〚〛〜〝〞〟〰〾〿–—‘’‛“”„‟…‧﹏﹑﹔·.!?。。' translator = str.maketrans({k: ' ' for k in chinese_punctuation}) def preprocess_text(text): """统一将中文标点替换为英文空格""" return text.translate(translator)2.2 智能分词优化
简单的split()方法在中文场景下可能不够精准。我们可以结合正则表达式实现更智能的分词:
def advanced_split(text): # 处理连续空格并保留数字单位组合 return re.sub(r'\s+', ' ', text).strip().split()3. 数字短句识别引擎
3.1 核心识别算法
判断短句是否包含数字不能简单用isdigit(),需要更复杂的模式匹配:
def contains_number(s): """判断字符串是否包含数字模式""" patterns = [ r'\d+', # 纯数字 r'\d+\.\d+', # 小数 r'\d+%', # 百分比 r'\d+\s*[万亿亿]', # 带单位 r'[一二三四五六七八九十百千万亿]+' # 中文数字 ] return any(re.search(p, s) for p in patterns)3.2 性能优化技巧
当处理大型文档时,我们可以使用生成器表达式减少内存占用:
def extract_number_sentences(text, keyword=None): processed = preprocess_text(text) words = advanced_split(processed) if keyword == '数字短句' or (keyword and keyword.isdigit()): return (w for w in words if contains_number(w)) elif keyword: matches = [w for w in words if keyword in w] return matches if matches else None return None4. 构建生产级解决方案
4.1 完整处理流程
将上述模块组合成可复用的数据处理类:
class ReportAnalyzer: def __init__(self, filepath): with open(filepath, 'r', encoding='utf-8') as f: self.raw_text = f.read() self.words = None def preprocess(self): cleaned = preprocess_text(self.raw_text) self.words = advanced_split(cleaned) return self def query(self, keyword): if not self.words: self.preprocess() if keyword == '数字短句': results = list(filter(contains_number, self.words)) print(*results, sep='\n') else: matches = [w for w in self.words if keyword in w] if matches: print(len(matches)) print(*matches, sep='\n') else: print('未找到关键词') return self4.2 使用示例
analyzer = ReportAnalyzer('government_report_2024.txt') analyzer.preprocess().query('数字短句') # 提取所有数字短句 analyzer.query('就业') # 查询包含"就业"的短句5. 高级应用与扩展
5.1 数据增强处理
提取数字后,可以进一步解析数值和单位:
def parse_number(s): # 解析数字和单位 num_match = re.search(r'(\d+\.?\d*)', s) unit_match = re.search(r'([万亿亿]元|%)', s) num = float(num_match.group(1)) if num_match else None unit = unit_match.group(0) if unit_match else '' return {'value': num, 'unit': unit, 'original': s}5.2 结果可视化
使用Pandas可以方便地进行数据分析:
import pandas as pd def analyze_report(filepath): analyzer = ReportAnalyzer(filepath).preprocess() numbers = [parse_number(w) for w in analyzer.query('数字短句')] df = pd.DataFrame(numbers).dropna() # 按单位分组统计 print(df.groupby('unit')['value'].agg(['count', 'mean', 'max']))6. 异常处理与边界情况
健壮的生产代码需要考虑各种边界情况:
def safe_extract(text): try: processed = preprocess_text(text) words = advanced_split(processed) return [parse_number(w) for w in words if contains_number(w)] except Exception as e: print(f"处理出错: {str(e)}") return []在实际项目中,我发现处理政府工作报告这类文档时,最大的挑战不是技术实现,而是文本的格式一致性。不同年份的报告可能使用不同的数字表述方式,比如"5.2%"可能写作"5.2个百分点",这时候就需要不断调整正则表达式模式来适应这些变化。
