14

我有一个包含几个超链接的 PDF 文档,我需要从 pdf 中提取所有文本。我使用了 PDFMiner 库和来自 http://www.endliescurious.com/2012/06/13/scraping-pdf-with-python/的代码来提取文本。但是,它不会提取超链接。

例如,我的文本显示Check this link out,并附有一个链接。我能够提取单词Check this link out,但我真正需要的是超链接本身,而不是单词。

我该怎么做呢?理想情况下,我更喜欢用 Python 来做,但我也愿意用任何其他语言来做。

我看过itextsharp,但没用过。我正在运行Ubuntu,并希望得到任何帮助。

4

6 回答 6

11

这是一个老问题,但似乎很多人都在关注它(包括我在尝试回答这个问题时),所以我分享了我想出的答案。附带说明一下,学习如何使用 Python 调试器 (pdb) 很有帮助,因此您可以即时检查这些对象。

可以使用 PDFMiner 获取超链接。复杂之处在于(就像很多关于 PDF 的情况一样),链接注释和链接文本之间实际上没有任何关系,只是它们都位于页面的同一区域。

这是我用来在 PDFPage 上获取链接的代码

annotationList = []
if page.annots:
    for annotation in page.annots.resolve():
        annotationDict = annotation.resolve()
        if str(annotationDict["Subtype"]) != "/Link":
            # Skip over any annotations that are not links
            continue
        position = annotationDict["Rect"]
        uriDict = annotationDict["A"].resolve()
        # This has always been true so far.
        assert str(uriDict["S"]) == "/URI"
        # Some of my URI's have spaces.
        uri = uriDict["URI"].replace(" ", "%20")
        annotationList.append((position, uri))

然后我定义了一个函数,如:

def getOverlappingLink(annotationList, element):
    for (x0, y0, x1, y1), url in annotationList:
        if x0 > element.x1 or element.x0 > x1:
            continue
        if y0 > element.y1 or element.y0 > y1:
            continue
        return url
    else:
        return None

我用来搜索之前在页面上找到的 annotationList,以查看是否有任何超链接与我在页面上检查的 LTTextBoxHorizo​​ntal 占用相同的区域。

在我的例子中,由于 PDFMiner 在文本框中合并了太多文本,我浏览了每个文本框的 _objs 属性并查看了所有 LTTextLineHorizo​​ntal 实例,看看它们是否与任何注释位置重叠。

于 2018-04-02T16:13:05.487 回答
10

Ashwin 的回答稍作修改:

import PyPDF2
PDFFile = open("file.pdf",'rb')

PDF = PyPDF2.PdfFileReader(PDFFile)
pages = PDF.getNumPages()
key = '/Annots'
uri = '/URI'
ank = '/A'

for page in range(pages):
    print("Current Page: {}".format(page))
    pageSliced = PDF.getPage(page)
    pageObject = pageSliced.getObject()
    if key in pageObject.keys():
        ann = pageObject[key]
        for a in ann:
            u = a.getObject()
            if uri in u[ank].keys():
                print(u[ank][uri])
于 2019-05-24T21:23:26.923 回答
6

我认为使用 PyPDF 你可以做到这一点。如果要从 PDF 中提取链接。我不确定我是从哪里得到的,但它作为其他东西的一部分存在于我的代码中。希望这可以帮助:

PDFFile = open('File Location','rb')

PDF = pyPdf.PdfFileReader(PDFFile)
pages = PDF.getNumPages()
key = '/Annots'
uri = '/URI'
ank = '/A'

for page in range(pages):

    pageSliced = PDF.getPage(page)
    pageObject = pageSliced.getObject()

    if pageObject.has_key(key):
        ann = pageObject[key]
        for a in ann:
            u = a.getObject()
            if u[ank].has_key(uri):
            print u[ank][uri]

我希望这应该在您的 PDF 中提供链接。PS:我没有广泛尝试过这个。

于 2015-02-10T06:37:58.287 回答
1
import pikepdf
pdf_file = pikepdf.Pdf.open("pdf.pdf")    
urls = []
for page in pdf_file.pages:
    for annots in page.get("/Annots"):
        url=annots.get("/A").get("/URI")
        if url is not None:
            urls.append(url)
            urls.append(" ; ")
print(urls)

您将在给定的 PDF 中获得以分号分隔的链接列表

于 2021-01-31T08:48:47.417 回答
0

超链接实际上是注释,因此您需要处理注释而不是“提取文本”。我怀疑如果你真的很绝望(并且在 PostScript 中编程很舒服),你将需要使用 itextsharp、MuPDF 或 Ghostscript 之类的库。

不过,我认为处理寻找 LNK 类型的注释相对容易。

于 2015-01-02T15:16:04.613 回答
0

这是一个以我能找到的最简单的方式创建 URL 列表的版本:

import PyPDF2

pdf = PyPDF2.PdfFileReader('filename.pdf')

urls = []
for page in range(pdf.numPages):
    pdfPage = pdf.getPage(page)
    try:
        for item in (pdfPage['/Annots']):
            urls.append(item['/A']['/URI'])
    except KeyError:
        pass
于 2019-09-27T18:04:13.260 回答