python协程爬虫-aiohttp+aiomultiprocess使用

最近使用协程写了个爬虫,效果杠杠的啊,使用aiohttp替代requests发起请求,requests是同步的,会阻塞比较久,再加上aiomultiprocess,实现多进程异步协程,每个进程都单独的事件循环执行多个协程任务;这篇文章主要是记录下这两个库的使用

aiohttp

aiohttp是基于asyncio的一个异步http客户端和服务器

官方文档:https://aiohttp.readthedocs.io/en/stable/client_quickstart.html

这里我主要记录客户端的操作

简单实用例子

async def funct(index):    
    print("start ", index)    
    async with aiohttp.ClientSession() as session:        
        async with session.get("https://movie.douban.com/top250?start=0", timeout=5) as resp:            
            print(resp.status)
            print(await resp.text())    
    print("end ", index)

  

是要先创建一个会话,然后使用这个会话进行请求

aiohttp.ClientSession()

创建会话,session提供了各种请求方法,如get、post、delete、put等

这里认识了新的关键字async with,因为是协程的上下文管理,所以多了async关键字

这个不是强制使用的,你也可以自己手动关闭会话,但是一定要记得关闭

注意:

1、不要为每个请求创建会话。每个应用程序很可能需要一个会话来执行所有请求。

2、aiohttp在发送请求之前在内部执行URL 规范化。要禁用规范化,请使用encoded=True参数进行URL构建

 

获取响应信息

resp.status # 状态码
await resp.text() # 获取响应正文,可以指定编码
await resp.read() # 读取二进制响应内容
await resp.json() # 获取json响应内容
await resp.content.read(size) # 读取流

注意事项:aiohttp是在await resp.text()之后才发起请求的,所以必须调用之后才能获取响应的内容,不然会出现异常aiohttp.client_exceptions.ClientConnectionError: Connection closed

aiomultiprocess

asyncio和多处理本身是有用的,但有局限性:asyncio仍然不能超过GIL的速度,并且多处理一次只能处理一个任务。但是,他们在一起可以充分实现自己的真正潜力。

aiomultiprocess提供了一个简单的界面,同时在每个子进程上运行完整的asyncio事件循环,从而实现了Python应用程序从未有过的并发级别。每个子进程可以一次执行多个协程,仅受工作量和可用内核数限制。

注:aiomultiprocess需要Python 3.6或更高版本

用法

在子进程中执行协程

import asyncio
from aiohttp import request
from aiomultiprocess import Process
​
async def put(url, params):
    async with request("PUT", url, params=params) as response:
        pass
​
async def main():
    p = Process(target=put, args=("https://jreese.sh", {}))
    await p
​
if __name__ == "__main__":
    asyncio.run(main())

  

 

如果您想从协程中获取结果Worker,请使用以下方法:

import asyncio
from aiohttp import request
from aiomultiprocess import Worker
​
async def get(url):
    async with request("GET", url) as response:
        return await response.text("utf-8")
​
async def main():
    p = Worker(target=get, args=("https://jreese.sh", ))
    response = await p
​
if __name__ == "__main__":
    asyncio.run(main())

   

如果您需要一个托管的工作进程池,请使用Pool

import asyncio
from aiohttp import request
from aiomultiprocess import Pool

async def get(url):
    async with request("GET", url) as response:
        return await response.text("utf-8")

async def main():
    urls = ["https://jreese.sh", ...]
    async with Pool() as pool:
        result = await pool.map(get, urls)

if __name__ == "__main__":
    asyncio.run(main())

 

 

posted @ 2020-02-25 23:03  Alummox  阅读(2996)  评论(0编辑  收藏  举报