python爬虫处理在线预览的pdf文档

引言

最近在爬一个网站,然后爬到详情页的时候发现,目标内容是用pdf在线预览的

比如如下网站:

https://camelot-py.readthedocs.io/en/master/_static/pdf/foo.pdf

根据我的分析发现,这样的在线预览pdf的采用了pdfjs加载预览,用爬虫的方法根本无法直接拿到pdf内的内容的,对的,你注意到了我说的【根本无法直接拿到】中的直接两个字,确实直接无法拿到,怎么办呢?只能把pdf先下载到本地,然后用工具转了,经过我查阅大量的相关资料发现,工具还是有很多:

  1.借用第三方的pdf转换网站转出来

  2.使用Python的包来转:如:pyPdf,pyPdf2,pyPdf4,pdfrw等工具

这些工具在pypi社区一搜一大把:

但是效果怎么样就不知道了,只能一个一个去试了,到后面我终于找到个库,非常符合我的需求的库 ——camelot

camelot可以读取pdf文件中的数据,并且自动转换成pandas库(数据分析相关)里的DataFrame类型,然后可以通过DataFrame转为csv,json,html都行,我的目标要的就是转为html格式,好,废话不多说,开始搞

开始解析

1.安装camelot:

pip install camelot-py

pip install cv2  (因为camelot需要用到这个库)

2.下载pdf:因为在线的pdf其实就是二进制流,所以得按照下载图片和视频的方式下载,然后存到本地的一个文件里,这个步骤就不多说了

3.解析:

import camelot

file = ‘temp.pdf‘
table = camelot.read_pdf(file,flavor=‘stream‘)
table[0].df.to_html(‘temp.html‘)

以上的temp.html就是我希望得到的数据了,然后根据我的分析发现,在read_pdf方法里一定带上参数  【flavor=‘stream‘】,不然的话就报这个错:

RuntimeError: Please make sure that Ghostscript is installed

原因就是,read_pdf默认的flavor参数是lattice,这个模式的话需要安装ghostscript库,然后你需要去下载Python的ghostscript包和ghostscript驱动(跟使用selenium需要下载浏览器驱动一个原理),而默认我们的电脑肯定是没有安装这个驱动的,所以就会报上面那个错。我试着去装了这个驱动和这个包,去read_pdf时其实感觉没有本质区别,是一样的,所以带上参数flavor=‘stream‘即可,当然如果你硬要用lattice模式的话,安装完ghostscript包和ghostscript驱动之后,记得在当前py文件用  【import ghostscript】导入下这个包,不然还是会报如上错误

继续走,发现能拿到我想要的数据了,非常nice,然后突然的,报了如下错误:

PyPDF2.utils.PdfReadError: EOF marker not found

当时就是卧槽,这什么情况,我开始去研究EOF marker是什么意思,但是我直接打开这个pdf文件又是正常的

非常诡异,网上查阅了一堆,大概意思就是说,没有EOF结束符,这个东西在之前我做js开发的时候遇到过,js的语句体{},少了最后的【}】,

我又去了解了下EOF到底在二进制文件指的什么,然后看到老外的这个帖子:

我用同样的方法查看数据的前五个字符和后五个字符:

好像有了眉目,我以文本的方式打开了我下载到本地的一个pdf,在%%EOF结尾之后还有很多的null

难道是NULL的问题?我手动删掉null之后,单独对这个修改过的pdf用pdf查看器打开,正常打开,没有问题,我接着用代码针对这个文件执行read_pdf,发现非常神奇的不会报错了,那还真是结尾的NULL元素了。

然后我在从网上读取到pdf之后的二进制部分用字符串的strip()方法,以为用strip可以去除那些null,结果发现还是如此

-------------------------------------

那就只有先锁定  %%EOF 所在位置,然后切片操作了,部分代码如下,果然问题解决,但同时又报了一个新的错,这个就是个编码问题了,相信搞爬虫的朋友们对这个问题非常熟悉了

先暂时不管这个问题,我又改了下目标网站的指定页码

pdfminer.psparser.SyntaxError: Invalid dictionary construct: [/‘Type‘, /‘Font‘, /‘Subtype‘, /‘Type0‘, /‘BaseFont‘, /b"b‘", /"ABCDEE+\\xcb\\xce\\xcc\\xe5‘", /‘Encoding‘, /‘Identity-H‘, /‘DescendantFonts‘, <PDFObjRef:11>, /‘ToUnicode‘, <PDFObjRef:19>]

发现问题越来越严重了,我鼓捣了一番之后,又查了一堆资料,将utf-8改成gb18030还是报错,我发现我小看这个问题了,接着查阅,然后发现github上camelot包的issues也有人提了这个报错,

https://github.com/atlanhq/camelot/issues/161

然后这里有个人说可以修复下pdf文件:

我查了下,需要安装一个软件mupdf,然后在终端用命令 修复

mutool clean 旧的.pdf 新的.pdf

首先这并不是理想的解决方法,在python代码中,是可以调用终端命令,用os和sys模块就可以,但是万一因为终端出问题还不好找原因,所以我并没有去修复,之后我发现我这个决定是对的

接着看,发现issue里很多人都在反馈这个问题,最后看到这个老哥说的

大概意思就是说pypdf2无法完美的处理中文文档的pdf,而camelot对pdf操作就基于pypdf2,卧槽,这个就难了。

然后我又查到这篇文章有说到这个问题:https://blog.csdn.net/kmesky/article/details/102695520

那只能硬改源码了,改就改吧,毕竟这也不是我第一次改源码了

注意:如果你不知道的情况下,千万不要改源码,这是一个大忌,除非你非常清楚你要做什么

修改源码:

1.format.py

C:\Program Files\Python37\Lib\site-packages\pandas\io\formats\format.py该文件的第846行

由这样:

改成这样:

2.generic.py

File "D:\projects\myproject\venv\lib\site-packages\PyPDF2\generic.py", 该文件的第484行

3.utils.py

Lib/site-packages/PyPDF2/utils.py 第238行

4.运行

再运行:之前那些错误已经没有了

但同时又有了一个新的错

其实这个超出索引范围的报错的根本是上面的警告:UserWarning:page-1 is image-based,camelot only works on text-based pages. [streams.py:443]

因为源数据pdf的内容是个图片,不再是文字,而camelot只能以文本形式提取数据,所以数据为空,所以 table[0]会报索引超出范围

针对图片的处理,我网上查阅了一些资料,觉得这篇文章写的不错,可以提取pdf中的图片

https://blog.csdn.net/qq_15969343/article/details/81673302

但是,我的目标是希望拿到pdf中的内容,然后转成html格式,在之前,我已经由在线pdf->本地pdf->提取表格->表格转html,这是第一种。

如果要提取图片的话,那步骤就是第二种:在线pdf->本地pdf->提取图片->ocr提取表格->验证对错->表格转html,这样就会多些步骤,想想,我为了拿到一个网站的数据,每个网页就要做这些操作,而且还要判断是图片就用用第二种,是表格就用第一种,两个方法加起来的话,爬一个网站的数据要做的操作的就多了,虽然这些都属于IO操作型,但是到后期开启多线程,多进程时,与那些直接就能从源网页提取的相比就太耗时间了。

这样不是不行,是真的耗时间,所以我暂时放弃对图片的提取了,只提取table,先对pdf二进制数据判断是否是图片,是图片就跳过了

原理就是,根据上面那片博客里的:

打开二进制源码验证:

第一个,它确实是图片的:

第二个,它是表格:

不过经过我的验证,发现这个方法正确率不能百分之百,少部分的即使是表格还是有/Image和/XObject相关的字符串

那没办法了,有多少是多少吧

部分代码实现:

fujian_data = requests.get(fujian_url, headers=headers).content
fujian_index = fujian_data.index(b‘%%EOF‘)
fujian_data = fujian_data[:fujian_index + len(b‘%%EOF‘)]
checkXO = rb"/Type(?= */XObject)"
checkIM = rb"/Subtype(?= */Image)"
isXObject = re.search(checkXO, fujian_data)
isImage = re.search(checkIM, fujian_data)
if isXObject and isImage:
    # 是图片跳过
    pass
f = open(‘temp.pdf‘, ‘wb‘)
f.write(fujian_data)
f.close()
tables = camelot.read_pdf(‘temp.pdf‘, flavor=‘stream‘)
if os.path.exists(‘temp.pdf‘):
    os.remove(‘temp.pdf‘)  # 删除本地的pdf
tables[0].df.to_html(‘foo.html‘, header=False, index=False)

至此完毕,当然,你也可以用camelot 的to_csv 和 to_json方法转成你希望的,具体就自己研究了

以上就是Python处理在线pdf的所有内容

原文地址:https://www.cnblogs.com/Eeyhan/p/12111371.html

时间: 2024-10-06 07:33:31

python爬虫处理在线预览的pdf文档的相关文章

Office在线预览及PDF在线预览的实现方式大集合

一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office2007以上版本的一个PDF插件SaveAsPDFandXPS.exe可以导出PDF文件,然后再利用免费的swftools.exe工具生成swf格式的Flash文件,网页中加载flexpaper免费开源工具(有广告)实现Flash文件的预览.优点:1.有效的保护的源文件及文件的复制,不可复制也是缺点.2.源码是自己的,版权有保证.缺点:1.服务器上必须安装Office软件.2.导出PDF文件本身是个

Office在线预览及PDF在线预览的实现方式史上最全大集合

Office在线预览及PDF在线预览的实现方式大集合 一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office2007以上版本的一个PDF插件SaveAsPDFandXPS.exe可以导出PDF文件,然后再利用免费的swftools.exe工具生成swf格式的Flash文件,网页中加载flexpaper免费开源工具(有广告)实现Flash文件的预览.优点:1.有效的保护的源文件及文件的复制,不可复制也是缺点.2.源码是自己的,版权有保证.缺点:1.服务器

轻松便捷的文档在线预览工具

北京博信施科技有限公司是一家专注于Office文档在线预览及PDF文档在线预览服务的专业提供商,依据HTML标准的4.01版本规范,研制开发出Microsoft Word.Excel.Powerpoint文档转换HTML文件格式以及Adobe PDF文件转换HTML文件格式的软件产品.实现Microsoft Word文档在线预览.Excel表格在线预览.Powerpoint演示文档在线预览及Adobe PDF文档在线预览,完美呈现Microsoft Office及Adobe PDF文档原始样式和

基于HTML的轻松便捷的文档在线预览工具—HTMLFilter

北京博信施科技有限公司是一家专注于Office文档在线预览及PDF文档在线预览服务的专业提供商,依据HTML标准的4.01版本规范,研制开发出Microsoft Word.Excel.Powerpoint文档转换HTML文件格式以及Adobe PDF文件转换HTML文件格式的软件产品.实现Microsoft Word文档在线预览.Excel表格在线预览.Powerpoint演示文档在线预览及Adobe PDF文档在线预览,完美呈现Microsoft Office及Adobe PDF文档原始样式和

WEB在线预览PDF

这是我在博客园发表的第一篇文章.以后会陆续把在线预览其他格式文档的解决方案发表出来. 解决思路:把pdf转换成html显示. 在线预览pdf我暂时了解3种解决方案,欢迎大家补充. 方案一: 利用pdf2html软件将PDF转换成HTML. 用法: PDF2HTML [选项] <PDF 文件> [<HTML 文件>] -f <页数>   : 转换开始页-l <页数>  : 转换结束页-z <缩放率>        : 设置转换缩放率,从 50 到

Java实现web在线预览office文档与pdf文档实例

https://yq.aliyun.com/ziliao/1768?spm=5176.8246799.blogcont.24.1PxYoX 摘要: 本文讲的是Java实现web在线预览office文档与pdf文档实例, 1.首先我们需要找到可以把office转换成pdf的方法,查找资料发现有openoffice这一软件可以把office转换成pdf,这一软件先下载下来,然后记住自己安装的在那个位置.然后在cmd环境下进入安装目录的program目 云计算 云服务器ECS 大数据 建站 备案 文档

word文档在线预览解决方案

花了一整天在网上翻关于 “word文档在线预览解决方案” 相关的资料,感觉实现难度比较大还是用PDF来解决好了.. 下面列一下比较好的参考资料吧 参考资料 前端实现在线预览pdf.word.xls.ppt等文件 OFFICE 文档转换为html在线预览 [Asp.net]常见word,excel,ppt,pdf在线预览方案,有图有真相,总有一款适合你! Office文件在线预览功能够折腾的了 Office在线预览及PDF在线预览的实现方式大集合 python3将docx转换成pdf,html文件

JSP实现word文档的上传,在线预览,下载

前两天帮同学实现在线预览word文档中的内容,而且需要提供可以下载的链接!在网上找了好久,都没有什么可行的方法,只得用最笨的方法来实现了.希望得到各位大神的指教.下面我就具体谈谈自己的实现过程,总结一下学习中的收获. 我相信很多程序员都遇到过,有些word文档希望直接在浏览器中打开进行预览,但是浏览器往往不是很配合,直接就提示下载,不像pdf文档,浏览器可以直接进行预览.Word文档甚至始终都会通过本地的Office软件打开.那么,问题来了,如何可以在线浏览word文档呢? 其实,我在最初的时候

借助flexpaper实现word在线预览和打印

为了实现word能够在web上尽量以原始的排版样式展现出来,选择基于activex控件的方式太过于依赖某种浏览器,并且存在可能需要花费金钱购买相应的控件产品:于是借助flexpaper这种flash展现方式就成为了首选的解决方案.该方案的实现过程主要是先将word文档转换成pdf文档,接着再通过SWFTOOLS工具将pdf文档转换成swf文件,然后flexpaper加载这些swf文件进行展示. 访问flexpaper的官网地址:http://flexpaper.devaldi.com/downl