동시 프로그래밍은 일정 시간 내에 여러 작업을 수행할 수 있는 프로그램 설계를 말합니다. 일반적으로 프로그램의 여러 작업이 동시에 시작되어 서로 영향을 주지 않고 실행할 수 있다는 점에서 나타납니다. 동시 프로그래밍의 이점은 프로그램의 성능과 응답성을 향상시킬 수 있다는 것입니다.
크롤러 프로그램은 일반적인 I/O 집약적 작업의 경우 멀티스레딩과 비동기 I/O가 모두 좋은 선택입니다. 프로그램의 일부가 I/O 작업으로 인해 차단되어도 프로그램의 다른 부분은 계속 실행될 수 있으므로 기다리거나 차단하는 데 많은 시간을 낭비할 필요가 없습니다.
먼저 크롤러 프로그램의 싱글 스레드 버전을 살펴보겠습니다. 이 크롤러 프로그램은 requests
라이브러리를 사용하여 JSON 데이터를 얻고 open
함수를 통해 이미지를 로컬에 저장합니다. 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.40s system 95% cpu 3.193 total
我们使用aiohttp
将上面的代码修改为异步 I/O 的版本。为了以异步 I/O 的方式实现网络资源的获取和写文件操作,我们首先得安装三方库aiohttp
和aiofile
""" 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
명령을 사용하여 위 코드의 실행 시간과 CPU 사용률을 이해할 수 있습니다. time python3 example04.py다음은 내 컴퓨터에서 싱글 스레드 크롤러 코드를 실행한 결과입니다.
python3 example04.py 2.36s user 0.39s system 12% cpu 21.578 total여기서 우리는 코드에 걸린 총 시간이
21.578
초라는 점에만 주의하면 됩니다. CPU 사용률은 12%
입니다. 멀티 스레드 버전아래 표시된 명령을 실행하세요. 🎜time python3 example05.py🎜🎜🎜코드 실행 결과는 다음과 같습니다. 🎜🎜🎜python3 example05.py 2.65s user 0.40s system 95% cpu 3.193 total🎜🎜🎜Asynchronous I/O version 🎜🎜We aiohttp를 사용하여 위 코드를 비동기 I/O 버전으로 수정하세요. 비동기 I/O에서 네트워크 리소스 획득 및 파일 쓰기 작업을 수행하려면 먼저 타사 라이브러리앞서 언급한 스레드 풀 기술을 사용하여 위 코드를 멀티 스레드 버전으로 수정합니다.
rrreee
aiohttp
및 aiofile
를 설치해야 합니다. 🎜🎜🎜pip install aiohttp aiofile🎜🎜🎜다음은 크롤러 코드의 비동기 I/O 버전입니다. 🎜rrreee🎜아래 표시된 명령을 실행하세요. 🎜🎜🎜time python3 example06.py🎜🎜🎜코드의 실행 결과는 다음과 같습니다. 🎜🎜🎜python3 example06.py 0.92s 사용자 0.27s 시스템 290% CPU 0.420 total🎜🎜🎜싱글 스레드 버전과 비교 크롤러 프로그램, 더보기 스레드 버전과 크롤러 프로그램의 비동기 I/O 버전의 실행 시간이 크게 향상되었으며 크롤러 프로그램의 비동기 I/O 버전이 가장 좋은 성능을 발휘했습니다. 🎜위 내용은 Python 크롤러에서 동시 프로그래밍을 적용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!