1.测试学习

(2)单线程:

from time import sleep
import time
def request(url):print('正在请求:',url)sleep(2)print('下载成功:', url)
urls = ['www.baidu.com','www.sogou.com','www.goubanjia.com']
start = time.time()
for url in urls:request(url)
print(time.time()-start)

测试结果:需要6秒多

正在请求: www.baidu.com
下载成功: www.baidu.com
正在请求: www.sogou.com
下载成功: www.sogou.com
正在请求: www.goubanjia.com
下载成功: www.goubanjia.com
6.001747369766235

(2)开启线程池:测试结果是2秒多

from time import sleep
import time
from multiprocessing.dummy import Pool
def request(url):print('正在请求:',url)sleep(2)print('下载成功:', url)
urls = ['www.baidu.com','www.sogou.com','www.goubanjia.com']
start = time.time()
pool=Pool(3)
pool.map(request,urls)
print(time.time()-start)

测试结果:

正在请求: www.baidu.com
正在请求: www.sogou.com
正在请求: www.goubanjia.com
下载成功: www.goubanjia.com
下载成功: www.sogou.com
下载成功: www.baidu.com
2.034695625305176

(3)在程序中是否可以一味的使用多线程,多进程?

推荐:单线程+异步协程(效率最高,用的人不是很多,大量爬取数据是会用到的)

下面了解一下

协程(go和python独有的概念),,协程不会占用很高的内存

领导在乎的是把数据爬取出来.

主要还是request模块的学习.下面学习几个概念这几个概念,一会儿会在代码中有所体现

event_loop:事件循环,相当于一个无限循环,我们可以把一些特殊函数注册(放置)到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。程序是按照设定的顺序从头执行到尾,运行的次数也是完全按照设定。当在编写异步程序时,必然其中有部分程序的运行耗时是比较久的,需要先让出当前程序的控制权,让其在背后运行,让另一部分的程序先运行起来。当背后运行的程序完成后,也需要及时通知主程序已经完成任务可以进行下一步操作,但这个过程所需的时间是不确定的,需要主程序不断的监听状态,一旦收到了任务完成的消息,就开始进行下一步。loop就是这个持续不断的监视器。coroutine:中文翻译叫协程,在 Python 中常指代为协程对象类型,我们可以将协程对象注册到事件循环中,
它会被事件循环调用。我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,
而是返回一个协程对象。task:任务对象,它是对协程对象的进一步封装,包含了任务的各个状态。future:任务对象,代表将来执行或还没有执行的任务,实际上和 task 没有本质区别。另外我们还需要了解 async/await 关键字,它是从 Python 3.6 才出现的,专门用于定义协程。其中,async 定义一个协程,await 用来挂起阻塞方法的执行。

(4)协程基础

#asyncio是python3.6才出来的一种技术
import asyncio
async def requests(url):    #被async修饰,就会没有返回值,内部不会执行,只返回一个协程对象print('正在请求:',url)print('下载成功:',url)
c=requests('www.baidu.com')
print(c)

得到下面的结果:

<coroutine object requests at 0x000001A6E0150410>
sys:1: RuntimeWarning: coroutine 'requests' was never awaited

(5)升级初版

import asyncio
async def requests(url):  #async本质上是个生成器print('正在请求:',url)print('下载成功:',url)
c=requests('www.baidu.com')#实例化一个事件循环对象
loop=asyncio.get_event_loop()#将协程对象注册到时间循环对象中,并且我们需要启动事件循环对象
loop.run_until_complete(c)    #可以无限循环的位置(c...)

得到下面的结果:

正在请求: www.baidu.com
下载成功: www.baidu.com

(6)

import asyncio
async def requests(url):  #async本质上是个生成器,特殊函数async关键字print('正在请求:',url)print('下载成功:',url)
c=requests('www.baidu.com')      #协程#实例化一个事件循环对象
loop=asyncio.get_event_loop()#添加的新点,任务对象
#方法1:创建一个任务对象,将协程对象封装到了该对象中
task=loop.create_task(c)  #这一步是进一步的处理,.   #任务对象
#方法2:另一种形式实例化任务对象的方法,不需要上边的实例化事件循环对象
# task=asyncio.ensure_future(c)
print(task)   #pending
#将协程对象注册到事件循环对象中,并且我们需要启动事件循环对象
loop.run_until_complete(task)  #括号里边可以有多个参数,无限循环  #事件循环
print(task)     #finished
#核心:绑定回调

注意:任务对象就是对协程的一种封装

结果:

<Task pending coro=<requests() running at F:/Python_workspace_S18/papa_part/day4/2.协程基础.py:49>>
正在请求: www.baidu.com
下载成功: www.baidu.com
<Task finished coro=<requests() done, defined at F:/Python_workspace_S18/papa_part/day4/2.协程基础.py:49> result=None>

(7)给任务对象绑定回调,这个虽然简单但是及其重要

单任务异步协程

#单任务异步协程
import asyncioasync def request(url):print('正在请求:', url)print('下载成功:', url)return url#回调函数必须有一个参数:task
#task.result():任务对象中封装的协程对象对应的特殊函数内部的返回值
def callbak(task):                  #必须有一个参数,并且必须是任务本身print('the callback')print(task.result())      #result就是上边函数的url
c = request('www.baidu.com')loop=asyncio.get_event_loop()#给任务对象绑定一个回调函数
task=asyncio.ensure_future(c)      #先执行这一步,才能执行回调
task.add_done_callback(callbak)    #这个多了一个回调函数
#什么是回调函数?当任务对象执行完成之后,可以回头调用给其绑定的另外一个函数
loop.run_until_complete(task)       #全部执行完成之后,才执行回调函数

结果:

正在请求: www.baidu.com
下载成功: www.baidu.com
the callback
www.baidu.com

另一种写法:

#单任务异步协程
import asyncioasync def request(url):print('正在请求:', url)print('下载成功:', url)return url#回调函数必须有一个参数:task
#task.result():任务对象中封装的协程对象对应的特殊函数内部的返回值
def callbak(task):                  #必须有一个参数,并且必须是任务本身print('the callback')print(task.result())      #result就是上边函数的url
c = request('www.baidu.com')loop=asyncio.get_event_loop()#给任务对象绑定一个回调函数
# task=asyncio.ensure_future(c)      #先执行这一步,才能执行回调   #第一种写法
task=loop.create_task(c)                                        #第二种写法
task.add_done_callback(callbak)    #这个多了一个回调函数
#什么是回调函数?当任务对象执行完成之后,可以回头调用给其绑定的另外一个函数
loop.run_until_complete(task)       #全部执行完成之后,才执行回调函数

回调函数的目的:对数据进行解析

(8)多任务异步协程:(1个任务不是异步),

只有多任务异步协程才是有意义的

asyncio出现来了async和await

from time import sleep
import asyncio
import time
urls = ['www.baidu.com','www.sogou.com','www.goubanjia.com']
start = time.time()
async def request(url):print('正在请求:',url)#在多任务异步协程实现中,不可以出现不支持异步的相关代码。比如time模块中的sleep# sleep(2)await asyncio.sleep(2)    #可以用asyncio里边的sleep,才能计算出异步时间,支持异步,并且必须加上await才能等待print('下载成功:',url)loop = asyncio.get_event_loop()         #通过事件循环执行
#任务列表:放置多个任务对象
tasks = []
for url in urls:c = request(url)task = asyncio.ensure_future(c)tasks.append(task)                      #依次追加到列表中loop.run_until_complete(asyncio.wait(tasks))
#作用:将任务对象注册到事件当中,只能启动一次的用法
#里边的参数代表的是,多个事件循环必须是异步的因此需要加上asyncio.wait(),有阻塞就挂起,执行完再搞阻塞print(time.time()-start)

得到下面的结果:

正在请求: www.baidu.com
正在请求: www.sogou.com
正在请求: www.goubanjia.com
下载成功: www.baidu.com
下载成功: www.sogou.com
下载成功: www.goubanjia.com
2.040722608566284

(9)多任务异步协程在flask中的应用

下面是flaskServer.py文件,首先需要安装flask模块

# Author: studybrother sun
from flask import Flask
import timeapp = Flask(__name__)@app.route('/bobo')
def index_bobo():time.sleep(2)    #耗时两秒return 'Hello bobo'@app.route('/jay')
def index_jay():time.sleep(2)return 'Hello jay'@app.route('/tom')
def index_tom():time.sleep(2)return 'Hello tom'if __name__ == '__main__':app.run(threaded=True)

启动:服务器上的程序,访问下面的网址,需要等待2s钟才能得到下面的结果

上边的服务器启动之后,我们再次启动下面的程序

import requests    #目的是发送请求
import asyncio
import time
#单线程+多任务异步协程
urls = ['http://127.0.0.1:5000/jay','http://127.0.0.1:5000/bobo','http://127.0.0.1:5000/tom'
]
start=time.time()
for url in urls:page_text=requests.get(url=url).text   #请求url得到的返回值print(page_text)
print(time.time()-start)

得到下面的结果:

Hello jay
Hello bobo
Hello tom
6.132113456726074

下面是单线程+异步协程在爬虫中的用法:

import requests
import asyncio
import time
#单线程+多任务异步协程
urls = ['http://127.0.0.1:5000/jay','http://127.0.0.1:5000/bobo','http://127.0.0.1:5000/tom'
]
async def get_pageText(url):print('正在下载:',url) #requests模块是不支持异步操作的。,下面是6s的原因,不支持异步page_text = requests.get(url).textprint('下载完毕:',url)return page_textstart = time.time()
tasks = []
for url in urls:c = get_pageText(url)task = asyncio.ensure_future(c)tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))    #这行代码表示注册,以及启动的作用print(time.time()-start)

得到下面的结果:

正在下载: http://127.0.0.1:5000/jay
下载完毕: http://127.0.0.1:5000/jay
正在下载: http://127.0.0.1:5000/bobo
下载完毕: http://127.0.0.1:5000/bobo
正在下载: http://127.0.0.1:5000/tom
下载完毕: http://127.0.0.1:5000/tom
6.1820220947265625

应该是2s多,怎么会这样????

#aiohttp:支持异步的一个基于网络请求的模块
# pip install aiohttp     #安装这个异步请求模块import requests
import asyncio
import time
import aiohttp        #支持异步的网络请求内容,升级支持异步请求的requests模块
#单线程+多任务异步协程
urls = ['http://127.0.0.1:5000/jay','http://127.0.0.1:5000/bobo','http://127.0.0.1:5000/tom'
]
#代理操作:
#async with await s.get(url,proxy="http://ip:port") as response:
async def get_pageText(url):async with aiohttp.ClientSession() as s:         #实例化请求对象async with await s.get(url) as response:      #得到相应对象,在异步中有with就需要加上async#发起请求也是需要加上await的page_text = await response.text()          #注意这个地方text是个方法,得到响应数据就需要先挂起# 借助于回调函数进行响应数据的解析操作awaitprint(page_text)return page_text
#封装回调函数用于数据解析start = time.time()
tasks = []
for url in urls:c = get_pageText(url)task = asyncio.ensure_future(c)#给任务对象绑定回调函数用于数据解析tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))print(time.time()-start)

已经实现.得到下面的结果:

Hello jay
Hello bobo
Hello tom
2.1180801391601562

升级:

#aiohttp:支持异步的一个基于网络请求的模块
# pip install aiohttpimport requests
import asyncio
import time
import aiohttp        #支持异步的网络请求内容,升级支持异步请求的requests模块
#单线程+多任务异步协程
urls = ['http://127.0.0.1:5000/jay','http://127.0.0.1:5000/bobo','http://127.0.0.1:5000/tom'
]
#代理操作:写代理时候的区别
#async with await s.get(url,proxy="http://ip:port") as response:
async def get_pageText(url):async with aiohttp.ClientSession() as s:         #实例化请求对象async with await s.get(url) as response:      #得到相应对象,在异步中有with就需要加上async#发起请求也是需要加上await的page_text = await response.text()          #注意这个地方text是个方法,得到响应数据就需要先挂起# 借助于回调函数进行响应数据的解析操作awaitprint(page_text)return page_text
#封装回调函数用于数据解析
def parse(task):               #回调函数#1.获取响应数据page_text = task.result()print(page_text+',即将进行数据解析!!!')#解析操作写在该位置start = time.time()
tasks = []
for url in urls:c = get_pageText(url)task = asyncio.ensure_future(c)#给任务对象绑定回调函数用于数据解析task.add_done_callback(parse)tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))print(time.time()-start)

下面得到的结果:顺序jay>bobo>tom>

  注意:这个是有一定顺序的

Hello jay
Hello jay,即将进行数据解析!!!
Hello bobo
Hello bobo,即将进行数据解析!!!
Hello tom
Hello tom,即将进行数据解析!!!
2.0991756916046143

get里边是paras,post里边是data,这个参数注意一下,还有代理还是有区别的,复数变成了单数

音频,视频,占用的视频比较大,可以用这个,一般是不用的.

转载于:https://www.cnblogs.com/studybrother/p/10951229.html

小爬爬4.协程基本用法多任务异步协程爬虫示例(大数据量)相关推荐

  1. python爬虫02-提升爬取效率、多线程,多线程传参,多进程,线程及线程池概念,协程,多任务异步协程,异步请求aiohttp模块,视频站工作原理

    1.提升爬取效率 使用多线程,多进程,携程,异步 2.多线程 进程是资源单位,每个进程,都会有一个默认的主线程 线程是执行单位 执行多线程需要导包: from threading import Thr ...

  2. 爬虫的单线程+多任务异步协程:asyncio 3.6

    单线程+多任务异步协程:asyncio 3.6 事件循环 无限循环的对象.事件循环中最终需要将一些 特殊的函数(被async关键字修饰的函数) 注册在该对象中. 协程 本质上是一个对象.可以把协程对象 ...

  3. python爬虫 asyncio aiohttp aiofiles 单线程多任务异步协程爬取图片

    python爬虫 asyncio aiohttp aiofiles 多任务异步协程爬取图片 main.py """=== coding: UTF8 ==="&q ...

  4. python爬虫 单线程的多任务异步协程

    在input().sleep(2).request.get()等时,都会导致线程阻塞,协程可以解决IO等操作时的阻塞现象,提高CPU利用效率. 1.单线程的多任务异步协程 main.py " ...

  5. 爬虫第四章 单线程+多任务异步协程

    单线程+多任务异步协程: asyncio 事件循环 loop: 无限循环的对象,事件循环中最终需要将一些特殊的函数注册到该事件循环中特殊的函数: 被ansyc关键字修饰的函数协程: 本质上是一个对象, ...

  6. java导出Excel增加下拉框选项,解决小数据量和大数据量下拉框选项的问题

    文章目录 java导出Excel增加下拉框选项 一.小数据量情况 二.大数据量情况 java导出Excel增加下拉框选项(java结合easyExcel) 添加传参模型ConsumablesAddDT ...

  7. 【机器学习算法实践】lightGBM将可解释的机器学习实现工业落地,小数据量机器学习就够了,大数据量还得深度学习。推荐看论文进行理解,boosting方法有残差的感觉了

    LightGBM是2017年由微软推出的可扩展机器学习系统,是微软旗下DMKT的一个开源项目,由2014年首届阿里巴巴大数据竞赛获胜者之一柯国霖老师带领开发.它是一款基于GBDT(梯度提升决策树)算法 ...

  8. 11 单线程+多任务异步协程 爬虫

    # from lxml import etree import asyncio import aiohttp import time def callback(task): # 回调函数page = ...

  9. 同程旅行王晓波:同程凤凰缓存系统在基于 Redis 方面的设计与实践(上篇)

    王晓波 同程旅行机票事业群 CTO 读完需要 12 分钟 速读仅需 4 分钟 本章和大家分享一下同程凤凰缓存系统在基于 Redis 方面的设计与实践.在本章中除了会列举我们工作过程中遇到各种问题和误区 ...

最新文章

  1. 实现Java中的ArrayList
  2. C++ 与 JAVA区别
  3. 使用Silverlight for Embedded开发绚丽的界面(4)
  4. hdu 4886(hash + dfs)
  5. Matlab中特征选择reliefF算法使用方法(分类与回归)
  6. MFC学习之路之多媒体 --(1) DirectShow
  7. Java实训项目4:GUI学生信息管理系统 - 项目结构图
  8. 工作绩效数据、工作绩效信息和工作绩效报告的区别
  9. linux内核分析和应用 -- 进程与线程(上)
  10. HTML5权威指南pdf
  11. axure iphone8元件库_Axure中移动端原型设计方法(附IPhoneX和IPhone8最新模板)
  12. 视频剪辑-mkv文件导入PR
  13. 在Linux中进行GO语言安装
  14. 台式计算机cpu允许温度,台式机cpu温度多少正常 台式机cpu正常温度
  15. OFDM 调制系统框图 OFDM
  16. 企业发放的奖金根据利润提成计算
  17. python循环输出1到10_用Python编写一个程序,使用for循环输出0~10之间的整数
  18. Linux设备上时间不准确?使用chrony服务配置时间服务器实现Linux时间同步以及实现主从设备时间同步
  19. 密集创投迎来爆发期 今年会是链游之年么?
  20. Apache Thrift 官方JAVA教程

热门文章

  1. 这才是中医养生的至高境界,没有治不好的病!
  2. 【数据库】数据库入门(七): 函数依赖(Functional Dependencies)
  3. C#上位机,信捷XD系列modbus485通信例子
  4. 使用 hexo 和 gitee 免费搭建个人博客
  5. 天宝MN18 amd4800h mini主机 到手测试
  6. mysql储存过程是什么意思_数据库原理mysql储存过程
  7. 调查: 不同软件的受欢迎程度
  8. 板绘人物侧脸怎么画?新手一看就会!
  9. 后悔买房了,每个月还房贷实在是太难了
  10. JavaScript比较日期大小(js比较日期大小)