55

urllib.urlretrieve即使远程http服务器上不存在该文件,它也会静默返回,它只是将一个html页面保存到命名文件中。例如:

urllib.urlretrieve('http://google.com/abc.jpg', 'abc.jpg')

只是静默返回,即使 google.com 服务器上不存在 abc.jpg,生成abc.jpg的也不是有效的 jpg 文件,它实际上是一个 html 页面。我猜返回的标头(httplib.HTTPMessage 实例)可用于实际判断检索是否成功,但我找不到任何httplib.HTTPMessage.

任何人都可以提供有关此问题的一些信息吗?

4

8 回答 8

27

urllib2如果可能,请考虑在您的情况下使用。它比urllib.

您可以轻松检测任何 HTTP 错误:

>>> import urllib2
>>> resp = urllib2.urlopen("http://google.com/abc.jpg")
Traceback (most recent call last):
<<MANY LINES SKIPPED>>
urllib2.HTTPError: HTTP Error 404: Not Found

resp实际上是HTTPResponse一个对象,你可以用它做很多有用的事情:

>>> resp = urllib2.urlopen("http://google.com/")
>>> resp.code
200
>>> resp.headers["content-type"]
'text/html; charset=windows-1251'
>>> resp.read()
"<<ACTUAL HTML>>"
于 2009-06-12T18:46:04.507 回答
7

我保持简单:

# Simple downloading with progress indicator, by Cees Timmerman, 16mar12.

import urllib2

remote = r"http://some.big.file"
local = r"c:\downloads\bigfile.dat"

u = urllib2.urlopen(remote)
h = u.info()
totalSize = int(h["Content-Length"])

print "Downloading %s bytes..." % totalSize,
fp = open(local, 'wb')

blockSize = 8192 #100000 # urllib.urlretrieve uses 8192
count = 0
while True:
    chunk = u.read(blockSize)
    if not chunk: break
    fp.write(chunk)
    count += 1
    if totalSize > 0:
        percent = int(count * blockSize * 100 / totalSize)
        if percent > 100: percent = 100
        print "%2d%%" % percent,
        if percent < 100:
            print "\b\b\b\b\b",  # Erase "NN% "
        else:
            print "Done."

fp.flush()
fp.close()
if not totalSize:
    print
于 2012-03-16T16:02:06.667 回答
5

根据文档是无证的

要访问消息,您似乎执行以下操作:

a, b=urllib.urlretrieve('http://google.com/abc.jpg', r'c:\abc.jpg')

b 是消息实例

既然我已经学会了 Python,那么在我打字时使用 Python 的内省能力总是很有用的

dir(b) 

我看到很多方法或功能可以玩

然后我开始用 b 做事

例如

b.items()

列出了很多有趣的东西,我怀疑玩这些东西会让你得到你想要操纵的属性。

抱歉,这是一个初学者的答案,但我正在努力掌握如何使用内省能力来提高我的学习能力,而你的问题刚刚出现。

好吧,我尝试了一些与此相关的有趣的东西——我想知道我是否可以自动从目录中出现的每个不需要参数的东西中获取输出,所以我写道:

needparam=[]
for each in dir(b):
    x='b.'+each+'()'
    try:
        eval(x)
        print x
    except:
        needparam.append(x)
于 2009-06-12T17:21:43.040 回答
2

您可以创建一个新的 URLopener(从 FancyURLopener 继承)并以任何您想要的方式抛出异常或处理错误。不幸的是,FancyURLopener 忽略了 404 和其他错误。看到这个问题:

如何在 urllib.urlretrieve 中捕获 404 错误

于 2010-01-02T22:36:30.440 回答
1

我最终完成了自己的retrieve实现,借助pycurl它支持比 urllib/urllib2 更多的协议,希望它可以帮助其他人。

import tempfile
import pycurl
import os

def get_filename_parts_from_url(url):
    fullname = url.split('/')[-1].split('#')[0].split('?')[0]
    t = list(os.path.splitext(fullname))
    if t[1]:
        t[1] = t[1][1:]
    return t

def retrieve(url, filename=None):
    if not filename:
        garbage, suffix = get_filename_parts_from_url(url)
        f = tempfile.NamedTemporaryFile(suffix = '.' + suffix, delete=False)
        filename = f.name
    else:
        f = open(filename, 'wb')
    c = pycurl.Curl()
    c.setopt(pycurl.URL, str(url))
    c.setopt(pycurl.WRITEFUNCTION, f.write)
    try:
        c.perform()
    except:
        filename = None
    finally:
        c.close()
        f.close()
    return filename
于 2009-06-13T09:18:53.347 回答
0
class MyURLopener(urllib.FancyURLopener):
    http_error_default = urllib.URLopener.http_error_default

url = "http://page404.com"
filename = "download.txt"
def reporthook(blockcount, blocksize, totalsize):
    pass
    ...

try:
    (f,headers)=MyURLopener().retrieve(url, filename, reporthook)
except Exception, e:
    print e
于 2016-03-03T08:53:22.173 回答
0

:) 我在 StackOverflow 上的第一篇文章,多年来一直是潜伏者。:)

可悲的是 dir(urllib.urlretrieve) 缺乏有用的信息。所以从这个线程到目前为止我试着写这个:

a,b = urllib.urlretrieve(imgURL, saveTo)
print "A:", a
print "B:", b

产生了这个:

A: /home/myuser/targetfile.gif
B: Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: max-age=604800
Content-Type: image/gif
Date: Mon, 07 Mar 2016 23:37:34 GMT
Etag: "4e1a5d9cc0857184df682518b9b0da33"
Last-Modified: Sun, 06 Mar 2016 21:16:48 GMT
Server: ECS (hnd/057A)
Timing-Allow-Origin: *
X-Cache: HIT
Content-Length: 27027
Connection: close

我想可以检查一下:

if b.Content-Length > 0:

我的下一步是测试检索失败的场景......

于 2016-03-07T23:44:29.610 回答
0

针对另一台服务器/网站的结果 - “B”中返回的内容有点随机,但可以测试某些值:

A: get_good.jpg
B: Date: Tue, 08 Mar 2016 00:44:19 GMT
Server: Apache
Last-Modified: Sat, 02 Jan 2016 09:17:21 GMT
ETag: "524cf9-18afe-528565aef9ef0"
Accept-Ranges: bytes
Content-Length: 101118
Connection: close
Content-Type: image/jpeg

A: get_bad.jpg
B: Date: Tue, 08 Mar 2016 00:44:20 GMT
Server: Apache
Content-Length: 1363
X-Frame-Options: deny
Connection: close
Content-Type: text/html

在“坏”的情况下(不存在的图像文件)“B”检索了一小块(Googlebot?)HTML 代码并将其保存为目标,因此 Content-Length 为 1363 字节。

于 2016-03-08T00:53:37.007 回答