You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正句子分词代码避免引号迁移至后续句子?

问题:PDF文本分句时跨段落/页面的闭合引号归属错误

我正在把PDF里的文本抓取到Excel,需要把故事文本分成句子。现在基本实现了,但有个问题:当句子以闭合引号结尾,且下一句在新段落或新页面时,闭合引号会跑到下一句里,而不是留在前句。比如文本里“makeve!”后面的引号会被带到下一页的句子中。请帮忙修改代码解决这个问题。

现有代码

import pdfplumber
import pandas as pd
import nltk
import re
import glob

def exclude_page_numbers(page_text, page_elements, exclusion_regions):
    filtered_text = ""

    for element in page_elements:
        text = element["text"]
        x, y = element["x0"], element["top"]  # 获取元素的x、y坐标

        # 检查元素是否在排除区域内
        exclude = False
        for region in exclusion_regions:
            x_min, y_min, x_max, y_max = region
            if x_min <= x <= x_max and y_min <= y <= y_max:
                exclude = True
                break

        if not exclude and not any(char.isdigit() for char in text) and not text.strip().isdigit():
            filtered_text += text + " "  # 每个元素后加空格

    return filtered_text


def extract_sentences(text):
    # 基于.!?分句,同时考虑句子内的引号配对
    sentences = re.split(r'(?<=[.!?])(?=(?:[^"]*"[^"]*")*[^"]*$)', text)
    sentences = [sentence.strip() for sentence in sentences]

    # 尝试将闭合引号合并到前一句(当前逻辑未生效)
    merged_sentences = []
    i = 0
    while i < len(sentences):
        if sentences[i].endswith('"'):
            if i + 1 < len(sentences):
                merged_sentence = sentences[i] + ' ' + sentences[i + 1]
                merged_sentences.append(merged_sentence)
                i += 2
            else:
                merged_sentences.append(sentences[i])
                i += 1
        else:
            merged_sentences.append(sentences[i])
            i += 1

    # 使用nltk对合并后的句子做二次分句
    tokenized_sentences = []
    for sentence in merged_sentences:
        tokenized_sentences.extend(nltk.sent_tokenize(sentence))

    return tokenized_sentences

def extract_text_from_pdf(pdf_file_path):
    with pdfplumber.open(pdf_file_path) as pdf:
        num_pages = len(pdf.pages)
        text = ""
        for page in range(3, num_pages - 2):
            page_obj = pdf.pages[page]
            page_text = page_obj.extract_text()
            page_elements = page_obj.extract_words()  # 获取文本元素及其位置
            filtered_text = exclude_page_numbers(page_text, page_elements, exclusion_regions)
            text += filtered_text

        return text

def scrape_sentences_to_excel(pdf_file_paths, excel_file_path):
    sentences = []
    for pdf_file_path in pdf_file_paths:
        # 提取PDF文本
        pdf_text = extract_text_from_pdf(pdf_file_path)

        # 分句处理
        extracted_sentences = extract_sentences(pdf_text)
        sentences.extend(extracted_sentences)

    # 创建DataFrame并写入Excel
    df = pd.DataFrame({'Sentences': sentences})
    df.to_excel(excel_file_path, index=False)

    print("句子提取并保存到Excel成功!")


pdf_folder_path = 'my_pdf_file_path'  # PDF文件夹路径
excel_file_path = 'me_excel_file_path'  # 输出Excel路径

# 定义排除区域(x_min, y_min, x_max, y_max)
exclusion_regions = [(42, 558, 359, 559)]  # 添加你的排除区域

# 获取文件夹内所有PDF文件
pdf_file_paths = glob.glob(pdf_folder_path + '/*.pdf')

# 执行提取并保存
scrape_sentences_to_excel(pdf_file_paths, excel_file_path)
解决方案

问题根源是PDF跨页/跨段落提取时,闭合引号和前一句被拆分,后续分句逻辑未处理这种边界情况。可以从以下两个关键环节修改:

1. 优化PDF文本拼接逻辑,提前处理跨页引号

在extract_text_from_pdf函数中,拼接页面文本时检查当前页开头是否为闭合引号,若是则将其移至上一页文本末尾:

def extract_text_from_pdf(pdf_file_path):
    with pdfplumber.open(pdf_file_path) as pdf:
        num_pages = len(pdf.pages)
        text = ""
        for page in range(3, num_pages - 2):
            page_obj = pdf.pages[page]
            page_elements = page_obj.extract_words()
            filtered_text = exclude_page_numbers(page_obj.extract_text(), page_elements, exclusion_regions)
            
            # 处理跨页的闭合引号:如果当前页开头是引号,移到上一页末尾
            if text and filtered_text.startswith('"'):
                filtered_text = filtered_text[1:].strip()
                text = text.rstrip() + '" '
            
            text += filtered_text + " "

        return text.strip()

2. 修正分句逻辑,确保闭合引号归属正确

原extract_sentences函数的合并逻辑方向错误,应检查下一句是否以引号开头,而非当前句以引号结尾:

def extract_sentences(text):
    # 先清理多余空格,避免干扰分句
    text = re.sub(r'\s+', ' ', text).strip()
    
    # 基于标点分句,同时考虑引号配对
    sentences = re.split(r'(?<=[.!?])(?=(?:[^"]*"[^"]*")*[^"]*$)', text)
    sentences = [s.strip() for s in sentences if s.strip()]

    # 处理被拆分到下一句的闭合引号
    merged_sentences = []
    i = 0
    while i < len(sentences):
        current_sent = sentences[i]
        # 检查下一句是否以闭合引号开头,且当前句是完整句子
        if i + 1 < len(sentences) and sentences[i+1].startswith('"'):
            merged_sent = f"{current_sent}\""
            merged_sentences.append(merged_sent)
            i += 2
        else:
            merged_sentences.append(current_sent)
            i += 1
    
    # 用nltk做二次分句优化
    final_sentences = []
    for sent in merged_sentences:
        final_sentences.extend(nltk.sent_tokenize(sent))
    
    # 清理空句子
    final_sentences = [s.strip() for s in final_sentences if s.strip()]
    
    return final_sentences

3. 额外准备:加载nltk分句模型

第一次运行前需下载分句模型:

nltk.download('punkt')

内容的提问来源于stack exchange,提问作者Paige Cox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:37:06