Вопрос

Если я открою файл с помощью urllib2, например, так:

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

Есть ли простой способ получить имя файла, отличное от синтаксического анализа исходного URL?

Редактировать:изменил openfile на urlopen...не уверен, как это произошло.

РЕДАКТИРОВАТЬ 2:В итоге я использовал:

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

Если я не ошибаюсь, это также должно исключить все потенциальные запросы.

Другие советы

Если вам нужно только само имя файла, при условии, что в конце нет переменных запроса, например http://example.com/somedir/somefile.zip?foo=bar , тогда вы можете использовать os.path.basename для этого:

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

В некоторых других постерах упоминалось использование urlparse, который будет работать, но вам все равно нужно будет убрать начальный каталог из имени файла. Если вы используете os.path.basename (), вам не нужно об этом беспокоиться, поскольку он возвращает только последнюю часть URL-адреса или пути к файлу.

Я думаю, что " имя файла " не очень четко определенная концепция, когда речь заходит о http-переводах. Сервер может (но не обязан) указывать его как «расположение содержимого» заголовок, вы можете попытаться получить это с помощью remotefile.headers ['Content-Disposition'] . Если это не удалось, вам, вероятно, придется самостоятельно проанализировать URI.

Только что видел, что я обычно делаю ..

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

Использование urlsplit - самый безопасный вариант:

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

Ты имеешь в виду urllib2.urlopen?Там нет вызываемой функции openfile в urllib2 модуль.

В любом случае, используйте urllib2.urlparse функции:

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

Вуаля.

Вы также можете объединить оба из двух лучших ответов: Используя urllib2.urlparse.urlsplit (), чтобы получить часть пути URL, а затем os.path.basename для фактического имени файла.

Полный код будет:

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

Функция os.path.basename работает не только для путей к файлам, но и для URL-адресов, поэтому вам не нужно вручную анализировать URL-адрес. Также важно отметить, что вы должны использовать result.url вместо исходного URL-адреса, чтобы следовать ответам на перенаправление:

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

Я думаю, это зависит от того, что вы подразумеваете под анализом. Невозможно получить имя файла без разбора URL, то есть удаленный сервер не дает вам имя файла. Однако вам не нужно много делать самостоятельно, есть модуль urlparse :

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

не то, что я знаю.

но вы можете разобрать это достаточно просто, как это:

<код>

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

используя запросы, но вы можете сделать это легко с помощью 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)

Вы, вероятно, можете использовать простое регулярное выражение здесь. Что-то вроде:

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

Использование PurePosixPath , который не является операционной системой & # 8212; зависит и обрабатывает URL-адреса изящно является питоническим решением:

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

Обратите внимание, что здесь нет сетевого трафика или чего-либо еще (т. е. эти URL никуда не денутся) - просто с использованием стандартных правил синтаксического анализа.

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

os.path.split(my_url)[1]

# 'index.html'

Это не openfile, но, возможно, все еще помогает:)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top