ホームページ  >  記事  >  バックエンド開発  >  Python クローラーで同時プログラミングを適用する方法

Python クローラーで同時プログラミングを適用する方法

WBOY
WBOY転載
2023-05-14 14:34:061231ブラウズ

同時プログラミングとは

同時プログラミングとは、一定期間内に複数の操作を実行できるプログラム設計を指します。通常、同時に開始され、実行できるプログラム内の複数のタスクによって表されます。実行および相互作用しますが、影響はありません。同時プログラミングの利点は、プログラムのパフォーマンスと応答性を向上できることです。

クローラでの同時プログラミングの適用

クローラ プログラムは典型的な I/O 集約型タスクです。I/O 集約型タスクの場合は、マルチスレッドと非同期 I/O が良い選択です。プログラムの特定の部分が I/O 操作によってブロックされても、プログラムの他の部分は引き続き実行できるため、待機やブロックに多くの時間を無駄にする必要がありません。

シングルスレッド バージョン

まず、クローラー プログラムのシングルスレッド バージョンを見てみましょう。このクローラ プログラムは、requests ライブラリを使用して JSON データを取得し、open 関数を通じて画像をローカルに保存します。

"""
example04.py - 单线程版本爬虫
"""
import os
import requests
def download_picture(url):
    filename = url[url.rfind('/') + 1:]
    resp = requests.get(url)
    if resp.status_code == 200:
        with open(f'images/beauty/{filename}', 'wb') as file:
            file.write(resp.content)
def main():
    if not os.path.exists('images/beauty'):
        os.makedirs('images/beauty')
    for page in range(3):
        resp = requests.get(f&#39;<https://image.so.com/zjl?ch=beauty&sn=>{page * 30}&#39;)
        if resp.status_code == 200:
            pic_dict_list = resp.json()[&#39;list&#39;]
            for pic_dict in pic_dict_list:
                download_picture(pic_dict[&#39;qhimg_url&#39;])
if __name__ == &#39;__main__&#39;:
    main()

macOS または Linux システムでは、time コマンドを使用して、以下に示すように、上記のコードの実行時間と CPU 使用率を把握できます。

time python3 example04.py

次は、私のコンピューターでシングルスレッド クローラー コードを実行した結果です。

python3 example04.py 2.36s user 0.39s system 12% cpu 21.578 total

ここでは、コードの合計消費時間にのみ注意する必要があります。 21.578 秒、CPU 使用率は 12% です。

マルチスレッド バージョン

前述のスレッド プール テクノロジを使用して、上記のコードをマルチスレッド バージョンに変更します。

"""
example05.py - 多线程版本爬虫
"""
import os
from concurrent.futures import ThreadPoolExecutor
import requests
def download_picture(url):
    filename = url[url.rfind(&#39;/&#39;) + 1:]
    resp = requests.get(url)
    if resp.status_code == 200:
        with open(f&#39;images/beauty/{filename}&#39;, &#39;wb&#39;) as file:
            file.write(resp.content)
def main():
    if not os.path.exists(&#39;images/beauty&#39;):
        os.makedirs(&#39;images/beauty&#39;)
    with ThreadPoolExecutor(max_workers=16) as pool:
        for page in range(3):
            resp = requests.get(f&#39;<https://image.so.com/zjl?ch=beauty&sn=>{page * 30}&#39;)
            if resp.status_code == 200:
                pic_dict_list = resp.json()[&#39;list&#39;]
                for pic_dict in pic_dict_list:
                    pool.submit(download_picture, pic_dict[&#39;qhimg_url&#39;])
if __name__ == &#39;__main__&#39;:
    main()

以下のコマンドを実行します。

time python3 example05.py

コードの実行結果は次のとおりです。

python3 example05.py 2.65s user 0.40 ■ system 95% cpu 3.193 total

非同期 I/O バージョン

aiohttp を使用して、上記のコードを非同期 I/O バージョンに変更します。非同期 I/O でネットワーク リソースの取得とファイルの書き込み操作を実現するには、まずサードパーティのライブラリ aiohttpaiofile をインストールする必要があります。

pip install aiohttp aiofile

以下は、クローラ コードの非同期 I/O バージョンです。

"""
example06.py - 异步I/O版本爬虫
"""
import asyncio
import json
import os
import aiofile
import aiohttp
async def download_picture(session, url):
    filename = url[url.rfind(&#39;/&#39;) + 1:]
    async with session.get(url, ssl=False) as resp:
        if resp.status == 200:
            data = await resp.read()
            async with aiofile.async_open(f&#39;images/beauty/{filename}&#39;, &#39;wb&#39;) as file:
                await file.write(data)
async def main():
    if not os.path.exists(&#39;images/beauty&#39;):
        os.makedirs(&#39;images/beauty&#39;)
    async with aiohttp.ClientSession() as session:
        tasks = []
        for page in range(3):
            resp = await session.get(f&#39;<https://image.so.com/zjl?ch=beauty&sn=>{page * 30}&#39;)
            if resp.status == 200:
                pic_dict_list = (await resp.json())[&#39;list&#39;]
                for pic_dict in pic_dict_list:
                    tasks.append(asyncio.ensure_future(download_picture(session, pic_dict[&#39;qhimg_url&#39;])))
        await asyncio.gather(*tasks)
if __name__ == &#39;__main__&#39;:
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

以下のコマンドを実行します。

time python3 example06.py

コードの実行結果は次のとおりです:

python3 example06.py 0.92s user 0.27 s system 290% cpu 0.420 total

シングルスレッド バージョンのクローラ プログラムと比較して、マルチスレッド バージョンおよび非同期 I/O バージョンのクローラ プログラムの実行時間は、大幅に改善され、非同期 I/O バージョンのクローラーの /O バージョンが最高のパフォーマンスを発揮します。

以上がPython クローラーで同時プログラミングを適用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。