asyncio
能够实现单线程的并发IO操做,若是仅用在客户端,发挥的威力并不大,把asyncio
用在服务端,例如WEB服务器,因为HTTP链接就是IO操做,所以能够用单线程+coroutine
实现多用户的高并发支持。html
asyncio
实现了TCP、UDP、SSL等协议,aiohttp
则是基于asyncio
实现的HTTP框架。json
首先咱们定义一个协同程序用来获取页面,并打印出来。咱们使用asyncio.coroutine将一个方法装饰成一个协同程序,aiohttp.request是一个协同程序,因此他是一个可读方法。服务器
@asyncio.coroutine def print_page(url): response = yield from aiohttp.request('GET', url) #close断开的是网页与服务器的Connection:keep-alive body = yield from response.read_and_close(dcode=True) print(body)
如你所见,咱们可使用yield from从另外一个协程中调用一个协程。为了从同步代码中调用一个协程,咱们须要一个时间循环,咱们能够经过asyncio.get_event_loop()获得一个标准的时间循环,以后使用它的loop.run_until_complete()方法启动协程,因此,为了使以前的协程运行咱们只须要作:cookie
loop = asyncio.get_evemnt_loop() loop.run_until_complete(print_page('http://xxxxx'))
一个有用的方法是asyncio.wait,经过它能够获取一个协程的列表,同时返回一个将它们包括在内的单独的协程,因此咱们能够这样写:session
loop.run_until_complete(asyncio.wait([print_page(url) for url in url_list]))
如今咱们已经知道如何作异步请求,所以咱们能够写一个数据抓取器,咱们仅仅还须要一些工具来解析HTML并发
import aiohttp import asyncio def get_content(html): ''' 处理HTML获取所需信息 ''' async def print_magnet(page): headers = {'key':'value'} cookies = {'cookies_are': 'working'} url = 'http://www.cnbligs.com/#p{}'.format(page) async with aiohttp.ClientSession(cookies=cookies) as session: async with session.get(url, headers=headers) as response: content = get_content(await response.text()) print(await response.text()) loop = asyncio.get_event_loop() tasks = asyncio.wait([print_magnet(page) for page in range(10)]) loop.run_until_complete(tasks)
为了不爬虫一次性的产生过多的请求致使帐号/IP被封能够考虑使Semaphore控制同时的并发量,与咱们熟悉的threading模块中的Semaphore(信号量)用法相似。框架
import aiohttp impoer asyncio NUMBERS = range(12) URL = 'http://httpbin.org/get?a={}' sema = asyncio.Semaphore(3) async def fetch_async(a): async with aiohttp.request('GET', URL.format(a)) as res: data = await r.json() return data['args']['a'] async def print_result(a): with (await sema): r = await fetch_async(a) print('fetch({}) = {}'.foemat(a, r)) loop = asyncio.get_event_loop() f = asyncio.wait([print_result(num) for num in NUMBERS]) loop.run_until_complete(f)
能够到后台看到并发受到了信号量的限制,同一时刻基本只处理三个请求。异步