2008-10-02 2 views
31

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

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

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

РЕДАКТИРОВАТЬ: изменить открытку в urlopen ... не знаю, как это произошло.

EDIT2: Я закончил с использованием:

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

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

+0

я думаю, что это не Corect. Я имею в виду urllib2.openfile (...) – user15453 2008-10-02 15:35:22

+0

Убедитесь, что вы знаете, что вы хотите в этих двух случаях: trailing slash (`http: // example.com/ somefile /`) и нет пути: `http: // example .com` Ваш пример наверняка провалится на последнем (вернется «example.com»). Итак, окончательный ответ @ insin. Это еще одна причина, почему использование urlsplit - хороший совет. – nealmcb 2012-02-08 23:53:24

+0

из заголовков ответов: https://stackoverflow.com/questions/11783269/python-httplib-urllib-get-filename – jozxyqk 2015-11-01 12:24:35

ответ

47

Возможно, вы имели в виду: urllib2.urlopen?

Вы могли бы потенциально поднять предназначен Имя файла если сервер посылает заголовок Content-Disposition, проверив remotefile.info()['Content-Disposition'], но это я думаю, вы просто должны разобрать URL.

Вы можете использовать urlparse.urlsplit, но если у вас есть какие-либо URL-адресов, как во втором примере, вы будете в конечном итоге, чтобы вытащить имя файла из себя все равно:

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

Может также просто сделать это:

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

Возможно, вы имели в виду: urllib2.urlopen? В модуле urllib2 нет функции openfile.

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

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

вуаля.

7

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

1

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

In [9]: urlparse.urlparse('http://example.com/somefile.zip') 
Out[9]: ('http', 'example.com', '/somefile.zip', '', '', '') 
0
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, но, возможно, до сих пор помогает :)

1

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

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

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

13

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

[[email protected]]$ 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 или файла.

4

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

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

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

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

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

Функция 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) 
0

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

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

Использование PurePosixPath, которая не зависит от операционной системы и обрабатывает URLs изящно это вещий решение:

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

Обратите внимание, как нет сетевого трафика здесь или что-нибудь (то есть те URLs дон 't go where) - просто используя стандартные правила синтаксического анализа.

2

Вы также можете комбинировать оба из двух наиболее подходящих ответов: Используя 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)