没有提供文件名的Python下载

时间:2010-05-08 19:28:35

标签: python download urllib2 urllib

如何使用python下载包含进度报告的文件,但不提供文件名。

我已经尝试了urllib.urlretrieve,但我似乎必须为下载的文件提供一个文件名以保存为。

例如:

我不想提供这个:

urllib.urlretrieve("http://www.mozilla.com/products/download.html?product=firefox-3.6.3&os=win&lang=en-US", "/tmp/firefox.exe")

就是这样:

urllib.urlretrieve("http://www.mozilla.com/products/download.html?product=firefox-3.6.3&os=win&lang=en-US", "/tmp/")

但如果我这样做,我会收到此错误:

IOError: [Errno 21] Is a directory: '/tmp'

也无法从某个网址获取文件名 例如:

http://www.mozilla.com/products/download.html?product=firefox-3.6.3&os=win&lang=en-US

8 个答案:

答案 0 :(得分:9)

在澄清问题之后编辑了

urlparse.urlsplit将获取您正在打开的网址并将其拆分为其组成部分,然后您可以使用path部分并使用最后/ - 分隔的块作为文件名

import urllib, urlparse

split = urlparse.urlsplit(url)
filename = "/tmp/" + split.path.split("/")[-1]
urllib.urlretrieve(url, filename)

答案 1 :(得分:7)

以下是在python3中完成此操作并且在url中未指定文件名的完整方法:

from urllib.request import urlopen
from urllib.request import urlretrieve
import cgi

url = "https://www.gstatic.com/webp/gallery3/2.png"
remotefile = urlopen(url)
blah = remotefile.info()['Content-Disposition']
value, params = cgi.parse_header(blah)
filename = params["filename"]
urlretrieve(url, filename)

答案 2 :(得分:2)

urlopen,它创建了一个类似文件的对象,可用于读取数据而不将其保存到本地文件:

from urllib2 import urlopen

f = urlopen("http://example.com/")
for line in f:
  print len(line)
f.close()

(我不确定这是否是你所要求的。)

答案 3 :(得分:2)

您指定的网址根本不会引用文件。它是一个重定向到网页,运行一些javascript,导致您的Web浏览器下载该文件。我的浏览器从相关网址引导到(镜像)的实际地址是:

http://mozilla.mirrors.evolva.ro//firefox/releases/3.6.3/win32/en-US/Firefox%20Setup%203.6.3.exe

我认为Web服务器有两种方式指定文件的名称以供下载;

  1. 网址路径的最后一段
  2. Content-Disposition标头,可以指定其他文件名使用
  3. 对于您要下载的文件,我认为您只需要URL的最后一个路径段(但使用文件的实际URL,而不是选择使用哪个镜像文件的网页)。但是对于某些下载,您需要从Content-Disposition标题中获取要使用的文件名。

答案 4 :(得分:1)

我最终得到了

os.system('wget -P /tmp http://www.mozilla.com/products/download.html?'
          'product=firefox-3.6.3&os=win&lang=en-US')

答案 5 :(得分:0)

快速浏览一下firefox页面上的javascript:

// 2. Build download.mozilla.org URL out of those vars.
download_url = "http://download.mozilla.org/?product=";
download_url += product + '&os=' + os + '&lang=' + lang;

所以只需更改您的网址:

http://www.mozilla.com/products/download.html?product=firefox-3.6.3&os=win&lang=en-US

http://download.mozilla.org/?product=firefox-3.6.3&os=win&lang=en-US

所以现在我将检查标题以查看我们真正得到的内容......

$ curl -I "http://download.mozilla.org/?product=firefox-3.6.3&os=win&lang=en-US"
HTTP/1.1 302 Found
Server: Apache
X-Backend-Server: pp-app-dist09
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0, private
Content-Type: text/html; charset=UTF-8
Date: Sat, 08 May 2010 21:02:50 GMT
Location: http://mozilla.mirror.ac.za/firefox/releases/3.6.3/win32/en-US/Firefox Setup 3.6.3.exe
Pragma: no-cache
Transfer-Encoding: chunked
Connection: Keep-Alive
Set-Cookie: dmo=10.8.84.200.1273352570769772; path=/; expires=Sun, 08-May-11 21:02:50 GMT
X-Powered-By: PHP/5.1.6

所以这实际上是302重定向,所以现在使用Location头中的内容作为获取实际文件的新url。你需要弄清楚如何做一个请求并自己阅读标题(对不起,我没有太多时间)。解析位置标题后,您可以使用正则表达式删除其余位置以获取文件名以保存文件:

>>> location = 'http://mozilla.mirror.ac.za/firefox/releases/3.6.3/win32/en-US/Firefox Setup 3.6.3.exe'
>>> re.match('^.*/(.*?)$', location).groups()[0]
'Firefox Setup 3.6.3.exe'

因此,要获得实际文件名,您需要自己遵循302。我需要的代码将由您自己决定,但希望这将指向您正确的方向。

答案 6 :(得分:0)

urlgrabber.urlgrab()将使用传递给它的URL的基名作为文件名。请注意,它会忽略Content-Disposition标题。

答案 7 :(得分:0)

b = ['a', 'b', 'c', 'd', 'e', 'f']