Question

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

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

Existe-t-il un moyen simple d'obtenir le nom du fichier en analysant 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]

Sauf erreur de ma part, cela devrait également supprimer toutes les requêtes potentielles.

Était-ce utile?

La solution

Voulez-vous dire urllib2.urlopen ?

Vous pourriez potentiellement lever le nom de fichier prévu si le serveur envoyait un en-tête Content-Disposition en vérifiant remotefile.info () ['Content-Disposition' ] , mais comme je pense que vous devrez simplement analyser l'URL.

Vous pouvez utiliser urlparse.urlsplit , mais si vous avez des URL similaires à celles du deuxième exemple, vous devrez quand même extraire le nom du fichier:

>>> 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', '', '')

Vous pourriez aussi bien faire ceci:

>>> 'http://example.com/somefile.zip'.split('/')[-1]
'somefile.zip'
>>> 'http://example.com/somedir/somefile.zip'.split('/')[-1]
'somefile.zip'

Autres conseils

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 cela:

[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'

D'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’aurez pas à vous en inquiéter, car il ne renvoie que la dernière partie de l’URL ou du chemin du fichier.

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

Je viens de voir ce que je fais normalement ..

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

L'utilisation de urlsplit est l'option la plus sûre:

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

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

Dans tous les cas, utilisez les fonctions urllib2.urlparse :

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

Voila.

Vous pouvez également combiner les deux réponses les mieux notées: Utilisation de 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)

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

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 grand-chose 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', '', '', '')

pas que je sache.

mais vous pouvez l’analyser assez facilement comme ceci:

url = 'http://example.com/somefile.zip'
print url.split('/')[-1]

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)

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

Utilisation de PurePosixPath qui n'est pas dépendant du système d'exploitation et gère les URL avec élégance est la solution pythonique:

>>> 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'y a 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.

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

os.path.split(my_url)[1]

# 'index.html'

Ceci n'est pas un fichier ouvert, mais peut-être encore utile:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top