Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python urllib2文件名_Python_Url_Urllib2 - Fatal编程技术网

Python urllib2文件名

Python urllib2文件名,python,url,urllib2,Python,Url,Urllib2,如果我使用urllib2打开一个文件,如下所示: remotefile = urllib2.urlopen('http://example.com/somefile.zip') 除了解析原始URL之外,是否有一种简单的方法来获取文件名 编辑:已将openfile更改为urlopen。。。我不知道这是怎么发生的 编辑2:我最终使用了: filename = url.split('/')[-1].split('#')[0].split('?')[0] 除非我弄错了,否则这也应该排除所有潜在的查询

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

remotefile = urllib2.urlopen('http://example.com/somefile.zip')
除了解析原始URL之外,是否有一种简单的方法来获取文件名

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

编辑2:我最终使用了:

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

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

你的意思是
urlib2.urlopen
urllib2
模块中没有名为
openfile
的函数

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

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

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

您的意思是

如果服务器正在发送内容处置头,您可以通过选中
remotefile.info()['Content-Disposition']
,潜在地提升预期的文件名,但实际上,我认为您只需解析url即可

您可以使用
urlparse.urlspit
,但是如果您有第二个示例中所示的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'

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

In [9]: urlparse.urlparse('http://example.com/somefile.zip')
Out[9]: ('http', 'example.com', '/somefile.zip', '', '', '')
这不是openfile,但可能仍然有帮助:)

据我所知,这不是

但您可以像这样很容易地解析它:


如果您只需要文件名本身,假设末尾没有查询变量,那么您可以使用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或文件路径的最后一部分。

使用
urlspit
是最安全的选项:

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

使用请求,但使用urllib(2)可以轻松完成


我只是看到了我通常做的

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

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)

您可能可以在这里使用简单的正则表达式。比如:

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
pythonic解决方案使用不依赖于操作系统且能优雅地处理URL的URL:

>>> 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不会去任何地方)-仅使用标准解析规则。

您还可以将两个最佳答案结合起来: 使用urllib2.urlparse.urlspit()获取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.openfile(…)确保您知道在这两种情况下需要什么:尾部斜杠(
http://example.com/somefile/
)并且没有路径:
http://example.com
您的示例肯定会在后者上失败(返回“example.com”)。@insin的最终答案也是如此。这也是为什么使用URLSPIT是一个好建议的另一个原因。从响应标题来看:这里的许多答案忽略了一个事实,即有两个地方可以查找文件名:URL和内容处置标题字段。当前所有提到头的答案都忽略了提及cgi.parse_header()将正确解析它。这里有一个更好的答案:使用posixpath.basename()而不是在“/”上手动拆分。我将始终使用urlspilt()而不是直接拆分字符串。如果你有一个附加了片段或查询的URL,比如说,后者就会阻塞。那么转义字符呢?是否应该首先解码这些内容?使用
os.path
解析URL似乎依赖于当前操作系统的拆分路径,就像拆分URL一样。我不认为每个操作系统都能保证这一点。这在Windows上不起作用。使用
导入posixpath;改为posixpath.basename
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
>>> 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'
>>> remotefile=urllib2.urlopen(url)
>>> try:
>>>   filename=remotefile.info()['Content-Disposition']
>>> except KeyError:
>>>   filename=os.path.basename(urllib2.urlparse.urlsplit(url).path)