Подтвердить что ты не робот

Загрузите и сохраните файл PDF с помощью модуля запросов Python

Я пытаюсь загрузить 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)
   ...: 

Я знаю, что это проблема кодека, но я не могу заставить ее работать.

4b9b3361

Ответ 1

В этом случае вы должны использовать response.content:

with open('/tmp/metadata.pdf', 'wb') as f:
    f.write(response.content)

Из документа:

Вы также можете получить доступ к телу ответа в виде байтов для нетекстовых запросов:

>>> r.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...

Итак, это означает: response.text возвращает результат как строковый объект, используйте его, когда вы загружаете текстовый файл . Например, файл HTML и т.д.

И response.content возвращает результат как объект байта, используйте его, когда вы загружаете двоичный файл. Например, файл 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)

chunk_size - размер блока, который вы хотите использовать. Если вы установите его как 2000, тогда запросы будут загружать этот файл в первые 2000 байты, записывать их в файл и делать это снова, снова и снова, если только это не закончится.

Таким образом, это может сэкономить ваше ОЗУ. Но я предпочел бы использовать response.content вместо этого в этом случае, так как ваш файл невелик. Как видите, использование response.raw является сложным.


Относится:

Ответ 2

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

Ответ 3

Пожалуйста, обратите внимание, что я новичок. Если мое решение неверно, пожалуйста, исправьте и/или дайте мне знать. Я тоже могу узнать что-то новое.

Мое решение:

Измените путь загрузки в соответствии с тем, где вы хотите сохранить файл. Не стесняйтесь использовать абсолютный путь тоже для вашего использования.

Сохраните ниже как downloadFile.py.

Использование: python downloadFile.py url-of-the-file-to-download new-file-name.extension

Не забудьте добавить расширение!

Пример использования: python downloadFile.py http://www.google.co.uk google.html

import requests
import sys
import os

def downloadFile(url, fileName):
    with open(fileName, "wb") as file:
        response = requests.get(url)
        file.write(response.content)


scriptPath = sys.path[0]
downloadPath = os.path.join(scriptPath, '../Downloads/')
url = sys.argv[1]
fileName = sys.argv[2]      
print('path of the script: ' + scriptPath)
print('downloading file to: ' + downloadPath)
downloadFile(url, downloadPath + fileName)
print('file downloaded...')
print('exiting program...')

Ответ 4

относительно ответа Кевина на запись в папку tmp, это должно быть примерно так:

with open('./tmp/metadata.pdf', 'wb') as f:
    f.write(response.content)

он забыл . перед адресом и, конечно, ваша папка tmp должна была быть уже создана