直接在Python中处理来自网页的PDF?

3 投票
2 回答
6886 浏览
提问于 2025-04-18 03:13

我想用Python直接从网上读取.pdf文件,而不是把它们都保存到我的电脑上。我只需要.pdf里的文字,而且我需要读取的数量很多(大约6万份),所以我希望不必把它们全部保存下来。

我知道怎么用urllib从网上保存一个.pdf文件,然后用PyPDF2打开它。(例子)

我想跳过保存到文件这一步。

import urllib, PyPDF2
urllib.urlopen('https://bitcoin.org/bitcoin.pdf')
wFile = urllib.urlopen('https://bitcoin.org/bitcoin.pdf')
lFile = PyPDF2.pdf.PdfFileReader(wFile.read())

我遇到了一个比较容易理解的错误:

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    fil = PyPDF2.pdf.PdfFileReader(wFile.read())
  File "C:\Python27\lib\PyPDF2\pdf.py", line 797, in __init__
    self.read(stream)
  File "C:\Python27\lib\PyPDF2\pdf.py", line 1245, in read
    stream.seek(-1, 2)
AttributeError: 'str' object has no attribute 'seek'

显然,PyPDF2不喜欢我给它的是urllib.urlopen().read()(这看起来返回的是一个字符串)。我知道这个字符串并不是.pdf的“文本”,而是文件的字符串表示。那我该怎么解决这个问题呢?

编辑:NorthCat的解决方案解决了我的错误,但当我尝试实际提取文本时,我得到了这个:

>>> print lFile.getPage(0).extractText()
ˇˆ˘˘˙˘˘˝˘˛˘ˇ˘ˇ˚ˇˇˇ˘ˆ˘˘˘˚ˇˆ˘ˆ˘ˇ˜ˇ˝˚˘˛˘ˇ ˘˘˘ˇ˛˘˚˚ˆˇˇ!
˝˘˚ˇ˘˘˚"˘˘ˇ˘˚ˇ˘˘˚ˇ˘˘˘˙˘˘˘#˘˘˘ˆ˘˛˘˚˛˙ ˘˘˚˚˘˛˙#˘ˇ˘ˇˆ˘˘˛˛˘˘!˘˘˛˘˝˘˘˘˚ ˛˘˘ˇ˘ˇ˛$%&˘ˇ'ˆ˛
$%&˘ˇˇ˘˚ˆ˚˘˘˘˘ ˘ˆ(ˇˇ˘˘˘˘ˇ˘˚˘˘#˘˘˘ˇ˛!ˇ)˘˘˚˘˘˛ ˚˚˘ˇ˘˝˘˚'˘˘ˇˇ ˘˘ˇ˘˛˙˛˛˘˘˚ˇ˘˘ˆ˘˘ˆ˙
$˘˘˘*˘˘˘ˇˆ˘˘ˇˆ˛ˇ˘˝˚˚˘˘ˇ˘ˆ˘"˘ˆ˘ˇˇ˘˛ ˛˛˘˛˘˘˘˘˘˘˛˘˘˚˚˘$ˇ˘ˇˆ˙˘˝˘ˇ˘˘˘ˇˇˆˇ˘ ˘˛ˇ˝˘˚˚#˘˛˘˚˘˘ 
˘ˇ˘˚˛˛˘ˆ˛ˇˇˇ ˚˘˘˚˘˘ˇ˛˘˙˘˝˘ˇ˘ˆ˘˛˙˘˝˘ˇ˘˘˝˘"˘˛˘˝˘ˇ ˘˘˘˚˛˘˚)˘˘ˆ˛˘˘ 
˘˛˘˛˘ˆˇ˚˘˘˘˘˚˘˘˘˘˛˛˚˘˚˝˚ˇ˘#˘˘˚ˆ˘˘˘˝˘˚˘ˆˆˇ˘ˆ 
˘˘˘ˆ˘˝˘˘˚"˘˘˚˘˚˘ˇ˘ˆ˘ˆ˘˚ˆ˛˚˛ˆ˚˘˘˘˘˘˘˚˛˚˚ˆ#˘ˇˇˆˇ˘˝˘˘ˇ˚˘ˇˇ˘˛˛˚ ˚˘˘˘ˇ˚˘˘ˇ˘˘˚ˆ˘*˘ 
˘˘ˇ˘˚ˇ˘˙˘˚ˇ˘˘˘˙˙˘˘˚˚˘˘˝˘˘˘˛˛˘ˇˇ˚˘˛#˘ˆ˘˘ˇ˘˚˘ˇˇ˘˘ˇˆˇ˘$%&˘ˆ˘˛˘˚˘,

2 个回答

1

试试这个:

import urllib, PyPDF2
import cStringIO

wFile = urllib.urlopen('https://bitcoin.org/bitcoin.pdf')
lFile = PyPDF2.pdf.PdfFileReader( cStringIO.StringIO(wFile.read()) )

因为 PyPDF2 不能用,所以有几个解决办法,不过这些办法需要把文件保存到硬盘上。

解决办法 1 如果你用的是 Linux 或 Mac,可以用 ps2ascii;如果是 Windows,可以用 xpdf。下面是使用 xpdf 的例子:

import os
os.system('C:\\xpdfbin-win-3.03\\bin32\\pdftotext.exe C:\\xpdfbin-win-3.03\\bin32\\bitcoin.pdf bitcoin1.txt')

或者

import subprocess
subprocess.call(['C:\\xpdfbin-win-3.03\\bin32\\pdftotext.exe',  'C:\\xpdfbin-win-3.03\\bin32\\bitcoin.pdf', 'bitcoin2.txt'])

解决办法 2 你可以使用一些在线的 PDF 转 TXT 工具。比如可以用 pdf.my-addr.com

import MultipartPostHandler
import urllib2


def pdf2text( absolute_path ):
    url = 'http://pdf.my-addr.com/pdf-to-text-converter-tool.php'

    params = {  'file' : open( absolute_path, 'rb' ),
                'encoding': 'UTF-8',
    }
    opener = urllib2.build_opener( MultipartPostHandler.MultipartPostHandler )
    return opener.open( url, params ).read()

print pdf2text('bitcoin.pdf')

关于 MultipartPostHandler 的代码,你可以在 这里找到。我试着用 cStringIO 替代 open(),但没有成功。也许这对你会有帮助。

2

我知道这个问题已经很久了,但我也遇到过同样的问题,这里是我解决它的方法。

在Py2PDF的新文档里,有一部分讲的是流式数据

那里的例子是这样的:

from io import BytesIO

# Prepare example
with open("example.pdf", "rb") as fh:
    bytes_stream = BytesIO(fh.read())

# Read from bytes_stream
reader = PdfReader(bytes_stream)

所以,我做的事情是这样的:

import urllib
from io import BytesIO
from PyPDF2 import PdfReader

NEW_PATH = 'https://example.com/path/to/pdf/online?id=123456789&date=2022060'

wFile = urllib.request.urlopen(NEW_PATH)
bytes_stream = BytesIO(wFile.read())

reader = PdfReader(bytes_stream)

撰写回答