31

如果我使用 urllib2 打开一个文件,如下所示:

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

除了解析原始 URL 之外,是否有一种简单的方法来获取文件名?

编辑:将 openfile 更改为 urlopen ...不知道这是怎么发生的。

EDIT2:我最终使用:

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

除非我弄错了,否则这也应该排除所有潜在的查询。

4

14 回答 14

49

你的意思是urllib2.urlopen吗?

如果服务器通过检查发送 Content-Disposition 标头,您可能会提升预期的文件名,但我认为您只需要解析 url。remotefile.info()['Content-Disposition']

您可以使用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'
于 2008-10-02T15:43:12.970 回答
13

如果您只想要文件名本身,假设末尾没有查询变量,例如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 或文件路径的最后部分。

于 2008-10-02T16:06:16.720 回答
7

我认为当涉及到 http 传输时,“文件名”不是一个很好定义的概念。服务器可能(但不是必须)提供一个作为“内容处置”标头,您可以尝试使用remotefile.headers['Content-Disposition']. 如果失败,您可能必须自己解析 URI。

于 2008-10-02T15:43:10.130 回答
6

刚看到这个我通常做的..

filename = url.split("?")[0].split("/")[-1]
于 2015-03-20T18:38:47.497 回答
4

使用urlsplit是最安全的选择:

url = 'http://example.com/somefile.zip'
urlparse.urlsplit(url).path.split('/')[-1]
于 2013-03-31T20:05:36.643 回答
2

你的意思是urllib2.urlopenopenfile模块中没有调用函数urllib2

无论如何,使用以下urllib2.urlparse功能:

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

瞧。

于 2008-10-02T15:42:59.867 回答
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)
于 2015-05-11T06:15:24.877 回答
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)
于 2016-04-28T14:41:39.770 回答
1

我想这取决于你所说的解析的意思。如果不解析 URL,就无法获取文件名,即远程服务器不给您文件名。但是,您不必自己做太多事情,有以下urlparse模块:

In [9]: urlparse.urlparse('http://example.com/somefile.zip')
Out[9]: ('http', 'example.com', '/somefile.zip', '', '', '')
于 2008-10-02T15:45:47.147 回答
1

从来没听说过。

但你可以像这样简单地解析它:

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

于 2008-10-02T15:46:49.670 回答
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,但可能仍然有帮助:)

于 2008-10-02T15:45:48.580 回答
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)
于 2014-02-26T20:54:44.823 回答
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
于 2015-09-10T22:31:37.437 回答
0

使用不依赖于操作系统并优雅处理 url 的PurePosixPath是 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'

请注意这里没有网络流量或任何东西(即那些 url 不会去任何地方) - 只需使用标准解析规则。

于 2016-04-11T19:28:35.967 回答