Pregunta

Si abro un archivo usando urllib2, así:

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

¿Existe una forma fácil de obtener el nombre del archivo que no sea analizar la URL original?

EDITAR: se cambió el archivo abierto a urlopen ... no estoy seguro de cómo sucedió.

EDIT2: Terminé usando:

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

A menos que me equivoque, esto también debería eliminar todas las consultas potenciales.

¿Fue útil?

Solución

Quiso decir urllib2.urlopen ?

Podrías levantar el nombre de archivo intentado si el servidor enviara un encabezado de Disposición de Contenido al revisar remotefile.info () ['Content-Disposition' ] , pero como es, creo que tendrás que analizar la url.

Puedes usar urlparse.urlsplit , pero si tienes alguna URL como en el segundo ejemplo, terminarás teniendo que sacar el nombre del archivo de todos modos:

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

También podría hacer esto:

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

Otros consejos

Si solo desea el nombre del archivo, suponiendo que no hay variables de consulta al final como http://example.com/somedir/somefile.zip?foo=bar luego puede usar os.path.basename para esto:

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

Algunos otros carteles mencionados usando urlparse, que funcionarán, pero todavía necesitarías quitar el directorio principal del nombre del archivo. Si usa os.path.basename (), no tiene que preocuparse por eso, ya que solo devuelve la parte final de la URL o la ruta del archivo.

Creo que " el nombre del archivo " no es un concepto muy bien definido cuando se trata de transferencias http. El servidor podría (pero no es obligatorio) proporcionar uno como " content-disposition " encabezado, puede intentar obtener eso con remotefile.headers ['Content-Disposition'] . Si esto falla, probablemente tenga que analizar la URI usted mismo.

Acabo de ver esto, normalmente lo hago ...

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

Usar urlsplit es la opción más segura:

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

¿Quieres decir urllib2.urlopen ? No hay ninguna función llamada openfile en el módulo urllib2 .

De todos modos, use las funciones urllib2.urlparse :

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

Voila.

También puedes combinar las dos respuestas mejor calificadas: Usando urllib2.urlparse.urlsplit () para obtener la parte de la ruta de la URL, y luego os.path.basename para el nombre del archivo real.

El código completo sería:

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

La función os.path.basename funciona no solo para rutas de archivos, sino también para urls, por lo que no tiene que analizar manualmente la URL. Además, es importante tener en cuenta que debes usar result.url en lugar de la url original para seguir las respuestas de redireccionamiento:

import os
import urllib2
result = urllib2.urlopen(url)
real_url = urllib2.urlparse.urlparse(result.url)
filename = os.path.basename(real_url.path)

Supongo que depende de lo que quieras decir al analizar. No hay forma de obtener el nombre de archivo sin analizar la URL, es decir, el servidor remoto no le da un nombre de archivo. Sin embargo, no tiene que hacer mucho por sí mismo, existe el módulo urlparse :

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

no que yo sepa.

pero puedes analizarlo con la misma facilidad:

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

utilizando solicitudes, pero puede hacerlo fácilmente con 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)

Probablemente puedas usar expresiones regulares simples aquí. Algo como:

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

Utilizando PurePosixPath que no es el sistema operativo & # 8212; Dependiente y maneja las URL con gracia es la solución 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'

Observe que no hay tráfico de red aquí ni nada (es decir, esas direcciones URL no van a ninguna parte), solo se usan las reglas de análisis estándar.

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

os.path.split(my_url)[1]

# 'index.html'

Esto no es un archivo abierto, pero quizás todavía ayude :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top