题
如果我使用urllib2打开文件,就像这样:
remotefile = urllib2.urlopen('http://example.com/somefile.zip')
是否有一种简单的方法可以获取文件名,然后解析原始URL?
编辑:将openfile更改为urlopen ...不确定是怎么发生的。
EDIT2:我最终使用了:
filename = url.split('/')[-1].split('#')[0].split('?')[0]
除非我弄错了,否则这也应该删除所有可能的查询。
解决方案
您的意思是 urllib2.urlopen 一>
如果服务器正在通过检查 remotefile.info()['Content-Disposition'发送Content-Disposition标头,则可以提升预期的文件名 ]
,但我认为你只需要解析网址。
您可以使用 urlparse.urlsplit
,但如果您有任何类似于第二个示例的网址,那么您最终还是必须自己提取文件名:
>>> 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'
其他提示
如果你只想要文件名本身,假设最后没有查询变量,如 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传输方面,它不是一个非常明确的概念。服务器可以(但不是必须)提供一个作为“content-disposition”的服务器。标题,您可以尝试使用 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
? urllib2
模块中没有名为 openfile
的函数。
无论如何,使用 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。另外,请务必注意,您应该使用 result.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;依赖和优雅地处理网址是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'
注意这里没有网络流量或任何东西(即那些网址没有去任何地方) - 只是使用标准的解析规则。
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,但可能仍有帮助:)