【JS逆向课件:第十三课:异步爬虫】

简介: 回调函数就是回头调用的函数

回顾
并行和并发

表示程序/计算机具有处理多个任务的能力
并行表示可以同时处理多个任务(几个多核CPU)
并发无法同时处理多个任务,但是可以基于时间片轮转法在多任务间快速切换的执行任务。
同步和异步

在基于并行或者并发处理任务的时候,任务中如果出现阻塞操作,就可以选择使用同步或者异步的方式进行处理阻塞操作。
同步处理:让CPU等待阻塞操作结束后,在继续执行处理阻塞后面的其他操作。
异步处理:遇到阻塞操作当前任务会交出CPU的使用权,让CPU可以继续处理其他任务。
因此,在异步应用的过程中,如果一个任务出现了阻塞操作,可以将阻塞操作单独封装成一个单独的任务。
进程和线程

是用来实现异步的两种技术手段
在异步应用的过程中,如果一个任务出现了阻塞操作,可以将阻塞操作单独封装成一个单独的任务,这个任务就是进程或者线程。
协程(重要!)
我们知道,无论是多进程还是多线程,在遇到IO阻塞时都会被操作系统强行剥夺走CPU的执行权限(使得cup执行其他操作,其他操作可能是我们程序的其他部分,也可能是其他的应用程序),我们自己程序的执行效率因此就降低了下来。

解决这一问题的关键在于:

我们自己从自己的应用程序级别检测到IO阻塞,然后使得cpu切换到我们自己程序的其他部分/任务执行(这里的任务指的是当前我们自己程序表示的进程或线程中的某一组操作/子程序),这样可以把我们程序的IO阻塞降到最低,我们的程序处于就绪态就会增多,以此来迷惑操作系统,操作系统便以为我们的程序是IO阻塞比较少的程序,从而会尽可能多的分配CPU给我们,这样也就达到了提升程序执行效率的目的。
通俗理解:
一个线程/进程可以表示一组指定行为的操作,这个操作可以由多个执行步骤组成,这些执行步骤有的是阻塞操作有的非阻塞操作,那么,当cpu执行当前进程/线程的时候遇到了阻塞的执行步骤的时候,如果不对其处理,则包含当前执行步骤的进程/线程就会被挂起进入到阻塞状态,且交出cpu的使用权(cpu就被别人抢走了)。那么如果遇到阻塞的执行步骤,我们的程序可以检测出它是阻塞的,且可以将cpu切换到我们自己程序其他非阻塞的执行步骤时,则包含这些执行步骤的进程/线程就不会进入到阻塞状态,从而减少进程/线程的阻塞状态,增加就绪状态(牢牢抢占cup)极大幅度提升程序执行的效率。
因此,有了协程后,在单进程或者单线程的模式下,就可以大幅度提升程序的运行效率了!
在python3.5之后新增了asyncio模块,可以帮我们检测IO(只能是网络IO【HTTP连接就是网络IO操作】),实现应用程序级别的切换(异步IO)。

接下来让我们来了解下协程的实现,从 Python 3.4 开始,Python 中加入了协程的概念,但这个版本的协程还是以生成器对象为基础的,在 Python 3.5 则增加了 asyncio,使得协程的实现更加方便。首先我们需要了解下面几个概念:

特殊函数:

在函数定义前添加一个async关键字,则该函数就变为了一个特殊的函数!
特殊函数的特殊之处是什么?
1.特殊函数被调用后,函数内部的程序语句(函数体)没有被立即执行
2.特殊函数被调用后,会返回一个协程对象
协程:

协程对象,特殊函数调用后就可以返回/创建了一个协程对象。
协程对象 == 特殊的函数 == 一组指定形式的操作
协程对象 == 一组指定形式的操作
任务:

任务对象就是一个高级的协程对象。高级之处,后面讲,不着急!
任务对象 == 协程对象 == 一组指定形式的操作
任务对象 == 一组指定形式的操作
事件循环:

事件循环对象(Event Loop),可以将其当做是一个容器,该容器是用来装载任务对象的。所以说,让创建好了一个或多个任务对象后,下一步就需要将任务对象全部装载在事件循环对象中。
思考:为什么需要将任务对象装载在事件循环对象?
当将任务对象装载在事件循环中后,启动事件循环对象,则其内部装载的任务对象对应的相关操作就会被立即执行。
import asyncio
import time

特殊的函数

async def get_request(url):
print('正在请求的网址是:',url)
time.sleep(2)
print('请求网址结束!')
return 123

创建了一个协程对象

c = get_request('www.1.com')

创建任务对象

task = asyncio.ensure_future(c)

创建事件循环对象

loop = asyncio.get_event_loop()

将任务对象装载在loop对象中且启动事件循环对象

loop.run_until_complete(task)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
任务对象对比协程对象的高级之处重点在于:

可以给任务对象绑定一个回调函数!

回调函数有什么作用?

回调函数就是回头调用的函数,因此要这么理解,当任务对象被执行结束后,会立即调用给任务对象绑定的这个回调函数!

相关文章
|
数据采集 存储 JSON
Python爬取知乎评论:多线程与异步爬虫的性能优化
Python爬取知乎评论:多线程与异步爬虫的性能优化
|
数据采集 存储 C++
Python异步爬虫(aiohttp)加速微信公众号图片下载
Python异步爬虫(aiohttp)加速微信公众号图片下载
|
10月前
|
数据采集 人工智能 JSON
Prompt 工程实战:如何让 AI 生成高质量的 aiohttp 异步爬虫代码
Prompt 工程实战:如何让 AI 生成高质量的 aiohttp 异步爬虫代码
|
数据采集 安全 网络安全
使用aiohttp实现异步HTTPS爬虫的SSL优化
使用aiohttp实现异步HTTPS爬虫的SSL优化
782 81
|
Web App开发 JavaScript 前端开发
如何在JavaScript中确定异步操作之间的依赖关系?
如何在JavaScript中确定异步操作之间的依赖关系?
596 156
|
JSON 前端开发 JavaScript
在 JavaScript 中,如何使用 Promise 处理异步操作?
通过以上方式,可以使用Promise来有效地处理各种异步操作,使异步代码更加清晰、易读和易于维护,避免了回调地狱的问题,提高了代码的质量和可维护性。
|
JavaScript 前端开发 API
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
消息中间件 JavaScript 前端开发
最细最有条理解析:事件循环(消息循环)是什么?为什么JS需要异步
度一教育的袁进老师谈到他的理解:单线程是异步产生的原因,事件循环是异步的实现方式。 本质是因为渲染进程因为计算机图形学的限制,只能是单线程。所以需要“异步”这个技术思想来解决页面阻塞的问题,而“事件循环”是实现“异步”这个技术思想的最主要的技术手段。 但事件循环并不是全部的技术手段,比如Promise,虽然受事件循环管理,但是如果没有事件循环,单一Promise依然能实现异步不是吗? 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您
|
数据采集 JavaScript 前端开发
JavaScript重定向对网络爬虫的影响及处理
JavaScript重定向对网络爬虫的影响及处理