当前位置:首页>python>告别手动打码!Python一键脱敏PDF中的身份证号、手机号,批量处理超省心!

告别手动打码!Python一键脱敏PDF中的身份证号、手机号,批量处理超省心!

  • 2026-09-02 19:54:39
告别手动打码!Python一键脱敏PDF中的身份证号、手机号,批量处理超省心!
小王遇到了一件头疼的事,有大量的PDF登记表,里面有身份证号码、手机号码,直接分享出去担心泄露隐私,挨个手动处理又慢又费力。问我在没有简便的方法。
在日常工作中,对PDF文件做脱敏处理是一件繁琐的事情,不能的直接修改和保存。今天分享一段Python代码,这段代码能自动识别PDF文件中的身份证号码、手机号码等,保留关键数字、隐藏中间部分,全程无需手动干预,批量处理效率直接拉满!
from pathlib import Pathimport reimport fitz  # PyMuPDFdef redact_numbers_with_overlay(input_path, output_path):    doc = fitz.open(input_path)    # 列表元素为元组(正则表达式, 保留的前部长度, 保留的后缀长度)    re_rules = [        (re.compile(r"\d{17}[\dXx]"), 10, 4),     # 身份证号(18位):保留前10,保留后4,中间8位覆盖        (re.compile(r"1\d{10}"), 3, 4),    # 手机号(11位):保留前3,保留后4,中间4位覆盖        #(re.compile(r"\d{10,11}"), 3, 4),  # 固定电话,保留前3,保留后4,中间覆盖    ]    for page in doc:        # 获取页面所有文本的详细信息(包含每个字符的位置)        text_instances = page.get_text("words")        for inst in text_instances:            x0, y0, x1, y1, word, block_no, line_no, span_no = inst            # 检查当前单词是否符合脱敏规则            for pattern, keep_pre, keep_suf in re_rules:                if pattern.fullmatch(word):                    total_len = len(word)                    # 计算需要覆盖的星号数量和位置                    if total_len <= keep_pre + keep_suf:                        continue  # 长度过短,无需脱敏                    # 计算中间部分的宽度(基于原文字符宽度均分)                    char_width = (x1 - x0) / total_len                    # 覆盖区域的起始X:前导文字的宽度                    cover_x0 = x0 + keep_pre * char_width                    # 覆盖区域的结束X:总宽度 - 后缀文字的宽度                    cover_x1 = x1 - keep_suf * char_width                    #  绘制与原字符同高的黑色矩形,背景设为白色(匹配纸张),边框设为无,完全无缝融合                    rect = fitz.Rect(cover_x0, y0 - 1, cover_x1, y1 + 1)                    page.draw_rect(rect, color=(1, 1, 1), fill=(1, 1, 1), width=0)                    #  精准写入星号:按原字符宽度均分,字距与原有格式一致                    star_count = total_len - keep_pre - keep_suf                    star_text = "*" * star_count                    # 星号的起始位置(与原中间位置对齐)                    star_x = cover_x0 + 1  # 微调1像素防止溢出                    star_y = y1 - 2  # 与原数字基线对齐                    # 使用小号字体确保星号紧凑,匹配表格字距                    page.insert_text(                        point=(star_x, star_y),                        text=star_text,                        fontsize=6,  # 字号                        fontname="china-s",  # 字体                        color=(0, 0, 0),  # 黑色                    )                    break  # 匹配一个规则后立即退出,避免重复处理    # 保存,文件体积不变    doc.save(output_path, garbage=4, deflate=True, clean=True)    doc.close()def batch_process_pdf(input_folder, output_folder):    input_folder = Path(input_folder)    output_folder = Path(output_folder)    if not input_folder.exists():        print(f"输入文件夹不存在:{input_folder}")        return    if not output_folder.exists():        output_folder.mkdir(parents=True,exist_ok=True)        print(f"创建输出文件夹:{output_folder}")    pdf_files = [f for f in input_folder.glob("*.pdf")]    if not pdf_files:        print("未找到PDF文件")        return    for filename in pdf_files:        name_new = f"{filename.stem}_脱敏.pdf"        file_new = output_folder.joinpath(name_new)        try:            redact_numbers_with_overlay(filename, file_new)            print(f"处理完成:{filename}")        except Exception as e:            print(f"处理失败:{filename}:{str(e)}")if __name__ == "__main__":    input_folder = r"D:\pdf"  # PDF文件夹路径    output_folder = r"D:\pdf_output"  # 输出文件夹路径    batch_process_pdf(input_folder, output_folder)
这段代码没有花里胡哨的功能,全部是办公刚需:
1、智能识别:自动匹配18位身份证号码、11位手机号。
2、精准脱敏:身份证保留前10位和后4位,手机号码保留前3位和后4位,中间用*代替。
3、批量处理:支持整个文件夹内所有PDF文件一键脱敏。
4、无损保存:处理后PDF体积、格式、排版基本与原文档一致。
再来说说代码的解析:
import fitz
fitz是所依赖的模块,安装命令:pip install PyMuPDF。
    input_folder = r"D:\pdf"  # PDF文件夹路径    output_folder = r"D:\pdf_output"  # 输出文件夹路径
代码末尾两行是要处理的文件夹和保存文件的文件夹。这样做可以避免原文件被覆盖。
def redact_numbers_with_overlay(input_path, output_path):
自定义函数,用来对PDF文档中的身份证号、手机号进行脱敏。input_path是输入PDF文件路径,output_path是脱敏后PDF的保存路径。
(re.compile(r"\d{17}[\dXx]"), 10, 4)
对身份证号码的脱敏规则,保留前10位和后4位。re.compile(r"\d{17}[\dXx]")匹配18位身份证号码。
def batch_process_pdf(input_folder, output_folder):
自定义函数,用于批量处理文件夹中的所有PDF文件。
output_folder.mkdir(parents=True,exist_ok=True)
如果输出文件夹不存在则创建文件夹。
pdf_files = [f for f in input_folder.glob("*.pdf")]
用于匹配所有PDF文件。
这段代码仅适用于处理可复制文字的PDF文档,图片类型的PDF文档,如扫描件无法直接处理。
 这段代码可以有效解决PDF文件敏感信息手动处理的痛点,并且还能批量操作,再也不用手动一个一个打码了,赶快动手试试吧!

最新文章

随机文章