Last active
June 28, 2017 05:23
-
-
Save nakamuray/d9cffda53ba3e936c4474ce9e09cbbc3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import functools | |
import time | |
import urllib.parse | |
import aiohttp | |
def throttling(sleep): | |
def decorator(func): | |
last_called = None | |
lock = asyncio.Lock() | |
@functools.wraps(func) | |
async def wrapper(*args, **kwargs): | |
nonlocal last_called | |
async with lock: | |
now = time.monotonic() | |
if last_called is not None: | |
delta = now - last_called | |
if delta < sleep: | |
await asyncio.sleep(sleep - delta) | |
try: | |
return await func(*args, **kwargs) | |
finally: | |
last_called = time.monotonic() | |
return wrapper | |
return decorator | |
_domain_funcq_map = {} | |
DOMAIN_CONCURRENCY = 2 | |
async def get_page(url): | |
domain = urllib.parse.urlparse(url).hostname | |
if domain not in _domain_funcq_map: | |
q = _domain_funcq_map[domain] = asyncio.Queue() | |
for _ in range(DOMAIN_CONCURRENCY): | |
q.put_nowait(throttling(1)(_get_page)) | |
func = await _domain_funcq_map[domain].get() | |
try: | |
return await func(url) | |
finally: | |
_domain_funcq_map[domain].put_nowait(func) | |
async def _get_page(url): | |
async with await aiohttp.get(url) as resp: | |
body = await resp.read() | |
return body | |
if __name__ == '__main__': | |
urls = [ | |
'http://localhost/1', | |
'http://localhost/2', | |
'http://localhost/3', | |
'http://localhost/4', | |
'http://localhost/5', | |
'http://localhost.localdomain/6', | |
] | |
loop = asyncio.get_event_loop() | |
print(loop.run_until_complete(asyncio.wait([get_page(u) for u in urls]))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
get_page()
を呼ぶだけ