urllib2 文件名
Posted
技术标签:
【中文标题】urllib2 文件名【英文标题】:urllib2 file name 【发布时间】:2010-09-14 20:22:34 【问题描述】:如果我使用 urllib2 打开一个文件,像这样:
remotefile = urllib2.urlopen('http://example.com/somefile.zip')
除了解析原始 URL 之外,有没有一种简单的方法来获取文件名?
编辑:将 openfile 更改为 urlopen...不确定这是怎么发生的。
EDIT2:我最终使用了:
filename = url.split('/')[-1].split('#')[0].split('?')[0]
除非我弄错了,否则这也应该排除所有潜在的查询。
【问题讨论】:
我认为这不正确。我的意思是 urllib2.openfile(...) 请确保您知道在这两种情况下您想要什么:斜杠 (http://example.com/somefile/
) 并且没有路径:http://example.com
您的示例肯定会在后者上失败(返回“example.com ”)。 @insin 的最终答案也是如此。这也是为什么使用 urlsplit 是个好建议的另一个原因。
来自响应头:***.com/questions/11783269/…
这里的很多答案都忽略了一个事实,即有两个地方可以查找文件名:URL 和 Content-Disposition 标头字段。当前所有提及标头的答案都忽略了提及 cgi.parse_header() 将正确解析它。这里有更好的答案:***.com/a/11783319/205212
【参考方案1】:
你的意思是urllib2.urlopen
? urllib2
模块中没有名为 openfile
的函数。
无论如何,使用urllib2.urlparse
函数:
>>> from urllib2 import urlparse
>>> print urlparse.urlsplit('http://example.com/somefile.zip')
('http', 'example.com', '/somefile.zip', '', '')
瞧。
【讨论】:
【参考方案2】:我认为当涉及到 http 传输时,“文件名”不是一个很好定义的概念。服务器可能(但不是必须)提供一个作为“content-disposition”标头,您可以尝试使用remotefile.headers['Content-Disposition']
来获得它。如果失败,您可能必须自己解析 URI。
【讨论】:
【参考方案3】:你是说urllib2.urlopen吗?
您可能会通过检查remotefile.info()['Content-Disposition']
来解除 intended 文件名 if 服务器正在发送 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'
【讨论】:
使用 posixpath.basename() 而不是在 '/' 上手动拆分。 我会总是使用 urlsplit() 并且从不直接拆分字符串。如果您有一个附加了片段或查询的 URL,例如example.com/filename.html?cookie=55#Section_3,后者会阻塞。 转义字符呢?应该先解码吗?【参考方案4】:我想这取决于你所说的解析是什么意思。不解析 URL 就无法获取文件名,即远程服务器不给你文件名。但是,您不必自己做太多事情,这里有 urlparse
模块:
In [9]: urlparse.urlparse('http://example.com/somefile.zip')
Out[9]: ('http', 'example.com', '/somefile.zip', '', '', '')
【讨论】:
【参考方案5】:import os,urllib2
resp = urllib2.urlopen('http://www.example.com/index.html')
my_url = resp.geturl()
os.path.split(my_url)[1]
# 'index.html'
这不是打开文件,但也许仍然有帮助:)
【讨论】:
【参考方案6】:我不知道。
但你可以像这样简单地解析它:
url = 'http://example.com/somefile.zip'
print url.split('/')[-1]
【讨论】:
【参考方案7】:如果您只想要文件名本身,假设末尾没有像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 或文件路径的最后部分。
【讨论】:
使用os.path
解析 URL 似乎依赖于当前操作系统的拆分路径,就像拆分 URL 一样。我不认为每个操作系统都可以保证。
这在 Windows 上不起作用。请改用import posixpath; posixpath.basename
。【参考方案8】:
使用urlsplit
是最安全的选择:
url = 'http://example.com/somefile.zip'
urlparse.urlsplit(url).path.split('/')[-1]
【讨论】:
【参考方案9】:使用请求,但您可以使用 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)
【讨论】:
【参考方案10】:刚看到这个,我通常这样做..
filename = url.split("?")[0].split("/")[-1]
【讨论】:
【参考方案11】: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)
【讨论】:
【参考方案12】:您可能可以在这里使用简单的正则表达式。比如:
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
【讨论】:
【参考方案13】:使用不依赖于操作系统的PurePosixPath 并优雅地处理 url 是 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 不会去任何地方) - 只需使用标准解析规则。
【讨论】:
【参考方案14】:您还可以将两个评分最高的答案结合起来: 使用 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)
【讨论】:
以上是关于urllib2 文件名的主要内容,如果未能解决你的问题,请参考以下文章