2017-08-13 50 views
1

老實說,我甚至不知道該怎麼標題這個問題。我試圖遍歷大量的URL,但一次只能處理20個URL(20個基於我有多少個代理)。但我還需要繼續循環訪問代理列表,因爲我正在處理這些URL。因此,例如,它將從第1個URL和第1個代理開始,一旦它到達第21個URL,它將再次使用第1個代理。這裏是我下面的一個不好的例子,如果任何人甚至可以指出我在正確的方向,這將是非常感激。Python多處理一個循環大列表

import pymysql.cursors 
from multiprocessing import Pool 
from fake_useragent import UserAgent 

def worker(args): 
    var_a, id, name, content, proxy, headers, connection = args 
    print (var_a) 
    print (id) 
    print (name) 
    print (content) 
    print (proxy) 
    print (headers) 
    print (connection) 
    print ('---------------------------') 

if __name__ == '__main__': 
    connection = pymysql.connect(
     host = 'host ', 
     user = 'user', 
     password = 'password', 
     db = 'db', 
     charset='utf8mb4', 
     cursorclass=pymysql.cursors.DictCursor 
    ) 

    ua = UserAgent() 
    user_agent = ua.chrome 
    headers = {'User-Agent' : user_agent} 

    proxies = [ 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx', 
     'xxx.xxx.xxx.xxx:xxxxx' 
    ] 

    with connection.cursor() as cursor: 
     sql = "SELECT id,name,content FROM table" 
     cursor.execute(sql) 
     urls = cursor.fetchall() 

    var_a = 'static' 

    data = ((var_a, url['id'], url['name'], url['content'], proxies[i % len(proxies)], headers, connection) for i, url in enumerate(urls)) 
    proc_num = 20 
    p = Pool(processes=proc_num) 
    results = p.imap(worker, data) 
    p.close() 
    p.join() 

回答

1

您可以使用列表來存儲新工藝。當您達到一定數量的項目時,請致電join查詢列表中的每個進程。這應該可以讓您對活動進程的數量進行一些控制。

if __name__ == '__main__': 
    proc_num = 20 
    proc_list = [] 
    for i, url in enumerate(urls): 
     proxy = proxies[i % len(proxies)] 
     p = Process(target=worker, args=(url, proxy)) 
     p.start() 
     proc_list.append(p) 
     if i % proc_num == 0 or i == len(urls)-1: 
      for proc in proc_list: 
       proc.join() 


如果你想活動進程的一個常數,你可以嘗試Pool模塊。只需修改worker定義即可接收元組。

if __name__ == '__main__': 
    data = ((url, proxies[i % len(proxies)]) for i, url in enumerate(urls)) 
    proc_num = 20 
    p = Pool(processes=proc_num) 
    results = p.imap(worker, data) 
    p.close() 
    p.join() 

只是爲了澄清事情時,worker功能應該收到一個元組,然後解壓。

def worker(args): 
    var_a, id, name, content, proxy, headers, connection = args 
    print (var_a) 
    ... etc ... 
+0

我一直在測試你給我的代碼,它在一定程度上有效。但是當我提出請求時,我有while循環,並且在請求完成之前它不會中斷(有時後連接代理不好,需要等待以獲得新的請求)。但是,如果發生這種情況,它似乎等待while循環完成,然後再請求任何其他鏈接。我認爲多處理的全部目的是能夠同時多次調用同一個函數?也許我誤解了它的工作原理。 – antfuentes87

+0

你可以使用'multiprocessing.Pool',它應該更平滑。還要考慮在'requests.get'中使用合理的超時(5 - 30秒)。 –

+0

看起來更順暢。我看到你正在向imap輸入「數據」,但是如果我有更多的變量需要輸入到函數中呢?我需要從網址訪問url [「name」],url [「id」]等。所以對於如何將這些變量添加到imap中一點困惑。 – antfuentes87

0

試試下面的代碼:

for i in range(len(urls)): 
    url = urls[i] # Current URL 
    proxy = proxies[i % len(proxies)] # Current proxy 
    # ... 
+0

怎麼樣一次只產卵20個進程(或者列表中有多少個代理)呢? – antfuentes87

+0

當每個進程啓動時,將其添加到計數器。結束時將其刪除。在for循環中,在執行之前檢查計數器。 –

+0

我想我只是困惑。不會for循環,只是讓所有的進程立即開始?所以如果我有1000個鏈接,它會不會嘗試啓動1000個進程?我怎樣才能一次創建20個進程? – antfuentes87