如何在不写入本地驱动器的情况下访问远程和加密的 PDF 文本

How to access remote and encrypted PDF text without writing to local drive

我是编码世界的新手,现在已经在这个问题上停留了 3 天,到处寻找答案,所以任何帮助将不胜感激。我需要从位于 url 的 Pdf 文件中提取少量文本。我使用 sessions.get(chart_PDF) 作为定位 URL 的驱动程序,其中 chart_PDF 是下面的示例 url。

示例 url 是 https://www.airservicesaustralia.com/aip/pending/dap/PADGN01-166_09SEP2021.pdf

我知道我可以将它写入我的本地驱动器,但我不想这样做,我希望能够远程进行,因为我只需要其中的几个数字。

我试过从url页面找密码解密,没找到。我尝试使用 PyPDF2pdfminerpikepdf(可能不太好)。

我只需要检索 PDF 底部附近的两个数字即可用于我的其余代码。请帮忙,即使这是一个简单的修复,我对这一切都是陌生的,需要一些帮助。谢谢。

from io import BytesIO
from pikepdf import Pdf as PDF
from pdfminer import high_level
chart_PDF = https://www.airservicesaustralia.com/aip/pending/dap/PADGN01-166_09SEP2021.pdf
retrieve = s.get(chart_PDF)
content = retrieve.content

response =urllib.request.urlopen(chart_PDF)
p = BytesIO(content)
p.getbuffer()
check = PDFPage.get_pages(p, check_extractable=False)
extract = high_level.extract_text(p)

我得到:

PDFTextExtractionNotAllowedWarning:位于 ​​0x000001B007ABEC20> 的 PDF <_io.BytesIO 对象包含一个元数据字段,指示它不应允许文本提取。忽略此字段和 proceeding.warnings.warn(warning_msg, PDFTextExtractionNotAllowedWarning)

或者,如果我尝试这样做:

from pikepdf import Pdf as PDF
from pdfminer.pdfpage import PDFPage
from PyPDF2 import PdfFileReader
new_pdf = PDF.new()
with PDF.open(p) as pdf:
    print(len(pdf.pages))
    page1 = pdf.pages[0]
    if PdfFileReader.getIsEncrypted(pdf):
        print(True)
        PdfFileReader.decrypt(page1, password='')
pdf.close()

我得到:

1987行,解密中 return self._decrypt(密码) 属性错误:_decrypt

21 年 3 月 8 日更新 非常感谢你!您帮了大忙!

from io import BytesIO
from pdfminer.pdfpage import PDFPage
from pdfminer import high_level

retrieve = s.get(chart_PDF)
content = retrieve.content
bytes = BytesIO(content)
bytes.getbuffer()
PDFPage.get_pages(bytes, check_extractable=False)
extract = high_level.extract_text(bytes, password='') #THIS LINE THROWS ERROR
joined = ''.join(extract)
find_txt = re.findall(r'[(]\d*[-]\d[.]\d[)]', joined)
print(find_txt)
bytes.close()

这现在运行良好,我已经能够提取我需要的数字(我基本上已经从 PDF 的括号内提取了所有数字)。我会整理一下以找到我需要的那个。

奇怪的是,虽然它给了我我需要的东西,但我的 extract = high_level.extract_text(bytes, password='') 行仍然抛出警告:(warning_msg, PDFTextExtractionNotAllowedWarning) 这是相当恼人的。不确定这个过程是如何工作的,但它仍然会泄露信息。

我不能使用 try except 或者它会跳过它。解决这个问题的方法是什么?我怎样才能阻止该错误出现?

最终更新

我绕过警告,现在运行良好。

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    extract = high_level.extract_text(bytes)

为忍受我的无知而干杯,你们帮了很多忙。

整个文件必须通过 RAM 下载 到设备,这样 blob 作为文件可以在最后解析为 一个或多个 %%EOF 和 第 0 页的位置 (它被转换为 1 或 i)它可能在流中的任何地方,。

然后您可以按照随机生成​​的顺序导航到其他连续编号的页面。如有任何投诉,请联系 Adob​​e。

然而,如果将其缓存为物理 FILE 对象,则最简单。如果你不想在磁盘上使用 ram 驱动器用于你的浏览器

同样,第一页底部的那两个对象可以任何地方 混合到“第 99 页”对象的内容中,否则。 PDF 中的每个字母在极端情况下可以是文件中任何位置的多个对象。但是一个好的创作编辑器会尝试将它们逐行保存。 (没有单词或段落这样的 PDF 东西。)

我们可以将文件打印为纯文本以查看它是如何合成的,尽管(安全)允许这样做。

我尝试从浏览器打印但收效甚微,但我知道这可能取决于浏览器系统和 OS 打印驱动程序。在这里,我使用 Acrobat portable 将页面打印为文本,因此我们可以看到每个文本块从左边缘开始的顺序偏移,就像 PDF 查看器需要重建它们一样。

更新 你说你的目标是 (1380-4.4) 到 ALTERNATE 的右边但是 PDF 没有左右或之前或之后的概念所以我们在这个文件中发现变量目标是在已知字符之前的 2 个单独的部分幸运的是一个完整的单块(备用)。因此,如果捕获仅限于附近的位置,那么这里的纯文本接近度可能会很好地工作。但是,不能保证 ALTERNATE 始终是单个块。

展示向打印机提供顺序数据流的方式可能不是一个好主意 这是一个 PDF 查看器解密文件的方式

正如这次所说,ALTERNATE 一词被定义为文本,但下一项是“B”下的“3”,它是作为矢量路径的文本,它不被称为“字符”,尽管它看起来像一个但是来自字体 table 的编号字形。我们稍后确实看到其中一些数字存储为“文本”,并且对于您的目标,它与同一对象中的类似文本混合在一起。

因此您需要调用 PDF 解释器 来为您提供对对象的所有点点滴滴的有意义的翻译,以便您可以提取“正确”的文本。

复杂文件中“简单”的一行目标最简单的方法是先使用 MuPDF 整理文件

    mutool clean -gggg -D infile.pdf outfile.pdf

结合

    PDFTOTXT -layout outfile.pdf outfile.txt

或类似于希望逐行导出该文本,这样您就可以在之前立即始终如一地找到您的目标!或在 ALTERNATE 之后。

N.B Mutool convert to HTML 会将目标值放在关键字后的 table 条目中,如果行数一致,那将是一种更简单的方法查找或grep。