urllib2文件名

31

如果我使用urllib2打开一个文件,像这样:

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

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

编辑:将openfile更改为urlopen...不确定怎么会发生这种情况。

编辑2:我最终使用了:

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

除非我弄错了,这应该会删除所有可能的查询。


我认为这不正确。我的意思是urllib2.openfile(...)。 - user15453
请确保您在这两种情况下知道自己想要什么:带斜杠的路径(http://example.com/somefile/)和没有路径的情况:http://example.com。您的示例肯定会在后者上失败(返回“example.com”)。@insin的最终答案也是如此。这就是为什么使用urlsplit是一个好建议的另一个原因。 - nealmcb
从响应头获取文件名:https://dev59.com/Qmgt5IYBdhLWcg3w0w3B - jozxyqk
这里有很多答案都忽略了一个事实,即查找文件名的地方有两个:URL和Content-Disposition头字段。所有提到头部的当前答案都忽略了cgi.parse_header()会正确解析它的事实。这里有一个更好的答案:https://dev59.com/Qmgt5IYBdhLWcg3w0w3B#11783319 - ʇsәɹoɈ
14个回答

49

您是不是要使用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'

7
改用posixpath.basename()函数代替手动使用'/'来分割路径。 - Thomas Wouters
8
我会始终使用urlsplit(),而不是直接对字符串进行分割。如果你的URL带有片段或查询附加,例如http://example.com/filename.html?cookie=55#Section_3,则直接字符串分割会出错。 - Dan Lenski
转义字符怎么办?应该先解码吗? - awiebe

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或文件路径的最后一个部分。


3
使用 os.path 解析 URL 似乎依赖于当前操作系统以与 URL 相同的方式拆分路径。我认为这并不保证在每个操作系统上都能实现。 - Rafał Dowgird
1
这个在Windows上行不通。改用import posixpath; posixpath.basename - j08lue

7

我认为,在http传输中,“文件名”并不是一个非常明确定义的概念。服务器可能会(但不一定)提供“content-disposition”头作为文件名,您可以使用remotefile.headers['Content-Disposition']来尝试获取它。如果失败了,您可能需要自己解析URI。


6

Just saw this I normally do..

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

4

使用urlsplit是最安全的选择:

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

2
< p > 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)

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)

2

您是指urllib2.urlopen吗?在urllib2模块中没有名为openfile的函数。

无论如何,使用urllib2.urlparse函数:

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

看这里。


1

我不知道有没有这样的功能。

但是你可以像这样轻松地解析它:

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


1
我猜这取决于您对解析的理解。没有办法在不解析URL的情况下获取文件名,也就是远程服务器不会提供文件名。但是,您不必自己做太多工作,可以使用 urlparse 模块:
In [9]: urlparse.urlparse('http://example.com/somefile.zip')
Out[9]: ('http', 'example.com', '/somefile.zip', '', '', '')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接