2010-05-08 6 views
4

Comment télécharger un fichier avec rapport d'avancement en utilisant python mais sans fournir de nom de fichier.Téléchargement de Python sans fournir de nom de fichier

J'ai essayé urllib.urlretrieve mais il me semble que je dois fournir un nom de fichier pour que le fichier téléchargé soit sauvegardé.

Ainsi, par exemple:

Je ne veux pas fournir ceci:

urllib.urlretrieve("http://www.mozilla.com/products/download.html?product=firefox-3.6.3&os=win&lang=en-US", "/tmp/firefox.exe") 

ceci:

urllib.urlretrieve("http://www.mozilla.com/products/download.html?product=firefox-3.6.3&os=win&lang=en-US", "/tmp/") 

mais si je fais je reçois cette erreur:

IOError: [Errno 21] Is a directory: '/tmp' 

Également incapable d'obtenir le filena moi d'une certaine URL Exemple:

http://www.mozilla.com/products/download.html?product=firefox-3.6.3&os=win&lang=en-US

+2

Comment pouvez-vous télécharger quelque chose si vous ne savez pas quoi télécharger? Vous avez besoin d'un identifiant. S'il vous plaît clarifier votre question. –

+1

Désolé je veux dire un nom de fichier pour le téléchargement pour enregistrer sous. Je connais l'URL. J'espère que cela à du sens. –

+0

Je ne sais pas si je comprends votre question: vous voulez extraire un nom de fichier d'une URL donnée, puis l'utiliser comme nom de fichier sous un répertoire défini par l'utilisateur? – Birt

Répondre

8

édité après que la question a été clarifiée ...

urlparse.urlsplit prend l'URL que vous ouvrez et le divise en ses composants, puis vous pouvez prendre la partie path et utiliser le dernier bloc / -delimited comme nom de fichier.

import urllib, urlparse 

split = urlparse.urlsplit(url) 
filename = "/tmp/" + split.path.split("/")[-1] 
urllib.urlretrieve(url, filename) 
+0

Le problème est que cette URL http://www.mozilla.com/products/download.html?product=firefox-3.6. 3 & os = win & lang = fr-US ne contient pas de nom de fichier. Merci pour votre réponse! –

2

Il est urlopen, ce qui crée un objet de type fichier qui peut être utilisé pour lire les données sans l'enregistrer dans un fichier local:

from urllib2 import urlopen 

f = urlopen("http://example.com/") 
for line in f: 
    print len(line) 
f.close() 

(Je ne suis pas vraiment sûr si c'est ce que vous demandez.)

+0

Pas tout à fait, je viens d'éditer ma question avec un exemple d'espoir cela aide Merci pour la réponse –

2

L'URL que vous spécifiez ne fait pas référence à un fichier. C'est une redirection vers une page Web, qui exécute du javascript, qui amène votre navigateur Web à télécharger le fichier. L'adresse réelle mon navigateur a été dirigé vers (un miroir) à partir de l'URL en question est:

http://mozilla.mirrors.evolva.ro//firefox/releases/3.6.3/win32/en-US/Firefox%20Setup%203.6.3.exe 

Je crois qu'il ya deux façons que les serveurs Web spécifient le nom du fichier pour les téléchargements;

  1. Le dernier segment de la route URL
  2. L'en-tête Content-Disposition, qui peut spécifier un autre nom de fichier à utiliser

Pour le fichier que vous voulez télécharger Je pense que vous avez seulement besoin du dernier segment de chemin de l'URL (mais en utilisant l'URL réelle du fichier, pas la page Web qui choisit quel fichier en miroir utiliser). Mais pour certains téléchargements, vous devez obtenir le nom de fichier à utiliser à partir de l'en-tête Content-Disposition.

0

Un coup d'œil sur le javascript sur la page Firefox révèle:

// 2. Build download.mozilla.org URL out of those vars. 
download_url = "http://download.mozilla.org/?product="; 
download_url += product + '&os=' + os + '&lang=' + lang; 

Il suffit donc de modifier votre URL:

http://www.mozilla.com/products/download.html?product=firefox-3.6.3&os=win&lang=en-US 

à

http://download.mozilla.org/?product=firefox-3.6.3&os=win&lang=en-US 

Alors maintenant, je vais vérifier les en-têtes pour voir ce que nous obtenons vraiment ...

$ curl -I "http://download.mozilla.org/?product=firefox-3.6.3&os=win&lang=en-US" 
HTTP/1.1 302 Found 
Server: Apache 
X-Backend-Server: pp-app-dist09 
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0, private 
Content-Type: text/html; charset=UTF-8 
Date: Sat, 08 May 2010 21:02:50 GMT 
Location: http://mozilla.mirror.ac.za/firefox/releases/3.6.3/win32/en-US/Firefox Setup 3.6.3.exe 
Pragma: no-cache 
Transfer-Encoding: chunked 
Connection: Keep-Alive 
Set-Cookie: dmo=10.8.84.200.1273352570769772; path=/; expires=Sun, 08-May-11 21:02:50 GMT 
X-Powered-By: PHP/5.1.6 

Donc, ceci est en fait une redirection 302, alors utilisez maintenant ce qui est dans l'en-tête Location comme votre nouvelle URL pour obtenir le fichier réel. Vous aurez besoin de comprendre comment faire une demande et lire les en-têtes vous-même (désolé, je n'ai pas beaucoup de temps). Une fois que vous analysez l'en-tête de l'emplacement, vous pouvez enlever le reste de l'emplacement en utilisant regex pour obtenir le nom du fichier pour enregistrer le fichier ainsi:

>>> location = 'http://mozilla.mirror.ac.za/firefox/releases/3.6.3/win32/en-US/Firefox Setup 3.6.3.exe' 
>>> re.match('^.*/(.*?)$', location).groups()[0] 
'Firefox Setup 3.6.3.exe' 

Donc, pour obtenir le nom de fichier réel que vous devrez suivre la 302 vous-même. Le code nécessaire pour cela je vous laisse, mais j'espère que cela vous indiquera la bonne direction.

0

utilisera le nom de base de l'URL qui lui a été transmis comme nom de fichier. Notez qu'il ignorera l'en-tête Content-Disposition.

1

J'ai fini avec

os.system('wget -P /tmp http://www.mozilla.com/products/download.html?' 
      'product=firefox-3.6.3&os=win&lang=en-US') 
+0

vous devriez probablement ajouter --trust-server-names switch pour que wget utilise le nom fourni Content-Disposition. – vac

Questions connexes