使Python多重处理更加高效地利用资源

问题描述 投票:0回答:2

我有一个非常示例的Python代码,它通过一些URL,对每个URL发出一个获取请求,使用Beachful Soup解析源代码以获取一些数据,使用pandas将数据存储在CSV文件中。

我有一个巨大的列表或 URL,这就是为什么我想使用多处理/线程来运行大约 50 个代码实例,但是即使我有一台很好的机器和代码,我也只能使用多处理运行大约 5 个代码实例我想没那么重。

代码看起来像这样:


import pandas as pd
from requests import get
from bs4 import BeautifulSoup

def parse_and_save(urls):
    for url in urls:
        page = get(url)
        soup = BeautifulSoup(page , 'html.parser')

        href = soup.find("a")["href"]
        pd.DataFrame({'link':href}).to_csv(f'{url}.csv')


if __name__ == '__main__':
    urls_to_parse = [....]
    processes = []
    for urls in urls_to_parse[::1000]:
       p = Process(target=parse_and_save , args=(urls,).start()
       processes.append(p)

    for process in processes:
        process.join()

我尝试使用线程和多处理,但没有任何效果,CPU 使用率达到 100%,我无能为力,有没有办法解决这个问题?或者我需要使用另一种编程语言?

谢谢!

python multithreading web-scraping parallel-processing python-multithreading
2个回答
0
投票

每个新进程/线程都需要额外的资源。因此,正确的方法是使用它们的池(通常不超过十分之几),并将 URL 映射到该池上。


0
投票

使用

concurrent.futures
也可以实现同样的效果,运行代码的大部分时间都在等待服务器响应,而不是处理器完成任务。无需将任务拆分到处理器上,您可以轻松使用这样的线程:

import requests
from bs4 import BeautifulSoup
import concurrent.futures

def parse_and_save(urls):
        page = requests.get(url)
        soup = BeautifulSoup(page.content , 'html.parser')

        href = soup.find("a")["href"]
        pd.DataFrame({'link':href}).to_csv(f'{url}.csv') #not sure your code will work?

urls_to_parse = [....]
workers = 50 #can change this, experiment to find best performance before GIL starts slowing you down: https://realpython.com/python-gil/
with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
    final_list = executor.map(parse_and_save, urls_to_parse)
© www.soinside.com 2019 - 2024. All rights reserved.