2009-06-12 36 views
48

urllib.urlretrieve trả về âm thầm ngay cả khi tệp không tồn tại trên máy chủ http từ xa, nó chỉ lưu trang html vào tệp được đặt tên. Ví dụ:Làm thế nào để biết nếu urllib.urlretrieve thành công?

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

chỉ trả về lặng lẽ, thậm chí nếu abc.jpg không tồn tại trên máy chủ google.com, được tạo ra abc.jpg không phải là một tập tin jpg hợp lệ, nó thực sự là một trang html. Tôi đoán các tiêu đề được trả lại (một cá thể httplib.HTTPMessage) có thể được sử dụng để thực sự cho biết các thành công truy xuất hay không, nhưng tôi không thể tìm thấy bất kỳ tài liệu nào cho httplib.HTTPMessage.

Ai đó có thể cung cấp một số thông tin về vấn đề này không?

Trả lời

22

Cân nhắc sử dụng urllib2 nếu có thể trong trường hợp của bạn. Nó nâng cao hơn và dễ sử dụng hơn urllib.

Bạn có thể phát hiện bất kỳ lỗi HTTP một cách dễ dàng:

>>> 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 thực sự là HTTPResponse đối tượng mà bạn có thể làm được rất nhiều điều hữu ích với:

>>> resp = urllib2.urlopen("http://google.com/") 
>>> resp.code 
200 
>>> resp.headers["content-type"] 
'text/html; charset=windows-1251' 
>>> resp.read() 
"<<ACTUAL HTML>>" 
+6

Có thể urllib2 cung cấp hành vi đệm ẩn của urlretrieve hay không? Hay chúng ta phải thực hiện lại nó? – Kiv

+0

Hãy xem sự tương tác khó chịu này từ ActiveState: http://code.activestate.com/recipes/491261/ Chúng tôi đang sử dụng nó trong dự án hiện tại của chúng tôi, hoạt động hoàn hảo –

+1

urlopen không cung cấp chức năng móc (để hiển thị thanh tiến trình cho ví dụ) như urlretrieve. –

2

Theo các tài liệu được là undocumented

để có được quyền truy cập vào thông điệp có vẻ như bạn làm điều gì đó như:

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

b là dụ nhắn

Kể từ khi tôi đã học được rằng Python luôn hữu ích khi sử dụng khả năng của Python để trở nên nội tâm khi tôi nhập

dir(b) 

Tôi thấy rất nhiều phương pháp hoặc các chức năng để chơi với

Và sau đó tôi bắt đầu làm việc với b

ví dụ

b.items() 

Lists rất nhiều điều thú vị, tôi nghi ngờ rằng chơi xung quanh với những thứ này sẽ cho phép bạn lấy thuộc tính bạn muốn thao tác.

Xin lỗi, đây là câu trả lời của người mới bắt đầu nhưng tôi đang cố gắng nắm vững cách sử dụng khả năng nội tâm để cải thiện việc học của mình và các câu hỏi của bạn vừa xuất hiện.

Vâng tôi đã cố gắng một cái gì đó thú vị liên quan đến này-tôi đã tự hỏi nếu tôi có thể tự động nhận được đầu ra từ mỗi trong những điều mà xuất hiện trong thư mục mà không cần thông số vì vậy tôi đã viết:

needparam=[] 
for each in dir(b): 
    x='b.'+each+'()' 
    try: 
     eval(x) 
     print x 
    except: 
     needparam.append(x) 
+0

Không có trạng thái cho tôi và mã của bạn chỉ hoạt động một lần. Hãy thử 'for k in b: print"% s:% r "% (k, b [k])' –

1

tôi đã kết thúc với retrieve thực hiện của riêng tôi , với sự giúp đỡ của pycurl nó hỗ trợ nhiều giao thức hơn urllib/urllib2, hy vọng nó có thể giúp người khác.

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

Bạn có thể tạo trình tạo URL mới (kế thừa từ FancyURLopener) và ném ngoại lệ hoặc xử lý lỗi theo bất kỳ cách nào bạn muốn. Thật không may, FancyURLopener bỏ qua 404 và các lỗi khác. Xem câu hỏi này:

How to catch 404 error in urllib.urlretrieve

6

Tôi giữ nó đơn giản:

# 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

Ý tưởng hay hơn là 'shutil.copyfileobj'. – lericson

+1

Làm thế nào, lericson? –

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

:) bài viết đầu tiên của tôi trên StackOverflow, đã là một Lurker trong nhiều năm. :)

Đáng buồn là dir (urllib.urlretrieve) thiếu thông tin hữu ích. Vì vậy, từ chủ đề này cho đến nay tôi đã cố gắng viết này:

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

mà sản xuất này:

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 

Tôi đoán người ta có thể kiểm tra:

if b.Content-Length > 0: 

bước tiếp theo của tôi là để thử nghiệm một trường hợp truy xuất không thành công ...

+0

b.getheader ('Độ dài nội dung') thường lớn hơn 0 ngay cả trên 404 (nếu tệp không tồn tại) –

0

Kết quả đối với một máy chủ/trang web khác - những gì trở lại trong "B" là một chút ngẫu nhiên, nhưng người ta có thể kiểm tra giá trị nhất định:

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 

Trong trường hợp 'xấu' (không tồn tại tập tin hình ảnh) "B" lấy ra một đoạn nhỏ (Googlebot?) Mã HTML và lưu nó làm mục tiêu, do đó Content-Length là 1363 byte.

Các vấn đề liên quan