2011-08-02 24 views
3

對於初學者,我是新來的Python,所以我下面的代碼可能不是最乾淨的。對於一個程序,我需要下載約500個網頁。這個url被存儲在一個由前一個函數填充的數組中。下載的部分是這樣的:蟒蛇 - 更快下載〜500個網頁(循環)

def downloadpages(num): 

    import urllib 
    for i in range(0,numPlanets): 
      urllib.urlretrieve(downloadlist[i], 'webpages/'+names[i]'.htm') 

每個文件只有20KB左右,但它需要至少10分鐘才能下載所有的人。下載合計大小的單個文件應該只需要一兩分鐘。有什麼方法可以加快速度?由於

編輯:爲了任何人誰是有興趣的,下面的例子在http://code.google.com/p/workerpool/wiki/MassDownloader和使用50個線程,下載時間已經從原來的10分鐘加減少到約20秒。隨着線程增加到60線程左右,下載速度不斷下降,之後下載時間又開始增加。

回答

4

但是,您並未下載單個文件。您正在下載500個單獨的頁面,每個連接都涉及開銷(用於初始連接),以及服務器正在執行的任何操作(是否爲其他人服務?)。

無論哪種方式,下載500 x 20kb與下載單個文件的大小不一樣。

+0

我沒有說我預計它會採取同樣的時間,只是如果有一個更快的方法 – Tim

3

您可以通過使用線程顯着加快執行速度(請小心,不要超載服務器)。

介紹材料/代碼示例:

+2

燃燒500個本地線程有點貴。在網絡服務器上同時點擊500次可能會從你的(不是那麼友好的)友好的本地系統管理員訪問,或者僅僅是違反AUP的一個簡單禁令。考慮將任務提供給(更小的)線程池。 –

+0

完美,會給這個去。在上面的例子中,他們一次使用五個線程,我將從此開始。感謝 – Tim

+0

或者扭曲或多處理或任何其他體面的併發方法。 –

2

您可以使用greenlet這樣做。

E.G與eventlet lib目錄下:

urls = [url1, url2, ...] 

import eventlet 
from eventlet.green import urllib2 

def fetch(url): 
    return urllib2.urlopen(url).read() 

pool = eventlet.GreenPool() 

for body in pool.imap(fetch, urls): 
    print "got body", len(body) 

在池中的所有呼叫都將是僞simulatneous。

當然,您必須先安裝帶有pip或easy_install的eventlet。

在Python中有幾個greenlet的實現。你可以用gevent或其他的做同樣的事情。

+0

綠色+1不是線程。 –

0

除了使用某種類型的併發之外,請確保您使用的任何方法來使請求使用HTTP 1.1連接持久性。這將允許每個線程只打開一個連接並通過它請求所有頁面,而不是爲每個請求進行TCP/IP設置/拆卸。不確定urllib2是否默認這樣做;你可能不得不推出自己的。