同時プログラミングとは、一定期間内に複数の操作を実行できるプログラム設計を指します。通常、同時に開始され、実行できるプログラム内の複数のタスクによって表されます。実行および相互作用しますが、影響はありません。同時プログラミングの利点は、プログラムのパフォーマンスと応答性を向上できることです。
クローラ プログラムは典型的な 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'<https://image.so.com/zjl?ch=beauty&sn=>{page * 30}') if resp.status_code == 200: pic_dict_list = resp.json()['list'] for pic_dict in pic_dict_list: download_picture(pic_dict['qhimg_url']) if __name__ == '__main__': 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('/') + 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') with ThreadPoolExecutor(max_workers=16) as pool: for page in range(3): resp = requests.get(f'<https://image.so.com/zjl?ch=beauty&sn=>{page * 30}') if resp.status_code == 200: pic_dict_list = resp.json()['list'] for pic_dict in pic_dict_list: pool.submit(download_picture, pic_dict['qhimg_url']) if __name__ == '__main__': main()
以下のコマンドを実行します。
time python3 example05.py
コードの実行結果は次のとおりです。
python3 example05.py 2.65s user 0.40 ■ system 95% cpu 3.193 total
aiohttp
を使用して、上記のコードを非同期 I/O バージョンに変更します。非同期 I/O でネットワーク リソースの取得とファイルの書き込み操作を実現するには、まずサードパーティのライブラリ aiohttp
と aiofile
をインストールする必要があります。
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('/') + 1:] async with session.get(url, ssl=False) as resp: if resp.status == 200: data = await resp.read() async with aiofile.async_open(f'images/beauty/{filename}', 'wb') as file: await file.write(data) async def main(): if not os.path.exists('images/beauty'): os.makedirs('images/beauty') async with aiohttp.ClientSession() as session: tasks = [] for page in range(3): resp = await session.get(f'<https://image.so.com/zjl?ch=beauty&sn=>{page * 30}') if resp.status == 200: pic_dict_list = (await resp.json())['list'] for pic_dict in pic_dict_list: tasks.append(asyncio.ensure_future(download_picture(session, pic_dict['qhimg_url']))) await asyncio.gather(*tasks) if __name__ == '__main__': 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 サイトの他の関連記事を参照してください。