2009-06-12 87 views
48

urllib.urlretrieve即使該文件在遠程http服務器上不存在,也會以無提示方式返回,它只是將html頁面保存到指定文件中。例如:如何知道urllib.urlretrieve是否成功?

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

只是默默返回,即使abc.jpg的不google.com服務器上,所產生的abc.jpg不是有效的JPG文件,它實際上是一個HTML頁面。我猜測返回的頭文件(一個httplib.HTTPMessage實例)可以用來實際判斷檢索成功與否,但我找不到httplib.HTTPMessage的任何文檔。

任何人都可以提供有關此問題的一些信息?

回答

22

如果可能的話,考慮使用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>>" 
+6

urllib2可以提供urlretrieve的緩存行爲嗎?或者我們不得不重新實現它? – Kiv 2009-06-12 22:45:52

+0

從ActiveState看這個awersome recipie:http://code.activestate.com/recipes/491261/ 我們在我們當前的項目中使用它,完美地工作 – 2009-06-18 05:50:48

+1

urlopen不提供鉤子函數(顯示進度條例如)像urlretrieve。 – 2009-08-20 20:05:29

2

根據該文件是爲undocumented

獲得訪問郵件,它看起來像你這樣做:

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) 
+0

對我來說沒有身份,你的代碼只能工作一次。嘗試`在b中輸入k:print'%s:%r「%(k,b [k])` – 2012-03-16 16:35:10

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 
2

您可以創建一個新的URLopener(從FancyURLopener繼承),並拋出異常或錯誤處理任何你想要的方式。不幸的是,FancyURLopener忽略404和其他錯誤。看到這個問題:

How to catch 404 error in urllib.urlretrieve

6

我把它簡單:

# 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 
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 
0

:)我在計算器上的第一篇文章,是一個潛伏者多年。 :)

可悲的是目錄(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: 

我的下一步是測試方案檢索失敗...

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字節。

相關問題