使用Python从PDF中提取超链接

15

我有一个PDF文档,其中有一些超链接,我需要从PDF中提取所有文本。我使用了PDFMiner库和来自这里的代码来提取文本。但是,它并不提取超链接。

例如,我有一段文本,上面写着查看此链接,带有链接。我能够提取单词查看此链接,但我真正需要的是超链接本身,而不是单词。

我该如何做到这一点?理想情况下,我更喜欢用Python实现,但我也愿意用其他语言实现。

我已经看过itextsharp,但没有使用它。我在运行Ubuntu系统,非常感谢任何帮助。

6个回答

13

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])

PdfFileReader方法接受文件作为参数,因此不需要PDFFile对象! - shantanuo

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

我使用之前在页面上找到的注释列表来搜索,以查看任何超链接是否占据了我正在检查页面上的LTTextBoxHorizontal相同的区域。

在我的情况下,由于PDFMiner将太多的文本合并到文本框中,我遍历了每个文本框的_objs属性,并查找了所有LTTextLineHorizontal实例,以查看它们是否与任何注释位置重叠。


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提供链接。 附注:我没有进行全面尝试。

1
这似乎很好用,但我能否提取包含超链接的文本并进行修改? - Sundeep Pidugu

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中。

0

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

我认为很容易处理注释以查找类型LNK。


1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Randomly Named User
1
你需要使用一个库来定位并返回给定页面(或大纲树中)上的所有注释,并返回描述它们的字典。这应该包含要绘制的文本和URL。很抱歉,我无法告诉您要使用哪个库或如何使用它,因为我不知道有任何可以做到这一点的库。 - KenS

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

在项查找时出现“TypeError: 'IndirectObject' object is not subscriptable”错误。 - gasstationwithoutpumps

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接