# -*- coding: utf-8 -*- """ PDF转TXT工具 - 有文本层的PDF:直接用PyMuPDF提取 - 扫描件PDF:用RapidOCR识别(需要先 pip install rapidocr-onnxruntime pymupdf) 用法:python pdf2txt.py """ import pymupdf import os import time from rapidocr_onnxruntime import RapidOCR # ============ 配置 ============ SRC_DIR = r'F:\BaiduNetdiskDownload\python电子书籍' OUT_DIR = r'F:\BaiduNetdiskDownload\python电子书籍_TXT' # 要转换的文件(按需增删) PDF_FILES = [ 'Python算法教程_中文版.pdf', 'Python学习手册(第4版).pdf', ] ZOOM = 1.5 # 渲染分辨率,越大越准但越慢 # ============================== os.makedirs(OUT_DIR, exist_ok=True) engine = RapidOCR() def has_text_layer(doc, sample_pages=10): """检测PDF是否有文本层""" total = 0 for i in range(min(sample_pages, doc.page_count)): total += len(doc[i].get_text('text', sort=True).strip()) return total > 200 def extract_text_pdf(src_path, out_path): """直接提取文本层""" doc = pymupdf.open(src_path) total = doc.page_count with open(out_path, 'w', encoding='utf-8') as f: for i in range(total): text = doc[i].get_text('text', sort=True) f.write(f'\n===== 第 {i+1} 页 =====\n\n{text}\n') if (i+1) % 100 == 0: print(f' 提取中: {i+1}/{total}') doc.close() return total def ocr_scanned_pdf(src_path, out_path): """OCR识别扫描件,支持断点续传""" doc = pymupdf.open(src_path) total = doc.page_count # 断点续传:检查已完成页数 start_page = 0 mode = 'w' if os.path.exists(out_path): with open(out_path, 'r', encoding='utf-8') as f: done = f.read().count('===== 第 ') if done >= total: print(f' 已完成,跳过') doc.close() return total start_page = done mode = 'a' print(f' 从第 {start_page+1} 页继续') mat = pymupdf.Matrix(ZOOM, ZOOM) t0 = time.time() with open(out_path, mode, encoding='utf-8') as f: for i in range(start_page, total): pix = doc[i].get_pixmap(matrix=mat, alpha=False) tmp_img = os.path.join(OUT_DIR, f'_tmp_p{i}.png') pix.save(tmp_img) result, _ = engine(tmp_img) lines = [line[1] for line in result] if result else [] f.write(f'\n===== 第 {i+1} 页 =====\n\n' + '\n'.join(lines) + '\n') f.flush() os.remove(tmp_img) if (i+1) % 10 == 0: elapsed = time.time() - t0 speed = (i+1-start_page) / elapsed eta = (total-i-1) / speed / 60 print(f' OCR: {i+1}/{total} 页, 速度{speed:.1f}页/秒, 预计剩余{eta:.0f}分钟') doc.close() return total if __name__ == '__main__': for fname in PDF_FILES: src = os.path.join(SRC_DIR, fname) txt_name = os.path.splitext(fname)[0] + '.txt' out = os.path.join(OUT_DIR, txt_name) print(f'\n处理: {fname}') doc = pymupdf.open(src) pages = doc.page_count doc.close() print(f' 共 {pages} 页') if has_text_layer(pymupdf.open(src)): print(' -> 有文本层,直接提取') n = extract_text_pdf(src, out) else: print(' -> 扫描件,使用OCR识别') n = ocr_scanned_pdf(src, out) size = os.path.getsize(out) / 1024 print(f' 完成: {n}页, {size:.0f}KB -> {out}') print('\n全部完成!')PDF转换成TXT脚本代码-QZQ-2026-9-28
张小明
前端开发工程师
基于 SpringBoot+Vue+MySQL 的学生信息管理系统设计与实现(Web 三角色)
基于 SpringBootVueMySQL 的学生信息管理系统设计与实现(Web 三角色) 1. 前言 学生信息管理是学校教学运行中最基础也最琐碎的一环:学籍档案散落在各种表格里,选课靠纸质单据层层统计,成绩汇总常常出现抄错串行的情况…
Claude Code 年入 25 亿美元,Codex 才 10 亿:用 TaoToken 统一 Key 实测两套 AI 编程工具配置
/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …
Claude Code 插件加载失败排查与手动安装 GitHub skills 实战指南
1. 从"官方插件"这个词说起:它到底指什么很多人第一次看到claude-plugins-official这个仓库名,第一反应是"官方插件市场"或者"插件安装包集合"。我一开始也这么以为,点进去翻了半天才发现,它更像是…
Claude Code插件仓库解析:标准化加载机制与开发调试指南
1. 从 claude-plugins-official 说起:这个仓库到底解决了什么问题第一次看到claude-plugins-official这个仓库名的时候,我正被一堆零散的插件配置折腾得够呛。那会儿我在几个不同的项目里来回切换,每个项目用的 Claude Code 插件版本、配置方…
回形针设计史与AI安全:从办公桌到回形针最大化器的工程启示
paperclip 这个词,最近在中文互联网上热得有点反常。热搜里凡是聊人工智能的帖子,十有八九会绕到那枚“蓝色回形针”上——一个极端目标驱动下,把全世界都变成回形针工厂原料的科幻设想。但作为一个常年和材料、制造、办公用品打交道的人&…
Claude Code插件开发实战:从claude-plugins-official到自定义skill与命令
1. 从 claude-plugins-official 说起:这个仓库到底解决了什么问题第一次看到claude-plugins-official这个仓库名的时候,我下意识以为它就是一个普通的插件合集,点进去扫两眼就关掉了。后来在几个项目里反复被“插件加载失败”“skill 不生效”…