python爬虫--多任务异步协程, 快点,在快点......
多任务异步协程asyncio
特殊函数: - 就是async关键字修饰的一个函数的定义 - 特殊之处: - 特殊函数被调用后会返回一个协程对象 - 特殊函数调用后内部的程序语句没有被立即执行 - 协程 - 对象。协程==特殊的函数。协程表示的就是一组特定的操作。 - 任务对象 - 高级的协程(对协程的进一步的封装) - 任务对象==协程==特殊的函数 - 任务对象==特殊的函数 - 绑定回调: - task.add_done_callback(task) - 参数task:当前回调函数对应的任务对象 - task.result():返回的就是任务对象对应的特殊函数的返回值 - 事件循环对象 - 创建事件循环对象 - 将任务对象注册到该对象中并且开启该对象 - 作用:loop可以将其内部注册的所有的任务对象进行异步执行 - 挂起:就是交出cpu的使用权。 await:被用做在特殊函数的内部,在被阻塞的时候 wait:给每一个任务赋予一个可被挂起的权限 #【重点】在特殊函数内部的实现中,不可以出现不支持异步的模块(例如time,requests)代码,如果出现了,则会中断整个的异步效果!!!
asyncio的使用
import asyncio import time from time import sleep # 特殊函数 async def get_request(url): print('正在下载: ',url) sleep(2) print('下载完毕: ',url) return 'page_text' # 回调函数,普通函数 def parse(task): # 参数表示任务对象 print('i am callback',task.result()) start = time.time() # 调用特殊函数 func = get_request('www.xx.com') # 创建任务对象 task = asyncio.ensure_future(func) # 给任务对象绑定回调函数 task.add_done_callback(parse) # 创建一个事件循环对象 loop = asyncio.get_event_loop() # 让loop执行一个任务 loop.run_until_complete(task) print("总耗时:",time.time()-start) #总耗时: 2.0017831325531006
多任务协程
import asyncio import time # 特殊函数 async def get_request(url): print('正在下载',url) # time.sleep(2) 不支持异步的模块 会中断整个的异步效果 await asyncio.sleep(2) print('下载完成',url) return 'page_text' def parse(task): print(task.result()) start = time.time() urls = ['www.xxx1.com','www.xxx2.com','www.xxx3.com'] tasks = [] #存放多任务 for url in urls: # 调用特殊函数 func = get_request(url) # 创建任务对象 task = asyncio.ensure_future(func) # 给任务对象绑定回调函数 task.add_done_callback(parse) tasks.append(task) # 创建事件循环对象 loop = asyncio.get_event_loop() # 执行任务 loop.run_until_complete(asyncio.wait(tasks)) print('总耗时:',time.time()-start) #2.0015313625335693
aiohttp的使用
- requests一定是不支持异步 - aiohttp是一个支持异步的网络请求模块 - 环境安装 - 编码流程: - 大致的架构: with aiohttp.ClientSession() as s: #s.get(url,headers,params,proxy="http://ip:port") with s.get(url) as response: #response.read()二进制(.content) page_text = response.text() return page_text - 补充细节 - 在每一个with前加上async - 需要在每一个阻塞操作前加上await async with aiohttp.ClientSession() as s: #s.get(url,headers,params,proxy="http://ip:port") async with await s.get(url) as response: #response.read()二进制(.content) page_text = await response.text() return page_text
异步协程爬虫案例
# 需求用多任务异步协程获取百度,搜狗,京东,淘宝的页面源码数据,并简单解析 import asyncio import requests import time from lxml import etree urls = ['https://www.baidu.com','http://www.taobao.com/','http://www.jd.com/','https://www.sogou.com/'] headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36' } # 特殊函数 async def get_request(url): print('正在下载',url) page_text = requests.get(url,headers=headers).text print(url,'下载完成') return page_text # 回调函数 def parse(task): page_text = task.result() tree = etree.HTML(page_text) div = tree.xpath('//div') print(div) start = time.time() tasks = []#存放多任务 for url in urls: func = get_request(url) task = asyncio.ensure_future(func) task.add_done_callback(parse) tasks.append(task) # 创建事件要在循环外 loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) print('总耗时:',time.time()-start) #根据结果发现执行并不是异步,原因是requests不是异步模块,所以整个程序不会异步执行
基于aiohttp的多任务协程的爬虫
# 需求用多任务异步协程获取百度,搜狗,京东,淘宝的页面源码数据,并简答解析 import asyncio import requests import time import aiohttp from lxml import etree urls = ['https://www.baidu.com','http://www.taobao.com/','http://www.jd.com/','https://www.sogou.com/'] headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36' } # 特殊函数 async def get_request(url): async with aiohttp.ClientSession() as s: # s.get(url,headers,params,proxy="http://ip:port") async with await s.get(url,headers=headers) as response: print('正在下载', url) # response.read()二进制(.content) page_text = await response.text() print(url, '下载完成') return page_text # 回调函数 def parse(task): page_text = task.result() tree = etree.HTML(page_text) div = tree.xpath('//div') print(div) start = time.time() tasks = []#存放多任务 for url in urls: func = get_request(url) task = asyncio.ensure_future(func) task.add_done_callback(parse) tasks.append(task) # 创建事件要在循环外 loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) print('总耗时:',time.time()-start) #总耗时: 3.0848371982574463
相关推荐
efeve 2020-09-14
ericxieforever 2020-09-03
Dimples 2020-06-08
鲁鲁酱 2020-06-02
feishicheng 2020-05-31
paopao00 2020-05-10
georgeandgeorge 2020-05-09
Greatemperor 2020-05-03
jacktangj 2020-04-17
CloudXli 2020-04-07
oXiaoChong 2020-04-07
学习备忘录 2020-02-18
wyqwilliam 2020-02-10
PythonMaker 2020-01-19
ddxygq 2019-12-30
shengge0 2019-12-26
sschencn 2019-12-19
SDUTACM 2019-12-09
Laozizuiku 2019-12-04
mayflowers 2019-11-18
wklken的笔记 2019-11-01