2017-08-13 2 views
1

Honnêtement, je n'étais même pas sûr de savoir quoi nommer cette question. J'essaie de parcourir une grande liste d'URL, mais je ne traite que 20 URL (20 sont basées sur le nombre de proxies que j'ai) à la fois. Mais j'ai également besoin de continuer à boucler la liste de proxy, car je suis en train de traiter les URL. Ainsi, par exemple, il commencerait avec la 1ère URL et le 1er proxy, et dès qu'il atteindrait la 21ème URL, il utiliserait à nouveau le 1er proxy. Voici mon pauvre exemple ci-dessous, si quelqu'un peut même me pointer dans la bonne direction, ce serait très apprécié.Python Multiprocessing une grande liste avec une boucle

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() 

Répondre

1

Vous pouvez utiliser une liste pour stocker de nouveaux processus. Lorsque vous atteignez un certain nombre d'éléments, appelez le join pour chaque processus de la liste. Cela devrait vous donner un certain contrôle sur le nombre de processus actifs.

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() 


Si vous voulez un nombre constant de processus actifs, vous pouvez essayer le module Pool. Il suffit de modifier la définition worker pour recevoir un tuple.

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() 

Juste pour clarifier les choses, la fonction worker devrait recevoir un tuple puis décompresser.

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

J'ai testé le code que vous m'avez donné et cela fonctionne jusqu'à un certain point. Mais j'ai tout en boucle pour quand je fais une demande et il ne se casse pas jusqu'à ce que la demande passe (parfois le proxy de connexion arrière est mauvais et doit attendre pour en obtenir un nouveau). Mais si cela se produit, il semble attendre que la boucle while soit terminée, avant que tous les autres liens ne soient demandés. Je pensais que tout le but du multitraitement était de pouvoir appeler la même fonction plusieurs fois à la fois? Peut-être que je ne comprends pas comment cela fonctionne. – antfuentes87

+0

Vous pourriez utiliser 'multiprocessing.Pool', il devrait être beaucoup plus lisse. Envisagez également d'utiliser un délai d'attente raisonnable (5 à 30 secondes) dans 'requests.get'. –

+0

Cela semble beaucoup plus lisse. Je vois que vous entrez des "données" dans l'imap, mais que se passe-t-il si j'ai plus de variables à saisir dans la fonction? J'ai besoin d'accéder à url ["name"], url ["id"], etc ... depuis les urls. Si peu confus que la façon d'ajouter ces variables dans l'IMAP. – antfuentes87

0

Essayez le code ci-dessous:

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

Qu'en est-il seulement de la génération de 20 processus (ou de nombreux proxys dans la liste) à la fois? – antfuentes87

+0

Lorsque chaque processus démarre, ajoutez-le à un compteur. Retirez-le quand il se termine. Dans la boucle for, vérifiez le compteur avant de le faire. –

+0

Je suppose que je suis juste confus. Ne sera pas la boucle for, juste faire tout le processus à la fois commencer? Donc, si j'ai 1000 liens, n'essaiera-t-il pas de démarrer 1000 processus? Comment puis-je seulement créer 20 processus à la fois? – antfuentes87