pdf有两类,一类是别人用word转pdf,你想转过来那种,带有光标那种,计算机能轻松识别,转换相对简单很多。第二类,即图片类pdf,也就是平常工作中看到的各种扫描件,它的识别相对要复杂一些,但又常常是最主要的。近期突发奇想想坚持试写一个,期间遇到许多问题 ,但好在看了许多人的一些经验总结,最后一个个问题都突破了。然后我自己还遇到一些网上找不到答案,自己琢磨解决的。所以想稍微写点东西,希望对其他朋友有所帮助。

必备工具

1、Python      建议安装3.7或以上版本(我自己安装的是3.8版本,pycharm和anaconda3)

2、tesseract-ocr      下载地址: https://github.com/UB-Mannheim/tesseract/wiki 使用最新版本即可

(如果你还想详细了解tesseract-ocr,可以登录 Python OCR工具pytesseract详解 - 墨天轮 学习)


需要用到的库主要有:


pip install pillow

pip install opencv-python

pip install fitz

pip install PyMuPDF

pip install pytesseract


大致思路

其实本质是识别jpg或者png格式的图片,至于pdf,则只是加多了一步,即把pdf文件解开为一张张jpg或者png格式,利用for循环就能实现。用os弄出要转的图片的路径,赋值给img_path_guodu,然后接下来就可以通过下面的代码实现

text = pytesseract.image_to_string(Image.open(img_path_guodu), lang='chi_sim+eng')
doc = docx.Document()          # 创建一个新的word文档
doc.add_paragraph(text)     # 往文档里添加识别出来的文字
doc.add_page_break()        # 添加分页符,等于在word里按多了一次Ctrl+Enter

    # 下面两行设置了文档字体全篇为宋体,缺一行不可
doc.styles['Normal'].font.name = u'宋体'
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')

doc.save(os.getcwd() + '\\' + file_name + ".docx")  # 保存文档


常见问题

一、运行后提示No module named ‘frontend‘

控制台出现下面提示:

python idle shell将pdf转为word 用python将pdf转化为word后,word文件为空_python

报错有两种可能:

1、你没装PyMuPDF。解决方法:

pip install PyMuPDF

2、安装装了,但版本不对,最好装下面这个:

pip install PyMuPDF==1.19.0

你如果装的是pip install PyMuPDF==1.16.14 ,系统会提示:ERROR: pdf2docx 0.5.3 has requirement PyMuPDF>=1.19.0, but you'll have pymupdf 1.16.14 which is incompatible.

翻译:要安装更高版本的PyMuPDF才能对应pdf2docx 0.5.3。

所以我还是觉得最好直接安装pip install PyMuPDF==1.19.0

python idle shell将pdf转为word 用python将pdf转化为word后,word文件为空_解决方法_02

二、出现下面提示:

pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it’s not in your path

如下图:

python idle shell将pdf转为word 用python将pdf转化为word后,word文件为空_解决方法_03

解决方法:复制上面图片中选中的那个地址,去那个地址下,打开pytesseract.py文件,按照下面图这样修改:

# tesseract_cmd = 'tesseract'

tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

python idle shell将pdf转为word 用python将pdf转化为word后,word文件为空_Image_04

三、提示AttributeError: 'NoneType' object has no attribute '__array_interface__',起初我以为是安装Tesseract时没有勾选下载可供识别的语言,所以我就重新安装并且全部勾选了,但还是不行。错误提示如下图:

python idle shell将pdf转为word 用python将pdf转化为word后,word文件为空_pycharm_05

这里有先说说实现文字识别有两种写法,一种依赖于opencv的写法,一种不依赖opencv:
依赖opencv的如下:
img = cv.imread(img_path)
print(img)
text = pytesseract.image_to_string(Image.fromarray(img), lang='chi_sim+eng')    # lang='chi_sim+eng'是识别简体中文和英文;'chi_tra'则表示繁体中文
不依赖opencv写法如下:
text=pytesseract.image_to_string(Image.open(img_path), lang='chi_sim+eng')  # 这里用到的参数只有路径。

问题所在:

 问题出在img = cv.imread(img_path),其中的路径不可以带有中文。

我一开始发现前面的引入模块的代码

python idle shell将pdf转为word 用python将pdf转化为word后,word文件为空_Image_06

这里,import cv2 as cv 一行呈灰色,我试着执行以下操作:

python idle shell将pdf转为word 用python将pdf转化为word后,word文件为空_开发语言_07


但还是无法使用依赖opencv的写法去实现文字识别。

我试着重新pip install opencv-python安装模块,也是不行。

最后我发现,问题就出在img = cv.imread(img_path)这里读取的路径、包括文件名只能带有英文数字及一些特定字符,不能带有中文、日文等字符,带有中文就没法使用cv方法,当你print(img)时,控制台也会显示None,说明此时读不出img。一旦把文件夹及需要识别的文件的文件名,全部改为英文字母时,就可以运行程序。


解决方法:

如果出现上面的错误,则可以选择用不依赖opencv的方法,便不再出现报错问题

四、文件抽出来时,放大参数设置得太大。PDF抽出图片后,在识别时,无法识别图片前面那几行字,还有最后一行或几行也没法识别,并且容易出现错误识别。

问题就出在:

PDF文件解压成一张张jpg格式后,通常文件因为太大而无法完整识别全部内容,易出现部分遗漏或错漏,这里我之前有认识误区,我以为图片越大越容易识别,其实不是的,2800像素*2800像素,就是比较好的了,超过10000像素的反而识别得很混乱。
解决方法:需要先将文件压到合适大小,把短边改为2800像素,长边根据短边做出相应等比例缩放。如此则即可以识别,同时又不至于文件太大。

认真读下面几段代码,就能理解等比例缩放图片大小的实现方式了,下面的方式,不需要用到opencv模块。cv、cv2模块,因为不能读取带有中文路径的文件,所以最好避开opencv模块,不然太局限了。


img_path = 'C:/Users/sun2020/Desktop/tpdf_docx/test266.png'
picture=Image.open(img_path)
heng,shu=picture.size
print(heng,shu)

picture = picture.resize((2800,int(2800*shu/heng)),Image.ANTIALIAS)   #改变尺寸,保持图片高品质
heng1,shu1=picture.size
print(heng1,shu1)

五、当我们读取的文件太大时,有时系统提示:

    raise DecompressionBombError(

PIL.Image.DecompressionBombError: Image size (217795500 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack.

翻译:图像大小(217795500像素)超过178956970像素的限制

解决方法:

在你的程序刚刚开始写的位置,写入下面三行代码:

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
Image.MAX_IMAGE_PIXELS = None

以后运行便不会报错。