【问题标题】:Making requests to many urls via multithreading通过多线程向多个 url 发出请求
【发布时间】:2019-08-30 14:22:24
【问题描述】:

我有一个相对 URL 列表 -PostLink 和一个 base_url。我通过for loop 向每个网址发出请求。它运行良好,大约需要六分钟。

import requests
bowl = requests.get('http://www.aaronsw.com/weblog/fullarchive')
soup = BeautifulSoup(bowl.text, 'html.parser')
PostLink = soup.body.find_all('a', href = True)
PostLink = [i['href'] for i in PostLink][2:]
baseurl = 'http://www.aaronsw.com/weblog/'
bowls = [requests.get(baseurl + i) for i in PostLink]

现在觉得这个工作是I/O密集型的,希望通过多线程加快爬取速度。

我试过了

from concurrent.futures import ThreadPoolExecutor 
pool = ThreadPoolExecutor(6)
res = []
for i in PostLink:
    future = pool.submit(requests.get, (baseurl + i))
    res.append(future.result())

我认为我做错了。任何帮助表示赞赏。

【问题讨论】:

    标签: python multithreading python-requests


    【解决方案1】:

    这里有一些代码可以多处理一个项目列表并针对列表中的每个项目并行执行your_function

        from multiprocessing import Pool, cpu_count
    
    def multi_processor(function_name):
    
        file_list = []
    
        # Test, put 6 strings in the list so your_function should run six times with 6 processors in parallel (assuming your CPU has that many cores)
        file_list.append("test1")
        file_list.append("test2")
        file_list.append("test3")
        file_list.append("test4")
        file_list.append("test5")
        file_list.append("test6")
    
        # Use max number of system processors - 1
        pool = Pool(processes=cpu_count()-1)
        pool.daemon = True
    
        results = {}
        # for every  file in the file list, start a new process
        for each_file in file_list:
            results[each_file] = pool.apply_async(function_name, args=("arg1", "arg2"))
    
        # Wait for all processes to finish before proceeding
        pool.close()
        pool.join()
    
        # Results and any errors are returned
        return {your_function: result.get() for your_function, result in results.items()}
    
    
    def your_function(arg1, arg2):
        try:
            print("put your stuff in this function")
            your_results = ""
            return your_results
        except Exception as e:
            return str(e)
    
    if __name__ == "__main__":
        some_results = multi_processor(your_function)
        print(some_results)
    

    【讨论】:

    • 来自stackoverflow.com/questions/40894487/…,我了解到在这种情况下最好使用多线程。
    • 对不起,我从来没有使用过多线程,所以我没有任何sn-ps。根据您提供的 URL,我认为 I/O 与 CPU 密集型在您的情况下不会那么重要。如果串行处理需要 6 分钟,我猜多线程和处理之间的区别并不大。多线程不是内存安全的,这意味着线程之间的内存引用可能会发生冲突。多处理没有这个问题。
    【解决方案2】:

    使用multiprocessing 大约需要 54 秒。

    from multiprocessing import Pool
    with Pool(6) as p:
        bowls = p.map(requests.get, [baseurl+i for i in PostLink])
    

    同时使用mutithreading也可以加快任务速度。

    from concurrent.futures import ThreadPoolExecutor
    startt = time.time()
    with ThreadPoolExecutor(8) as executor:
        bowls = executor.map(requests.get, [baseurl+i for i in PostLink])
    time.time()-startt
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 2020-01-21
      • 2015-08-25
      • 1970-01-01
      相关资源
      最近更新 更多