【问题标题】:Python Multiprocessing a large list with a loopPython多处理一个带有循环的大列表
【发布时间】:2017-08-13 06:13:11
【问题描述】:

老实说,我什至不知道给这个问题起什么名字。我正在尝试遍历大量 URL,但一次只处理 20 个 URL(20 个基于我拥有的代理数量)。但在处理 URL 时,我还需要继续遍历代理列表。因此,例如,它将从第一个 URL 和第一个代理开始,一旦它到达第 21 个 URL,它将再次使用第一个代理。这是我下面的糟糕示例,如果有人能指出我正确的方向,将不胜感激。

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

【问题讨论】:

    标签: python loops proxy multiprocessing python-requests


    【解决方案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 ...
    

    【讨论】:

    • 我一直在测试你给我的代码,它在一定程度上是有效的。但是当我发出请求时,我有 while 循环,并且在请求通过之前它不会中断(有时后端连接代理不好,需要等待获得新的代理)。但如果发生这种情况,它似乎要等待 while 循环完成,然后再请求任何其他链接。我认为多处理的全部目的是能够一次多次调用同一个函数?也许我误解了它是如何工作的。
    • 你可以使用multiprocessing.Pool,应该会更流畅。还可以考虑在requests.get 中使用合理的超时时间(5 - 30 秒)。
    • 这样看起来流畅多了。我看到您正在将“数据”输入到 imap 中,但是如果我需要将更多变量输入到函数中怎么办?我需要从 url 访问 url["name"]、url["id"] 等。对于如何将这些变量添加到 imap 中,几乎没有什么困惑。
    • 你能说得更具体点吗? url 是一个字符串,它没有任何键。但是您可以修改worker 的定义以接受任意数量的参数:def worker(*args):,或者构建一个“帮助”函数将参数解压缩到worker,例如:def helper(args): return worker(*args)
    • 是的,抱歉,url 只是一个例子。 urls 实际上是一个 MySQL 选择查询。所以我需要能够从中选择列并将它们与代理一起输入到函数中(在上面的示例中完全按照我的方式设置)希望这更清楚一点。
    【解决方案2】:

    试试下面的代码:

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

    【讨论】:

    • 一次只生成 20 个进程(或者列表中有多少代理)怎么样?
    • 每个进程启动时,将其添加到计数器中。结束时将其删除。在 for 循环中,在执行之前检查计数器。
    • 我想我只是糊涂了。不会 for 循环,只是让所有过程立即开始吗?那么如果我有 1000 个链接,它不会尝试启动 1000 个进程吗?我如何让它一次只创建 20 个进程?
    • 我想我需要这样的东西stackoverflow.com/questions/20190668/…(第一个答案),但是我如何在函数中输入代理,因为在答案中,没有使用循环。他只是在地图中输入数组。
    猜你喜欢
    • 2022-11-22
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    • 2013-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多