web-dev-qa-db-fra.com

Téléchargez et enregistrez le fichier PDF avec le module de requêtes Python

J'essaie de télécharger un fichier PDF à partir d'un site Web et de l'enregistrer sur le disque. Mes tentatives échouent avec des erreurs de codage ou donnent des fichiers PDF vierges.

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)
   ...: 

Je sais que c'est un problème de codec mais je n'arrive pas à le faire fonctionner.

52
Jim

Vous devez utiliser response.content dans ce cas:

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

De le document :

Vous pouvez également accéder au corps de la réponse sous forme d'octets, pour les requêtes non textuelles:

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

Cela signifie donc que: response.text renvoie le résultat sous forme d'objet chaîne, utilisez-le lorsque vous téléchargez un fichier texte . Tels qu'un fichier HTML, etc.

Et response.content renvoie la sortie sous forme d'objet octets, utilisez-la lorsque vous téléchargez un fichier binaire . Tels que fichier PDF, fichier audio, image, etc.


Vous pouvez aussi utiliser response.raw à la place . Cependant, utilisez-le lorsque le fichier que vous êtes sur le point de télécharger est volumineux. Voici un exemple de base que vous pouvez également trouver dans le document:

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 est la taille de bloc que vous souhaitez utiliser. Si vous le définissez comme 2000, les requêtes téléchargeront alors les premiers 2000 octets de ce fichier, les écriront dans le fichier et le feront encore et encore, à moins que l'opération ne soit terminée.

Donc, cela peut économiser votre RAM. Mais je préférerais utiliser response.content à la place dans ce cas car votre fichier est petit. Comme vous pouvez le voir, l'utilisation de response.raw est complexe.


Relates:

115
Kevin Guan

Dans Python 3, je trouve que pathlib est le moyen le plus simple de le faire. La demande response.content se marie bien avec _write_bytes_ de pathlib.

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

S'il vous plaît noter que je suis un débutant. Si ma solution est fausse, n'hésitez pas à la corriger et/ou à me le faire savoir. Je peux aussi apprendre quelque chose de nouveau.

Ma solution:

Modifiez le chemin de téléchargement en conséquence à l'emplacement où vous souhaitez que votre fichier soit enregistré. N'hésitez pas à utiliser également le chemin absolu pour votre utilisation.

Enregistrez le fichier ci-dessous sous le nom downloadFile.py.

Utilisation: python downloadFile.py url-of-the-file-to-download new-file-name.extension

N'oubliez pas d'ajouter une extension!

Exemple d'utilisation: 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...')
0
Pawel Flajszer