2009-10-04 30 views
50

tôi sử dụng đoạn mã sau để truyền các file lớn từ Internet vào một tập tin địa phương:suối lớn tập tin nhị phân với urllib2 nộp

fp = open(file, 'wb') 
req = urllib2.urlopen(url) 
for line in req: 
    fp.write(line) 
fp.close() 

này hoạt động nhưng nó tải khá chậm. Có cách nào nhanh hơn không? (Các tệp lớn nên tôi không muốn giữ chúng trong bộ nhớ.)

+2

Nếu chỉ này được xây dựng vào dưới dạng đĩa đơn lệnh, ví dụ 'urllib.urldownload (url, file)' –

+0

@GeraldKaszuba: bạn có nghĩa là ['urllib.urlretrieve (url, file)'] (http://docs.python.org/2/library/urllib.html#urllib. urlretrieve) – jfs

+0

@JFSebastian Nice! Có thể đăng nó như là một câu trả lời? –

Trả lời

94

Không có lý do để làm việc từng dòng, chỉ cần đoạn nó lên trong khối lớn hơn, ví dụ:

# from urllib2 import urlopen # Python 2 
from urllib.request import urlopen # Python 3 

response = urlopen(url) 
CHUNK = 16 * 1024 
with open(file, 'wb') as f: 
    while True: 
     chunk = response.read(CHUNK) 
     if not chunk: 
      break 
     f.write(chunk) 

Thử nghiệm một chút với nhiều CHUNK kích cỡ để tìm "điểm ngọt" cho các yêu cầu của bạn.

+0

nhờ Alex - có vẻ như đó là vấn đề của tôi vì hầu hết các dòng chỉ là vài trăm byte. – hoju

+2

nó làm việc cho tôi. Nhưng tôi nghĩ rằng fp.close() vẫn còn thiếu – printminion

+6

russenreaktor, bằng cách sử dụng với mở (...) là ...: có một ngầm gần() được gọi là để lại tuyên bố với. – mklauber

6

Tôi đã từng sử dụng mô-đun mechanize và phương thức Browser.retrieve() của nó. Trong quá khứ nó đã lấy 100% CPU và tải xuống mọi thứ rất chậm, nhưng một số bản phát hành gần đây đã sửa lỗi này và hoạt động rất nhanh.

Ví dụ:

import mechanize 
browser = mechanize.Browser() 
browser.retrieve('http://www.kernel.org/pub/linux/kernel/v2.6/testing/linux-2.6.32-rc1.tar.bz2', 'Downloads/my-new-kernel.tar.bz2') 

mechanize được dựa trên urllib2, vì vậy urllib2 cũng có thể có phương pháp tương tự ... nhưng tôi không thể tìm thấy bất kỳ bây giờ. (! Khối nhỏ và đòi hỏi Python để tìm thấy những dòng kết thúc cho bạn -)

+0

nó gần giống như Alex Martinelly đề xuất; 'BLOCK_SIZE' = 8 * 1024 và thường được sửa là –

58

Bạn cũng có thể sử dụng shutil:

import shutil 
try: 
    from urllib.request import urlopen # Python 3 
except ImportError: 
    from urllib2 import urlopen # Python 2 

def get_large_file(url, file, length=16*1024): 
    req = urlopen(url) 
    with open(file, 'wb') as fp: 
     shutil.copyfileobj(req, fp, length) 
+0

+1, điều này không chính xác giống như Alex Martelli đề nghị. Và nó chấp nhận tham số 'length' (' shutil.copyfileobj (fsrc, fdst [, length]) ') cũng là = 16 * 1024 theo mặc định –

3

Bạn có thể sử dụng urllib.retrieve() để tải tập tin:

Ví dụ:

try: 
    from urllib import urlretrieve # Python 2 

except ImportError: 
    from urllib.request import urlretrieve # Python 3 

url = "http://www.examplesite.com/myfile" 
urlretrieve(url,"./local_file") 
+3

Bạn có thể có nghĩa là' urllib.urlretrieve (url, "./ local_file") ' – Blairg23

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