비동기 파싱을 사용하는 이유
여러 url을 for문을 돌며 parsing을 하기엔 너무 오랜 시간이 걸립니다.
(1방문->1파싱->2방문->2파싱->....n방문->n파싱)
모든 사이트의 응답이 빠르지 않기 때문이기도하고, parsing하는데 오랜시간이 걸려버립니다.
멀티로 동작할 수 있는 컴퓨터의 자원을 이용해서 이 시간을 줄일 수 있습니다.
사이트에 방문하고 parsing하는 일을 1개의 작업(Task)으로 묶어놓고, 여러개의 작업을 동시에 처리하면 됩니다.
(1방문->1파싱)
-> (2방문->2파싱)
....
-> (n방문->n파싱)
이러한 동시 작업은 thread, process가 아닌 asyncio(코루틴)를 이용해서 파싱을 해보려고 합니다.
코루틴은 비동기(async) 함수와 실행(run), 기다리기(await) 를 대표로 사용합니다.
0. 임포트
import asyncio
import aiohttp
from bs4 import BeautifulSoup
1. 이벤트 루프 만들기
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
새로운 이벤트 루프를 만들고, 시스템에서 사용하는 이벤트 루프로 등록합니다.
2. url 접근해서 내용을 가져오는 함수를 작성합니다.
async def get_text_from_url(url):
async with aiohttp.ClientSession() as sess:
async with sess.get(url, headers={'user-agent': 'Mozilla/5.0'}) as res:
res_html = await res.text()
status = res.status
if status != 200:
return Response(-1, '추적에 실패하였습니다(-1)')
result_soup = BeautifulSoup(res_html, 'lxml')
contents = result_soup.select_one('body')
return contents
코루틴으로 동시에 실행되는 함수를 만들기 위해, def 앞에 async를 입력합니다.
input/output이 될때 컴퓨터에서는 블럭킹 되기 때문에, 블럭이 안되는 aiohttp를 이용해서 사이트의 html을 가져옵니다.
가져온 html은 beatifulsoap를 이용해서 파싱합니다. (*lxml을 이용하기 위해선 패키지를 따로 설치해야합니다)
3. 실행은 하지 않아요
futures = [asyncio.ensure_future(get_text_from_url(url)) for url in url_list]
group1 = asyncio.gather(*futures)
async로 만들어진 함수를 asyncio.ensure_future함수를 통해서 future로 만들어 놓습니다.
future는 아직 실행되지 않고, 실행을 암시하는 저수준의 어웨이터블(awaitable, await + able) 객체 입니다.
asyncio.gather를 이용해서 futures 어레이를 그룹화 해줍니다.
4. 그룹을 모두 실행해 줍니다.
results1 = loop.run_until_complete(group1)
비동기 함수들을 모두 실행하고, 끝날때까지 기다렸다가, results1 변수에 결과를 저장합니다.
5. 모든 비동기가 끝나면 loop를 닫아서 메모리에서 해지시켜줍니다.
loop.close()
'스터디 > Python' 카테고리의 다른 글
Python Moviepy - 코딩으로 동영상 만들기 (0) | 2023.03.27 |
---|---|
Python moviepy audiofileclip error. noise. (0) | 2023.02.12 |
Python 설치/삭제 명령어 + 버전 (0) | 2023.01.24 |
Python 개발에서 쓸만한 코드 모음 (0) | 2022.07.24 |
댓글