使用Python请求模块下载并保存PDF文件

Jim*_*Jim 63 python python-2.7

我试图从网站下载PDF文件并将其保存到磁盘.我的尝试要么失败,要么编码错误,要么导致空白PDF.

In [1]: import requests

In [2]: url = 'http://www.hrecos.org//images/Data/forweb/HRTVBSH.Metadata.pdf'

In [3]: response = requests.get(url)

In [4]: with open('/tmp/metadata.pdf', 'wb') as f:
   ...:     f.write(response.text)
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-4-4be915a4f032> in <module>()
      1 with open('/tmp/metadata.pdf', 'wb') as f:
----> 2     f.write(response.text)
      3 

UnicodeEncodeError: 'ascii' codec can't encode characters in position 11-14: ordinal not in range(128)

In [5]: import codecs

In [6]: with codecs.open('/tmp/metadata.pdf', 'wb', encoding='utf8') as f:
   ...:     f.write(response.text)
   ...: 
Run Code Online (Sandbox Code Playgroud)

我知道这是某种编解码器问题,但我似乎无法让它工作.

Kev*_*uan 131

response.content在这种情况下你应该使用:

with open('/tmp/metadata.pdf', 'wb') as f:
    f.write(response.content)
Run Code Online (Sandbox Code Playgroud)

文件:

对于非文本请求,您还可以以字节为单位访问响应正文:

>>> r.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...
Run Code Online (Sandbox Code Playgroud)

这意味着:response.text将输出作为字符串对象返回,在下载文本文件时使用它.如HTML文件等

并将response.content输出作为bytes对象返回,在下载二进制文件时使用它.如PDF文件,音频文件,图像等


您还可以使用response.raw代替.但是,当您要下载的文件很大时使用它.以下是您可以在文档中找到的基本示例:

import requests

url = 'http://www.hrecos.org//images/Data/forweb/HRTVBSH.Metadata.pdf'
r = requests.get(url, stream=True)

with open('/tmp/metadata.pdf', 'wb') as fd:
    for chunk in r.iter_content(chunk_size):
        fd.write(chunk)
Run Code Online (Sandbox Code Playgroud)

chunk_size是您要使用的块大小.如果将其设置为2000,则请求将下载该文件的第一个2000字节,将它们写入文件,并一次又一次地执行此操作,除非它完成.

所以这可以节省你的RAM.但我更喜欢response.content在这种情况下使用,因为你的文件很小.如您所见,使用response.raw很复杂.


涉及:


jug*_*ugi 18

您可以使用 urllib:

import urllib.request
urllib.request.urlretrieve(url, "filename.pdf")
Run Code Online (Sandbox Code Playgroud)

  • 说实话,这是最好的一个。 (2认同)
  • `urlretrieve` 依赖全局设置来确定请求标头,这使得它不适合某些用例。 (2认同)

Dou*_*eon 9

在Python 3中,我发现pathlib是执行此操作的最简单方法。请求的response.content与pathlib的_write_bytes_很好地结合在一起。

from pathlib import Path
import requests
filename = Path('metadata.pdf')
url = 'http://www.hrecos.org//images/Data/forweb/HRTVBSH.Metadata.pdf'
response = requests.get(url)
filename.write_bytes(response.content)
Run Code Online (Sandbox Code Playgroud)

  • 感谢您发布此内容。最初的问题是Python 2.7,但我已经继续前进,现在使用Python 3。我不知道pathlib库[版本3.4中的新功能],并将其合并到我当前的项目中。 (5认同)

x89*_*x89 5

通常,这应该适用于 Python3:

import urllib.request 
..
urllib.request.get(url)
Run Code Online (Sandbox Code Playgroud)

请记住,在 Python2 之后 urllib 和 urllib2 无法正常工作。

如果在某些神秘的情况下请求不起作用(发生在我身上),您也可以尝试使用

wget.download(url)
Run Code Online (Sandbox Code Playgroud)

有关的:

这是在网页上查找和下载所有 pdf 文件的不错的解释/解决方案:

https://medium.com/@dementorwriter/notesdownloader-use-web-scraping-to-download-all-pdfs-with-python-511ea9f55e48