728x90

grequest 모듈을 이용하여 비동기 HTTP 요청을 처리하는 방법입니다. 

 

grequests.get() 으로 요청 리스트를 생성하고, grequests.map()으로 실제 요청을 실해합니다.

import grequests

urls= ["http://abc.com/", "http://def.com/", ...,"http://zzz.com/",
req_tasks = [grequests.get(url, headers=headers) for url in urls]

res_list = grequests.map(req_tasks)

for res in res_list:
	print(res.text)

 

grequest vs. request Code

# Import 
import grequests
import requests
import time 
# pip install grequests


## Target url 
urls = [
    "https://finviz.com/screener.ashx?v=152&ft=4"
,   "https://finviz.com/screener.ashx?v=152&ft=4&r=21"
,   "https://finviz.com/screener.ashx?v=152&ft=4&r=41"
,   "https://finviz.com/screener.ashx?v=152&ft=4&r=61"
,   "https://finviz.com/screener.ashx?v=152&ft=4&r=81"
,   "https://finviz.com/screener.ashx?v=152&ft=4&r=101"
]

headers = {
    'Referer': 'https://freemidi.org/download-20225',
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}

## 동기(sync request) 함수 
def req_normal(urls, headers):
    res_list=[]
    for url in urls:
        res = requests.get(url=url, headers=headers)
        res_list.append(res)
    return res_list

def req_async_exception(e):
    print(e)

## 비동기(async request) 함수 
def req_async(urls, headers):    
    req_tasks = [grequests.get(url, headers=headers) for url in urls]
    #print(len(req_tasks))
    return grequests.map(req_tasks, exception_handler=req_async_exception, size=2, gtimeout=1)

# 파일 저장 함수 
def response2file(tag, response_list):
    page=0
    for res in response_list:
        page = page + 1
        with open(f"./data/{tag}_{page}.html", "w",  encoding='utf8') as f:
            f.write(res.text)
728x90

동기 함수 실행 코드 

s = time.time()
r = req_normal(urls, headers)
response2file(tag="req_normal_", response_list=r)
e = time.time()
print(f"req_normal() Durations : {round(e-s, 10)} s")
# Output
# 	req_normal() Durations : 1.9974486828 s

비동기 함수 실행 코드 

s = time.time()
r = req_async(urls, headers)
response2file(tag="req_async_", response_list=r)
e = time.time()
print(f"req_async() Durations : {round(e-s, 10)} s")

# Output
#   req_async() Durations : 0.9877688885 s

위 예제에서 비동기 방식이 약 2배 이상 빠른 것을 확인할 수 있습니다. 

 

 

grequest  코루틴 기반의 gevent 로 작성된 비동기식 HTTP 요청 모듈입니다. 

더보기

gevent 란?

gevent는 libev / libuv 이벤트 루프 위에 고수준 동기 API를 제공하기 위해 greenlet 을 사용하는 코루틴 기반 Python 네트워킹 라이브러리입니다 .

다음과 같은 특징이 있습니다

* libev 또는 libuv 기반의 빠른 이벤트 루프 .
* greenlet을 기반으로 하는 경량 실행 단위.
* Python 표준 라이브러리의 개념을 재사용하는 API(예: 이벤트 및 대기열 있음).
* SSL을 지원하는 협력 소켓
* 스레드 풀, dnspython 또는 c-ares를 통해 수행되는 협력 DNS 쿼리 .
* 타사 모듈이 협력하도록 하는 Monkey 패치 유틸리티
* TCP/UDP/HTTP 서버
* 하위 프로세스 지원( gevent.subprocess 통해 )
* 스레드 풀

Reference

* grequest : https://pypi.org/project/grequests/

* gevent : http://www.gevent.org/intro.html#example


 

728x90
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기
반응형