在日常工作中,我们经常需要处理各种文档和文章内容。无论是数据分析报告、技术文档整理,还是内容管理系统开发,文档处理都是绕不开的基础需求。Python凭借其丰富的文本处理库和简洁的语法,成为了文档处理领域的首选工具。
我最近完成了一个文档处理系统的开发,主要解决以下几个痛点:
这个系统已经在公司内部运行了3个月,处理了超过5000份文档,准确率达到98%以上。下面我将分享实现过程中的核心技术和经验。
经过多次测试和比较,我最终确定了以下技术栈:
python复制# 文档解析
import pdfplumber # PDF解析
import docx # Word文档处理
import python-docx # Word文档生成
# 文本处理
import re # 正则表达式
import nltk # 自然语言处理
from bs4 import BeautifulSoup # HTML解析
# 高级功能
from sumy.parsers.plaintext import PlaintextParser # 摘要生成
from sumy.nlp.tokenizers import Tokenizer
from sumy.summarizers.lsa import LsaSummarizer
选择这些库的主要考虑因素:
整个系统采用模块化设计,主要分为四个层次:
这种架构的优点是:
python复制def extract_text_from_pdf(pdf_path):
"""
从PDF提取文本内容
:param pdf_path: PDF文件路径
:return: 提取的文本内容
"""
text = ""
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
# 提取文本
page_text = page.extract_text()
if page_text:
text += page_text + "\n"
# 提取表格
tables = page.extract_tables()
for table in tables:
text += "\n表格内容:\n"
for row in table:
text += "|".join(str(cell) for cell in row) + "\n"
return text
注意:pdfplumber在处理扫描版PDF时需要配合OCR工具,推荐使用pytesseract
python复制def read_docx(file_path):
"""
读取Word文档内容
:param file_path: Word文件路径
:return: 文档文本内容
"""
doc = docx.Document(file_path)
full_text = []
for para in doc.paragraphs:
full_text.append(para.text)
return '\n'.join(full_text)
原始文档提取后通常包含大量噪音,需要进行清洗:
python复制def clean_text(text):
"""
文本清洗函数
:param text: 原始文本
:return: 清洗后的文本
"""
# 去除特殊字符
text = re.sub(r'[^\w\s]', '', text)
# 统一换行符
text = text.replace('\r\n', '\n').replace('\r', '\n')
# 去除多余空格
text = ' '.join(text.split())
# 转换为小写
text = text.lower()
return text
使用正则表达式提取特定信息:
python复制def extract_emails(text):
"""
从文本中提取邮箱地址
:param text: 输入文本
:return: 邮箱地址列表
"""
pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
return re.findall(pattern, text)
def extract_phone_numbers(text):
"""
从文本中提取电话号码
:param text: 输入文本
:return: 电话号码列表
"""
pattern = r'(\d{3}[-\.\s]??\d{3}[-\.\s]??\d{4}|\(\d{3}\)\s*\d{3}[-\.\s]??\d{4}|\d{3}[-\.\s]??\d{4})'
return re.findall(pattern, text)
使用LSA算法生成文档摘要:
python复制def generate_summary(text, sentences_count=3):
"""
生成文本摘要
:param text: 输入文本
:param sentences_count: 摘要句子数量
:return: 生成的摘要
"""
parser = PlaintextParser.from_string(text, Tokenizer("english"))
summarizer = LsaSummarizer()
summary = summarizer(parser.document, sentences_count)
return ' '.join(str(sentence) for sentence in summary)
当处理大型文档时(超过100页),内存管理变得很重要:
python复制def process_large_pdf(pdf_path, chunk_size=10):
"""
分块处理大型PDF文档
:param pdf_path: PDF文件路径
:param chunk_size: 每次处理的页数
:return: 生成器,逐块返回文本
"""
with pdfplumber.open(pdf_path) as pdf:
total_pages = len(pdf.pages)
for i in range(0, total_pages, chunk_size):
chunk_text = ""
end_page = min(i + chunk_size, total_pages)
for page in pdf.pages[i:end_page]:
chunk_text += page.extract_text() + "\n"
yield chunk_text
对于批量文档处理,可以使用多线程提高效率:
python复制from concurrent.futures import ThreadPoolExecutor
def batch_process_files(file_paths, process_func, max_workers=4):
"""
批量处理文件
:param file_paths: 文件路径列表
:param process_func: 处理函数
:param max_workers: 最大线程数
:return: 处理结果列表
"""
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(process_func, file_paths))
return results
问题1:PDF提取的文本乱码
python复制with pdfplumber.open(pdf_path, encoding='utf-8') as pdf:
...
问题2:Word文档样式丢失
python复制from docx import Document
def read_docx_with_styles(file_path):
doc = Document(file_path)
styled_text = []
for para in doc.paragraphs:
style = para.style.name
text = para.text
styled_text.append(f"[{style}]{text}")
return '\n'.join(styled_text)
问题3:摘要质量不稳定
python复制from sumy.summarizers.lex_rank import LexRankSummarizer
def generate_lexrank_summary(text, sentences_count=3):
parser = PlaintextParser.from_string(text, Tokenizer("english"))
summarizer = LexRankSummarizer()
summary = summarizer(parser.document, sentences_count)
return ' '.join(str(sentence) for sentence in summary)
python复制from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
def calculate_similarity(text1, text2):
"""
计算两段文本的相似度
:param text1: 文本1
:param text2: 文本2
:return: 相似度分数(0-1)
"""
vectorizer = TfidfVectorizer()
tfidf = vectorizer.fit_transform([text1, text2])
return cosine_similarity(tfidf[0:1], tfidf[1:2])[0][0]
python复制from sklearn.feature_extraction.text import TfidfVectorizer
def extract_keywords(text, top_n=10):
"""
提取文本关键词
:param text: 输入文本
:param top_n: 返回关键词数量
:return: 关键词列表
"""
vectorizer = TfidfVectorizer(stop_words='english')
tfidf_matrix = vectorizer.fit_transform([text])
feature_array = vectorizer.get_feature_names_out()
tfidf_sorting = np.argsort(tfidf_matrix.toarray()).flatten()[::-1]
top_keywords = [feature_array[i] for i in tfidf_sorting[:top_n]]
return top_keywords
案例1:合同管理系统
案例2:新闻聚合平台
案例3:学术论文分析
建议添加日志和性能监控:
python复制import logging
import time
logging.basicConfig(filename='document_processing.log', level=logging.INFO)
def log_processing_time(func):
"""
记录处理时间的装饰器
"""
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
logging.info(f"{func.__name__} took {end_time-start_time:.2f} seconds")
return result
return wrapper
健壮的错误处理机制:
python复制def safe_extract_text(file_path):
"""
安全的文本提取函数
"""
try:
if file_path.endswith('.pdf'):
return extract_text_from_pdf(file_path)
elif file_path.endswith('.docx'):
return read_docx(file_path)
elif file_path.endswith('.txt'):
with open(file_path, 'r') as f:
return f.read()
else:
raise ValueError("Unsupported file format")
except Exception as e:
logging.error(f"Error processing {file_path}: {str(e)}")
return None
建议定期:
在实际项目中,我发现文档处理的质量很大程度上取决于预处理步骤。投入时间优化文本清洗逻辑,可以显著提高后续分析的准确性。另外,对于关键业务场景,建议实现多重校验机制,比如结合规则匹配和机器学习模型来提高信息提取的可靠性。