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

使用PyPDF2修改PDF文本时英文拆分、阿拉伯语识别异常问题求助

问题根因&解决方案

问题1:英文单词拆分显示异常

PDF规范中TJ运算符本身支持将文本拆分为多个带字符间距调整的片段存储,你当前的逐行直接替换逻辑没有处理拆分的文本片段,会出现占位符/单词被拆分到不同片段无法匹配、替换后结构错乱的问题。

问题2:阿拉伯语替换失效

PDF内容流中的字符串编码不是默认使用UTF-8,而是和对应位置绑定的字体编码相关,阿拉伯语常用的CP1256、Identity-H等编码直接用UTF-8解码会被转为八进制转义字符,自然无法和你写的UTF-8阿拉伯语字符串匹配。


修改后的可运行代码
import os
import argparse
import re
from PyPDF2 import PdfFileReader, PdfFileWriter
from PyPDF2.generic import DecodedStreamObject, EncodedStreamObject, NameObject

# 匹配TJ操作的正则
TJ_PATTERN = re.compile(r'\[(.*?)\]\s*TJ', re.DOTALL)
# 匹配TJ数组内的文本片段+位移的正则
SEGMENT_PATTERN = re.compile(r'\((.*?)\)\s*([-+]?\d*\.?\d+)?')

def merge_tj_text(tj_content):
    """把TJ数组里的所有文本片段拼接成完整字符串"""
    segments = SEGMENT_PATTERN.findall(tj_content)
    full_text = ''
    for seg, _ in segments:
        # 处理转义字符
        seg = seg.replace(r'\(', '(').replace(r'\)', ')').replace(r'\\', '\\')
        full_text += seg
    return full_text, segments

def rebuild_tj_content(segments, replacements):
    """替换文本后重新生成TJ内容"""
    new_segs = []
    for seg, offset in segments:
        original_seg = seg.replace(r'\(', '(').replace(r'\)', ')').replace(r'\\', '\\')
        replaced_seg = original_seg
        for k, v in replacements.items():
            replaced_seg = replaced_seg.replace(k, v)
        # 转义特殊字符
        replaced_seg = replaced_seg.replace('\\', r'\\').replace('(', r'\(').replace(')', r'\)')
        if offset:
            new_segs.append(f'({replaced_seg}){offset}')
        else:
            new_segs.append(f'({replaced_seg})')
    return f'[{" ".join(new_segs)}]TJ'

def replace_text(content, replacements = dict(), encoding='cp1256'):
    # 先处理编码适配,阿拉伯语常用cp1256,可根据实际字体编码调整
    content = content.decode(encoding, errors='replace')
    # 处理所有TJ操作
    def replace_tj(match):
        tj_content = match.group(1)
        full_text, segments = merge_tj_text(tj_content)
        # 替换文本后重构TJ结构
        return rebuild_tj_content(segments, replacements)
    
    result = TJ_PATTERN.sub(replace_tj, content)
    return result.encode(encoding)

def process_data(obj, replacements):
    data = obj.getData()
    replaced_data = replace_text(data, replacements)
    if obj.decodedSelf is not None:
        obj.decodedSelf.setData(replaced_data)
    else:
        obj.setData(replaced_data)

if __name__ == "__main__":
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--input", required=True, help="path to PDF document")
    args = vars(ap.parse_args())

    in_file = args["input"]
    filename_base = in_file.replace(os.path.splitext(in_file)[1], "")

    # 阿拉伯语替换规则
    replacements = {'اسم': 'يارا'}

    pdf = PdfFileReader(in_file)
    writer = PdfFileWriter()

    for page_number in range(pdf.getNumPages()):
        page = pdf.getPage(page_number)
        contents = page.getContents()

        if isinstance(contents, (DecodedStreamObject, EncodedStreamObject)):
            process_data(contents, replacements)
        elif len(contents) > 0:
            for obj in contents:
                if isinstance(obj, (DecodedStreamObject, EncodedStreamObject)):
                    streamObj = obj.getObject()
                    process_data(streamObj, replacements)

        page[NameObject("/Contents")] = contents.decodedSelf
        writer.addPage(page)

    with open(f"{filename_base}.result.pdf", 'wb') as out_file:
        writer.write(out_file)

额外注意事项
  • 如果你的PDF阿拉伯语字体用的不是CP1256编码,可以把replace_text函数里的encoding参数改成对应编码,比如utf-8、iso-8859-6等
  • 若处理排版复杂的PDF,推荐使用PyMuPDF(fitz)库完成文本替换,操作逻辑更简单,稳定性远高于直接修改PyPDF2的原始内容流
  • 阿拉伯语为右到左书写的RTL语言,替换后如果出现文字顺序颠倒,需要调整文本的写入顺序适配PDF的RTL渲染规则

内容的提问来源于stack exchange,提问作者Sara Kat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 21:54:10