我在lxml文件中找到了bbox坐标,并使用PDFQuery提取了想要的数据.然后我将数据写入csv文件.

def pdf_scrape(pdf):
    """
    Extract each relevant information individually
    input: pdf to be scraped
    returns: dataframe of scraped data
    """
    # Define coordinates of text to be extracted
    CUSTOMER             = pdf.pq('LTTextLineHorizontal:overlaps_bbox("356.684, 563.285, 624.656, 580.888")').text() 
    CUSTOMER_REF         = pdf.pq('LTTextLineHorizontal:overlaps_bbox("356.684, 534.939, 443.186, 552.542")').text()
    SALES_ORDER          = pdf.pq('LTTextLineHorizontal:overlaps_bbox("356.684, 504.692, 414.352, 522.295")').text()
    ITEM_NUMBER          = pdf.pq('LTTextLineHorizontal:overlaps_bbox("356.684, 478.246, 395.129, 495.849")').text()
    KEY                  = '0000'+ SALES_ORDER + '-' + '00' + ITEM_NUMBER
    # Combine all relevant information into a single pandas dataframe
    page = pd.DataFrame({
        'KEY'          : KEY,
        'CUSTOMER'     : CUSTOMER,
        'CUSTOMER REF.': CUSTOMER_REF,
        'SALES ORDER'  : SALES_ORDER,
        'ITEM NUMBER'  : ITEM_NUMBER
                       }, index=[0])
    return(page)

pdf_search = Path("files/").glob("*.pdf")

pdf_files = [str(file.absolute()) for file in pdf_search]

master = list()
for pdf_file in pdf_files: 
    pdf = pdfquery.PDFQuery(pdf_file)
    pdf.load(0)

# Iterate over all pages in document and add scraped data to df
    page = pdf_scrape(pdf) 
    master.append(page)

master = pd.concat(master, ignore_index=True)
master.to_csv('scraped_PDF_as_csv\scraped_PDF_DataFrame.csv', index = False)

问题是我每天需要阅读数百个PDF,而这个脚本需要大约13-14秒才能从10个PDF的第一页中挖掘出四个元素.

有没有办法加速我的代码?

我try 过使用PyMuPDF,因为它应该更快,但在实现它时遇到了问题,无法提供与PDFQuery相同的输出.有人知道怎么做吗?

重申一下,我知道所需文本在文档中的位置,但我不一定知道它说了什么.

推荐答案

在回答其他问题时,我对PyMuPDF进行了一些探索,但我没有个人/实践经验.在发表这篇文章之前,我对pdf格式一无所知.尽管如此,我仍然可以展示我对一个非常基本的示例的看法,即使用PyMuPDF获取基于位置的单个文本.

此外,您不需要从这些时间推断pdf格式很慢,作者在文档中points this out次:

Performance Note:首次调用pdf.load()运行速度非常慢,因为底层pdfminer库必须将页面上的每个元素与其他元素进行比较.请参阅"缓存"部分,以避免在后续运行中出现这种情况.

pdf格式

import pdfquery

query1 = (176.4, 629.28, 176.4, 629.28)  # "Text 1" in simple.pdf
pdf = pdfquery.pdf格式("simple.pdf")

# query1 = (130, 407, 130, 407)  # Looking for "Gaussian" in more_complicated.pdf
# pdf = pdfquery.pdf格式("more_complicated.pdf")

pdf.load(0)

text1 = pdf.pq('LTTextLineHorizontal:overlaps_bbox("%d, %d, %d, %d")' % query1).text()

print(text1)

PyMuPDF

我仍然不知道如何最好地使用PyMuPDF完成这项任务,但这里有一种方法,至少可以为我提供简单和复杂的目标文本:

from fitz import open as fitz_open, Document, Page, Rect

query1 = Rect(165.6, 165.6, 165.6, 165.6)  # "Text 1" in simple.pdf
doc: Document = fitz_open("simple.pdf")

# query1 = Rect(130, 381, 130, 381)  # Looking for "Gaussian" in more_complicated.pdf
# doc: Document = fitz_open("more_complicated.pdf")

page: Page = doc.load_page(0)

page_dict: dict = page.get_text("dict")

bbox: Rect  # a variable we'll reuse as we work down to our query
text1 = ""  # the text we're looking for with query1

block: dict
for block in page_dict["blocks"]:
    if block["type"] == 1:  # skip, it's an image
        continue

    bbox = Rect(block["bbox"])
    if not bbox.contains(query1):
        continue

    line: dict
    for line in block["lines"]:

        bbox = Rect(line["bbox"])
        if not bbox.contains(query1):
            continue

        span: dict
        for span in line["spans"]:

            bbox = Rect(span["bbox"])
            if not bbox.contains(query1):
                continue

            text1 = span["text"]

print(text1)

分析

(您可能已经注意到,pdf格式和PyMuPDF之间的查询坐标不同,这是因为pdf格式使用左bottom作为原点,而PyMuPDF使用左upper作为原点.)

我还在macOS 12.4上用time命令测量了运行时间;平均运行3次.下面是我对simple运行pdf格式和PyMuPDF的结果.pdf和更复杂的.pdf:

simple.pdf more_complicated.pdf
file simple complicated
pdf格式 timing (s) 0.123 0.258
PyMuPDF timing (s) 0.069 0.070

PyMuPDF几乎同时运行这两个PDF,我认为我们看到pdf格式需要更长的时间来进行这n**2/2个交叉比较.

我想你会放弃很多便利,自己try 做这件事.如果您的PDF是一致的,您可能会调整PyMuPDF并使其正确,但如果它们的创建方式存在差异,则可能需要更长的时间才能正确(即使是这样,因为PDF中的文本具有欺骗性).

Python相关问答推荐

如何确保Flask应用程序管理面板中的项目具有单击删除功能?

无法获得指数曲线_fit来处理日期

如何从不同长度的HTML表格中抓取准确的字段?

不允许AMBIMA API请求方法

如何销毁框架并使其在tkinter中看起来像以前的样子?

Python -Polars库中的滚动索引?

将HTML输出转换为表格中的问题

如何在msgraph.GraphServiceClient上进行身份验证?

Pandas 在最近的日期合并,考虑到破产

仿制药的类型铸造

Python json.转储包含一些UTF-8字符的二元组,要么失败,要么转换它们.我希望编码字符按原样保留

Pandas 都是(),但有一个门槛

如何在虚拟Python环境中运行Python程序?

切片包括面具的第一个实例在内的眼镜的最佳方法是什么?

如何在UserSerializer中添加显式字段?

如何在turtle中不使用write()来绘制填充字母(例如OEG)

如何在Pyplot表中舍入值

numpy.unique如何消除重复列?

具有相同图例 colored颜色 和标签的堆叠子图

基于多个数组的多个条件将值添加到numpy数组