最近项目用到了,把PDF转为HTML,项目背景是某国企需求:把上市公司的上市公告爬下来,要公告的发行时间,公告的标题,还有公告的内容摘要,最关键的是这个内容摘要,这个内容公告是通过PDF解析的,刚开始我们把PDF解析成了TXT,使用了PDFminer3k这个模块
pdfminer3k
import importlib import sys import time importlib.reload(sys) time1 = time.time() # print("初始时间为:",time1) import os.path from pdfminer.pdfparser import PDFParser,PDFDocument from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.converter import PDFPageAggregator from pdfminer.layout import LTTextBoxHorizontal, LAParams,LTTextBox, LTTextLine,LTChar from pdfminer.pdfinterp import PDFTextExtractionNotAllowed def parse(text_path): # 读取PDF文本 fp = open(text_path, \'rb\') #创建一个PDF文本解析器 parser = PDFParser(fp) # 创建一个PDF文档对象 doc = PDFDocument() # 连接分析器,与文档对象 parser.set_document(doc) doc.set_parser(parser) # 提供初始化密码,如果没有密码,就创建一个空的字符串 doc.initialize() # 检测文档是否提供txt转换,不提供就忽略 if not doc.is_extractable: raise PDFTextExtractionNotAllowed else: # 创建PDF,资源管理器,来共享资源 rsrcmgr = PDFResourceManager() # 创建一个PDF设备对象 laparams = LAParams() device = PDFPageAggregator(rsrcmgr, laparams=laparams) # 创建一个PDF解释其对象 interpreter = PDFPageInterpreter(rsrcmgr, device) # 循环遍历列表,每次处理一个page内容 # doc.get_pages() 获取page列表 for page in doc.get_pages(): interpreter.process_page(page) # 接受该页面的LTPage对象 layout = device.get_result() # 这里layout是一个LTPage对象 里面存放着 这个page解析出的各种对象 # 一般包括LTTextBox, LTFigure, LTImage, LTTextBoxHorizontal 等等 # 想要获取文本就获得对象的text属性, for x in layout: if (isinstance(x,LTTextBoxHorizontal)): with open(r\'2.txt\', \'a\',encoding=\'utf-8\') as f: results = x.get_text() if "cid:" not in results and results: print(\'>>>>>>>>>>\',results) f.write(results) if __name__ == \'__main__\': pdf_path = r\'xxx.pdf\' parse(pdf_path)
此方法并不对所有的PDF有效,有的PDF会出现这样的问题
该问题还没有解决
pdftotree
官方文档地址https://pypi.org/project/pdftotree/
该方法是用来把PDF转化成HTML页面的,转化HTML页面的原因是为了提取文字方便
# import pdftotree import subprocess import pyocr import importlib import sys,os import time from scrapy.selector import Selector import requests importlib.reload(sys) time1 = time.time() def pdf_to_html(pdf_path): """ 将pdf转HTML,成功与不成功的 :param pdf_path: pdf的本地路径 :return:如果该文件是扫描版,返回扫描版,如果转换失败返回False,如果成功返回转化成HTML的地址 """ try: pdf_file = pdf_path html_output = pdf_file.split(".")[0]+".html" html_output_path = html_output.split("/")[-1] cmd = \'pdftotree\' + " " + "-o" + " " + html_output + " " + pdf_file b = run_command(cmd.split()) for i in b: i = i.decode() if "cannot build tree structure" in i: raise Exception("该文件是PDF扫描版") if "tabula.errors.JavaNotFoundError" in i: raise Exception( "tabula.errors.JavaNotFoundError: `java` command is not found from this Python process. " "Please ensure Java is installed and PATH is set for `java`") info(f"{pdf_file}已经转换成HTML") html_output_path = html_output_path+html_output_path domain_url = "/Users/gongsi/PycharmProjects/sticker/formal/AIQT_DATA/citic_report/citic_report/down_pdf/" file_path = os.path.join(os.path.dirname(__file__),) print(">>>>file",file_path) if os.path.exists(domain_url+html_output_path): return html_output_path return False except Exception as e: print(\'出现错误了\', e) if "PDF扫描版" in e: return "PDF扫描版" return False def run_command(command): """ 执行cmd命令 :param command: cmd字符串 :return: 包含执行命令结果的一个迭代器 """ p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) return iter(p.stdout.readline, b\'\')
这个方法只能解决部分PDF的转换,
其中有这些不能转化
1.PDF为扫描版。
2.会出现让你安装Java的现象。