不提供文件名的Python下载
如何使用python下载带有进度报告的文件,但不提供文件名不提供文件名的Python下载,python,download,urllib2,urllib,Python,Download,Urllib2,Urllib,如何使用python下载带有进度报告的文件,但不提供文件名 import urllib, urlparse split = urlparse.urlsplit(url) filename = "/tmp/" + split.path.split("/")[-1] urllib.urlretrieve(url, filename) 我尝试了urllib.urlretrieve,但似乎必须为下载的文件提供一个文件名才能另存为 例如: 我不想提供这个: urllib.urlretrieve("ht
import urllib, urlparse
split = urlparse.urlsplit(url)
filename = "/tmp/" + split.path.split("/")[-1]
urllib.urlretrieve(url, filename)
我尝试了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'
也无法从某些URL获取文件名
例如:
有,它创建了一个类似文件的对象,可用于读取数据,而无需将数据保存到本地文件:
from urllib2 import urlopen
f = urlopen("http://example.com/")
for line in f:
print len(line)
f.close()
(我不确定这是否是你想要的。)问题澄清后编辑
urlparse.urlspilt
将获取您正在打开的url并将其拆分为其组成部分,然后您可以获取路径
部分并使用最后一个/
分隔的区块作为文件名
import urllib, urlparse
split = urlparse.urlsplit(url)
filename = "/tmp/" + split.path.split("/")[-1]
urllib.urlretrieve(url, filename)
您指定的URL根本不引用文件。这是一个指向网页的重定向,该网页运行一些javascript,使您的web浏览器下载该文件。我的浏览器从相关URL定向到(镜像)的实际地址是:
http://mozilla.mirrors.evolva.ro//firefox/releases/3.6.3/win32/en-US/Firefox%20Setup%203.6.3.exe
我相信有两种方式可以让web服务器指定下载文件的名称
对于要下载的文件,我认为您只需要URL的最后一个路径段(但使用文件的实际URL,而不是选择要使用哪个镜像文件的网页)。但对于某些下载,您需要从
内容处置
标题获取要使用的文件名 快速查看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;
因此,只需将您的url更改为:
http://www.mozilla.com/products/download.html?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。所需的代码我将留给您,但希望这将为您指明正确的方向。将使用传递给它的URL的basename作为文件名。请注意,它将忽略内容处置
标题。我以
os.system('wget -P /tmp http://www.mozilla.com/products/download.html?'
'product=firefox-3.6.3&os=win&lang=en-US')
以下是使用python3和url中未指定文件名的完整方法:
from urllib.request import urlopen
from urllib.request import urlretrieve
import cgi
url = "http://cloud.ine.ru/s/JDbPr6W4QXnXKgo/download"
remotefile = urlopen(url)
blah = remotefile.info()['Content-Disposition']
value, params = cgi.parse_header(blah)
filename = params["filename"]
urlretrieve(url, filename)
结果你应该得到
cargo\u live\u animals\u parrot.jpg
文件如果你不知道下载什么,你怎么能下载?你需要一些标识符。请澄清您的问题。对不起,我指的是一个文件名,供下载保存为。我知道网址。我希望这是有意义的。不确定我是否理解你的问题:你想从给定的URL提取一个文件名,然后将其用作用户定义目录下的文件名?不完全是,我刚刚用一个示例编辑了我的问题,希望这有助于感谢你的回答。问题是此URL不包含文件名。谢谢你的回复!那么,当图像URL不包含扩展名时,您是如何解决的呢?可能您应该添加--trust server names开关,以便wget使用Content Disposition提供的名称。这是最好的答案,因为它考虑到服务器可以选择与URL完全不同的文件名。
import shutil
import urllib.parse
import urllib.request
import os
urls = {
'just_filename' : 'https://github.com/bits4waves/100daysofpractice-dataset/raw/master/requirements.txt',
'filename_with_params' : 'https://github.com/bits4waves/resonometer/blob/master/sound/violin-A-pluck.wav?raw=true',
'no_filename' : 'https://download.mozilla.org/?product=firefox-latest-ssl&os=linux64&lang=en-US',
}
for url in urls.values():
with urllib.request.urlopen(url) as response:
parsed_url_path = urllib.parse.urlparse(response.url).path
filename = os.path.basename(parsed_url_path)
with open(filename, 'w+b') as f:
shutil.copyfileobj(response, f)