web-dev-qa-db-fra.com

nom de fichier urllib2

Si j'ouvre un fichier en utilisant urllib2, comme ceci:

remotefile = urllib2.urlopen('http://example.com/somefile.Zip')

Existe-t-il un moyen simple d’obtenir le nom du fichier autrement que d’analyser l’URL d’origine?

EDIT: a changé openfile en urlopen ... je ne sais pas comment cela s’est passé.

EDIT2: J'ai fini par utiliser:

filename = url.split('/')[-1].split('#')[0].split('?')[0]

À moins que je ne me trompe, cela devrait également éliminer toutes les requêtes potentielles.

31
defrex

Voulez-vous dire urllib2.urlopen ?

Vous pourriez potentiellement lever le prévu nom_fichier si le serveur envoyait un en-tête Content-Disposition en cochant remotefile.info()['Content-Disposition'], mais comme c'est le cas, je pense que vous devrez simplement analyser l'URL.

Vous pouvez utiliser urlparse.urlsplit, mais si vous avez des URL comme dans le deuxième exemple, vous finirez par extraire le nom du fichier vous-même:

>>> urlparse.urlsplit('http://example.com/somefile.Zip')
('http', 'example.com', '/somefile.Zip', '', '')
>>> urlparse.urlsplit('http://example.com/somedir/somefile.Zip')
('http', 'example.com', '/somedir/somefile.Zip', '', '')

Pourrait aussi bien faire ceci:

>>> 'http://example.com/somefile.Zip'.split('/')[-1]
'somefile.Zip'
>>> 'http://example.com/somedir/somefile.Zip'.split('/')[-1]
'somefile.Zip'
49
Jonny Buchanan

Si vous voulez seulement le nom du fichier lui-même, en supposant qu'il n'y ait pas de variable de requête à la fin comme http://example.com/somedir/somefile.zip?foo=bar vous pouvez utiliser os.path.basename pour ce: 

[user@Host]$ python
Python 2.5.1 (r251:54869, Apr 18 2007, 22:08:04) 
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.path.basename("http://example.com/somefile.Zip")
'somefile.Zip'
>>> os.path.basename("http://example.com/somedir/somefile.Zip")
'somefile.Zip'
>>> os.path.basename("http://example.com/somedir/somefile.zip?foo=bar")
'somefile.zip?foo=bar'

Certaines autres affiches ont mentionné l'utilisation de urlparse, ce qui fonctionnera, mais vous devrez tout de même effacer le répertoire principal du nom du fichier. Si vous utilisez os.path.basename (), vous n'avez pas à vous en préoccuper, car il ne renvoie que la partie finale de l'URL ou du chemin du fichier.

13
Jay

Je pense que le "nom de fichier" n’est pas un concept très bien défini en matière de transferts http. Le serveur peut (mais n'est pas obligé de) en fournir un en-tête de "contenu-disposition", vous pouvez essayer de l'obtenir avec remotefile.headers['Content-Disposition']. Si cela échoue, vous devrez probablement analyser l'URI vous-même.

7
Rafał Dowgird

Je viens de voir ce que je fais normalement ..

filename = url.split("?")[0].split("/")[-1]
5
Ian Starnes

Utiliser urlsplit est l'option la plus sûre:

url = 'http://example.com/somefile.Zip'
urlparse.urlsplit(url).path.split('/')[-1]
4
Filipe Correia

Voulez-vous dire urllib2.urlopen? Il n'y a pas de fonction appelée openfile dans le module urllib2.

Quoi qu’il en soit, utilisez les fonctions urllib2.urlparse:

>>> from urllib2 import urlparse
>>> print urlparse.urlsplit('http://example.com/somefile.Zip')
('http', 'example.com', '/somefile.Zip', '', '')

Voila.

2
Dan Lenski

La fonction os.path.basename fonctionne non seulement pour les chemins de fichiers, mais également pour les URL, vous n'avez donc pas à analyser manuellement l'URL vous-même. De plus, il est important de noter que vous devez utiliser result.url au lieu de l'URL d'origine afin de suivre les réponses de redirection:

import os
import urllib2
result = urllib2.urlopen(url)
real_url = urllib2.urlparse.urlparse(result.url)
filename = os.path.basename(real_url.path)
2
Régis B.

Vous pouvez également combiner les deux réponses les mieux notées: Utilisez urllib2.urlparse.urlsplit () pour obtenir la partie chemin de l’URL, puis os.path.basename pour le nom de fichier actuel.

Le code complet serait:

>>> remotefile=urllib2.urlopen(url)
>>> try:
>>>   filename=remotefile.info()['Content-Disposition']
>>> except KeyError:
>>>   filename=os.path.basename(urllib2.urlparse.urlsplit(url).path)
2
Yth

Je suppose que cela dépend de ce que vous entendez par analyse. Il n’existe aucun moyen d’obtenir le nom de fichier sans analyser l’URL, c’est-à-dire que le serveur distant ne vous fournit pas de nom de fichier. Cependant, vous n'avez pas à faire beaucoup vous-même, il y a le module urlparse:

In [9]: urlparse.urlparse('http://example.com/somefile.Zip')
Out[9]: ('http', 'example.com', '/somefile.Zip', '', '', '')
1
miracle2k

pas que je sache de.

mais vous pouvez l’analyser assez facilement comme ceci:

url = 'http://example.com/somefile.Zip'
print url.split ('/') [- 1] 
 </ pre> </ code>

1
Corey Goldberg

Utiliser PurePosixPath qui n’est pas dépendant du système d’exploitation et gère les URL avec élégance est la solution Pythonic:

>>> from pathlib import PurePosixPath
>>> path = PurePosixPath('http://example.com/somefile.Zip')
>>> path.name
'somefile.Zip'
>>> path = PurePosixPath('http://example.com/nested/somefile.Zip')
>>> path.name
'somefile.Zip'

Notez qu’il n’ya pas de trafic réseau ici ou quoi que ce soit (c’est-à-dire que ces URL ne vont nulle part) - en utilisant simplement des règles d’analyse standard.

0
Adam Nelson
import os,urllib2
resp = urllib2.urlopen('http://www.example.com/index.html')
my_url = resp.geturl()

os.path.split(my_url)[1]

# 'index.html'

Ce n'est pas un openfile, mais ça aide peut-être encore :)

0
user15453

Vous pouvez probablement utiliser une expression régulière simple ici. Quelque chose comme:

In [26]: import re
In [27]: pat = re.compile('.+[\/\?#=]([\w-]+\.[\w-]+(?:\.[\w-]+)?$)')
In [28]: test_set 

['http://www.google.com/a341.tar.gz',
 'http://www.google.com/a341.gz',
 'http://www.google.com/asdasd/aadssd.gz',
 'http://www.google.com/asdasd?aadssd.gz',
 'http://www.google.com/asdasd#blah.gz',
 'http://www.google.com/asdasd?filename=xxxbl.gz']

In [30]: for url in test_set:
   ....:     match = pat.match(url)
   ....:     if match and match.groups():
   ....:         print(match.groups()[0])
   ....:         

a341.tar.gz
a341.gz
aadssd.gz
aadssd.gz
blah.gz
xxxbl.gz
0
Vovan Kuznetsov

utiliser des requêtes, mais vous pouvez le faire facilement avec urllib (2)

import requests
from urllib import unquote
from urlparse import urlparse

sample = requests.get(url)

if sample.status_code == 200:
    #has_key not work here, and this help avoid problem with names

    if filename == False:

        if 'content-disposition' in sample.headers.keys():
            filename = sample.headers['content-disposition'].split('filename=')[-1].replace('"','').replace(';','')

        else:

            filename = urlparse(sample.url).query.split('/')[-1].split('=')[-1].split('&')[-1]

            if not filename:

                if url.split('/')[-1] != '':
                    filename = sample.url.split('/')[-1].split('=')[-1].split('&')[-1]
                    filename = unquote(filename)
0
DoomedRaven