【Python爬虫实战】深入理解Python异步编程:从协程基础到高效爬虫实现
#1024程序员节|征文#
🌈个人主页:易辰君-CSDN博客
🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html
目录
前言
一、异步
(一)核心概念
(二)应用场景
(三)优缺点
二、协程异步实现方法
(一)基本的协程定义与运行
(二)并发执行多个协程
(三)创建与管理任务
(四)限制并发数
(五)超时控制
(六)队列管理
三、同步和异步的对比
(一)执行方式
(二) 阻塞与非阻塞
(三)性能和效率
(四)代码复杂性
(五)应用场景
(六)示例对比
四、异步爬虫
(一)异步爬虫的优点
(二)实现异步爬虫的基本步骤
(三)控制并发数量
(四)应用场景
(五)注意事项
五、总结
前言
随着网络和数据的迅速发展,越来越多的场景需要高效处理大量请求和数据。传统的同步编程模式在处理I/O密集型任务时会浪费大量等待时间,而Python的异步编程技术提供了一种更高效的方式。本文从Python异步编程的基础概念出发,深入讲解协程、asyncio
库及其核心功能。通过详细的代码示例与解释,我们将逐步探索异步编程的应用场景
一、异步
在Python中,异步编程是一种并发编程方法,允许程序在处理耗时任务时不必等待任务完成,而是继续执行其他代码。这样可以提升程序的效率和响应速度,特别适合处理I/O密集型任务(如网络请求、文件读写等)。
(一)核心概念
(1)事件循环: 异步编程的核心是事件循环(Event Loop),它管理任务的调度。事件循环会不断地检查是否有任务完成或需要开始新任务,从而实现任务的非阻塞执行。
(2)协程(Coroutine): 协程是异步任务的基本单元,是一个可以被挂起并在稍后继续执行的函数。Python 通过 async def
定义协程函数,协程内部可以用 await
来暂停并等待其他协程的结果。
(3)async
和 await
关键字:
-
async
用于定义一个协程函数,例如async def my_function()
。 -
await
用于暂停协程的执行并等待其他协程完成。例如,await some_async_task()
会暂停当前协程,直到some_async_task()
完成后再继续执行。
(4)asyncio
库: Python 的标准库 asyncio
提供了异步编程的核心功能,包含事件循环、任务管理、以及异步 I/O 操作等工具,帮助处理并发任务。
(二)应用场景
异步编程非常适合处理以下场景:
-
网络请求(如 HTTP 请求、数据库查询等)
-
文件读写操作
-
大量并发任务(如网络爬虫、数据采集)
示例:
import asyncioasync def task(name, delay):print(f"Task {name} started")await asyncio.sleep(delay) # 模拟一个异步I/O操作print(f"Task {name} completed")async def main():# 并发执行多个任务await asyncio.gather(task("A", 2),task("B", 1),task("C", 3))# 运行主协程
asyncio.run(main())
在这个例子中,task
是一个协程,使用 await asyncio.sleep(delay)
来模拟一个耗时任务。在 main
函数中,asyncio.gather
可以并发地执行多个 task
,而不需要等待其中一个任务完成才执行下一个。
(三)优缺点
-
优点:相比传统同步方法,异步编程在 I/O 密集型任务上更高效、响应更快。
-
缺点:异步代码的逻辑较难理解和调试,并且在 CPU 密集型任务上并不一定有优势。
二、协程异步实现方法
在Python中,使用协程实现异步的主要方法是通过 async
和 await
关键字以及 asyncio
库来管理协程和事件循环。这使得我们能够编写出非阻塞的代码,有效地进行异步任务调度。下面是几种常用的协程异步实现方法:
(一)基本的协程定义与运行
import asyncioasync def my_task():print("Task started")await asyncio.sleep(1) # 模拟异步操作print("Task completed")# 运行协程
asyncio.run(my_task())
在这个例子中:
-
my_task
是一个协程,使用async def
定义。 -
await asyncio.sleep(1)
模拟一个异步操作。在实际应用中,这可以替换为其他 I/O 操作,比如网络请求。
(二)并发执行多个协程
可以使用 asyncio.gather
并发运行多个协程,将它们一起调度,以便程序在等待一个任务时可以继续执行其他任务:
async def task(name, delay):print(f"Task {name} started")await asyncio.sleep(delay)print(f"Task {name} completed")async def main():await asyncio.gather(task("A", 2),task("B", 1),task("C", 3))asyncio.run(main())
在这里,asyncio.gather
接收多个协程,创建一个任务组,多个任务会并发执行,节省时间。
(三)创建与管理任务
asyncio.create_task
将协程封装成任务并立即调度,而不需要等待所有任务完成:
async def task(name):print(f"Task {name} started")await asyncio.sleep(1)print(f"Task {name} completed")async def main():task1 = asyncio.create_task(task("A"))task2 = asyncio.create_task(task("B"))# 可以在这里添加其他逻辑await task1await task2asyncio.run(main())
通过 asyncio.create_task
,可以先开始任务,然后在稍后使用 await
等待其完成。这样可以在需要时调度多个任务,并在合适的位置等待结果。
(四)限制并发数
在某些场景中需要限制并发数,可以使用 asyncio.Semaphore
控制:
import asynciosemaphore = asyncio.Semaphore(2)async def limited_task(name, delay):async with semaphore:print(f"Task {name} started")await asyncio.sleep(delay)print(f"Task {name} completed")async def main():await asyncio.gather(limited_task("A", 2),limited_task("B", 1),limited_task("C", 3),limited_task("D", 1))asyncio.run(main())
在这个例子中,asyncio.Semaphore(2)
设置同时最多只能有两个任务在执行,其他任务必须等待。
(五)超时控制
可以使用 asyncio.wait_for
来限制某个任务的最长等待时间:
async def my_task():await asyncio.sleep(3)print("Task completed")async def main():try:await asyncio.wait_for(my_task(), timeout=2)except asyncio.TimeoutError:print("Task timed out")asyncio.run(main())
(六)队列管理
asyncio.Queue
是实现生产者-消费者模式的常用方式,可以让多个协程通过队列共享数据:
async def producer(queue):for i in range(5):await asyncio.sleep(1)await queue.put(f"Item {i}")print(f"Produced Item {i}")async def consumer(queue):while True:item = await queue.get()if item is None:breakprint(f"Consumed {item}")queue.task_done()async def main():queue = asyncio.Queue()producer_task = asyncio.create_task(producer(queue))consumer_task = asyncio.create_task(consumer(queue))await producer_taskawait queue.put(None) # 终止消费者await consumer_taskasyncio.run(main())
在这里,producer
生产数据并放入队列,consumer
从队列中消费数据。队列的使用可以很方便地控制协程之间的数据传递和同步。
三、同步和异步的对比
同步和异步是两种处理任务的不同方式。它们在任务的执行和等待机制上有显著的区别,适合不同的应用场景。以下是它们的详细对比:
(一)执行方式
-
同步:任务按照顺序逐个执行,当前任务完成后才能执行下一个任务。如果一个任务正在执行,其他任务必须等待。
-
异步:任务可以在不等待其他任务完成的情况下启动,任务之间的执行不严格依赖顺序,多个任务可以同时进行(在I/O操作上,异步非常有效)。
(二) 阻塞与非阻塞
-
同步:同步方式是阻塞的,任务在执行期间会阻塞代码的后续执行,直到任务完成才会继续执行下一步。
-
异步:异步方式是非阻塞的,一个任务开始后可以立即开始执行其他任务,不必等待前一个任务完成。
(三)性能和效率
-
同步:在I/O操作频繁的程序中,同步会导致时间浪费,因为程序在等待I/O操作完成时处于空闲状态。适用于计算密集型或对顺序要求严格的场景。
-
异步:通过避免等待,提高了效率和响应速度。特别适用于I/O密集型操作(如网络请求、文件读写等),异步允许程序在等待I/O操作完成时继续处理其他任务。
(四)代码复杂性
-
同步:代码结构相对简单,因为任务是顺序执行的,不涉及任务切换和状态管理,容易理解和调试。
-
异步:代码相对复杂,尤其是在大型项目中,由于任务非顺序执行,涉及事件循环、回调或
await
/async
等机制,代码逻辑可能较难理解和维护。
(五)应用场景
-
同步:适用于对任务顺序有严格要求的场景,例如:数据处理、算法计算、特定顺序要求的逻辑。
-
异步:适合需要处理大量I/O操作、需要高并发支持的场景,例如:网络爬虫、聊天应用、实时数据流处理等。
(六)示例对比
同步示例
import timedef task(name):print(f"Starting task {name}")time.sleep(2) # 模拟阻塞操作print(f"Task {name} completed")# 顺序执行
task("A")
task("B")
task("C")
输出:
Starting task A
Task A completed
Starting task B
Task B completed
Starting task C
Task C completed
在同步示例中,task
函数按顺序执行,每个任务完成后才开始下一个。
异步示例
import asyncioasync def task(name):print(f"Starting task {name}")await asyncio.sleep(2) # 模拟非阻塞操作print(f"Task {name} completed")async def main():await asyncio.gather(task("A"), task("B"), task("C"))asyncio.run(main())
输出:
Starting task A
Starting task B
Starting task C
Task A completed
Task B completed
Task C completed
在异步示例中,任务A
、B
、C
几乎同时开始,await asyncio.sleep(2)
不会阻塞其他任务,任务可以并发执行,最终加快了整体运行速度。
对比总结
特性 | 同步 | 异步 |
---|---|---|
执行方式 | 顺序执行 | 并发执行 |
阻塞 | 阻塞 | 非阻塞 |
效率 | I/O 密集型性能低 | I/O 密集型性能高 |
代码复杂度 | 简单 | 较复杂 |
适用场景 | 计算密集型任务 | I/O 密集型、高并发任务 |
在实际应用中,同步和异步各有优缺点。选择同步或异步,主要取决于应用场景、任务需求和性能要求。
四、异步爬虫
异步爬虫是一种使用异步编程方法实现的网络爬虫,它能够在不等待网页响应的情况下,同时发送多个请求并处理返回的数据。这种方式特别适用于需要抓取大量网页内容的场景,因为它可以显著提升爬虫的效率。
在Python中,异步爬虫通常使用 asyncio
和 aiohttp
两个库来实现:
-
asyncio
:提供异步编程的核心框架,包括事件循环、协程和任务管理。 -
aiohttp
:一个异步HTTP库,支持异步发送请求和获取响应,非常适合构建异步爬虫。
(一)异步爬虫的优点
-
高并发性:可以同时发送大量请求,而不必等待每个请求完成再发送下一个。
-
资源利用率高:在等待服务器响应时可以处理其他任务,减少了等待时间。
-
适合I/O密集型任务:异步爬虫特别适用于抓取数据量大、网络请求多的任务场景。
(二)实现异步爬虫的基本步骤
以下是一个使用 asyncio
和 aiohttp
构建异步爬虫的示例,展示如何同时请求多个网页并处理响应。
示例:
import asyncio
import aiohttp# 定义一个异步请求函数
async def fetch(session, url):try:async with session.get(url) as response:print(f"Fetching {url}")html = await response.text() # 获取网页的 HTML 内容print(f"Completed {url}")return htmlexcept Exception as e:print(f"Error fetching {url}: {e}")# 主爬虫函数
async def main(urls):# 创建一个aiohttp会话async with aiohttp.ClientSession() as session:# 使用 asyncio.gather 并发请求多个 URLtasks = [fetch(session, url) for url in urls]results = await asyncio.gather(*tasks, return_exceptions=True)return results# 运行爬虫
urls = ["https://example.com","https://example.org","https://example.net"
]# 启动事件循环
asyncio.run(main(urls))
代码解析
-
fetch(session, url)
:这是异步请求函数,使用session.get(url)
发送异步 HTTP 请求。async with
确保会话资源能够正确释放。 -
asyncio.gather(*tasks)
:将所有fetch
请求作为任务传入asyncio.gather
,这样可以并发地执行这些任务,而不需要等待每个任务顺序完成。 -
asyncio.run(main(urls))
:启动事件循环并运行main
函数,main
中会创建多个并发任务并等待它们的完成。
(三)控制并发数量
在实际应用中,为了防止服务器拒绝请求,可以使用 asyncio.Semaphore
来限制并发请求数量。例如,限制并发请求数为5:
async def fetch(semaphore, session, url):async with semaphore: # 使用信号量限制并发try:async with session.get(url) as response:print(f"Fetching {url}")html = await response.text()print(f"Completed {url}")return htmlexcept Exception as e:print(f"Error fetching {url}: {e}")async def main(urls):semaphore = asyncio.Semaphore(5) # 限制为5个并发请求async with aiohttp.ClientSession() as session:tasks = [fetch(semaphore, session, url) for url in urls]results = await asyncio.gather(*tasks, return_exceptions=True)return results
(四)应用场景
-
数据采集:高效采集电商网站、新闻网站等的商品或内容信息。
-
实时数据爬取:抓取实时更新的内容,如股票数据、天气数据等。
-
大规模网页抓取:异步爬虫非常适合抓取大量网页内容,因为它能在不等待单个网页响应的情况下发起多个请求。
(五)注意事项
-
速率控制:可以加入请求延迟或限制并发请求数量,以防止被目标网站封禁。
-
异常处理:要处理网络超时、连接错误等异常,保证爬虫在出现错误时不会中断。
-
机器人检测:一些网站会检测并阻止大量并发请求,需要考虑反爬策略(如伪装请求头、模拟浏览器等)。
五、aiomysql的使用
aiomysql
是一个支持 Python 异步编程的 MySQL 数据库库,基于 asyncio
和 PyMySQL
构建。它可以让开发者在异步框架中执行数据库操作,适合需要同时处理大量数据库请求的高并发应用,如爬虫数据存储、Web 服务等。
(一)特点
-
异步支持:基于
asyncio
的异步支持,不会因为等待数据库响应而阻塞其他任务。 -
高效连接池:提供了内置的数据库连接池,减少每次查询前创建新连接的开销。
-
灵活的事务处理:支持事务和多种数据库操作,适合复杂的数据库事务操作。
(二)安装
在使用前,需要安装 aiomysql
。可以通过以下命令进行安装:
pip install aiomysql
(三)使用示例
以下是一个简单的 aiomysql
示例,包括如何创建连接、执行查询、插入数据和使用连接池。
(1)创建连接并执行查询
import asyncio
import aiomysqlasync def main():# 创建连接conn = await aiomysql.connect(host='localhost', port=3306,user='root', password='password',db='test_db')async with conn.cursor() as cur:# 执行查询await cur.execute("SELECT * FROM example_table")result = await cur.fetchall() # 获取所有查询结果print(result)conn.close() # 关闭连接# 运行异步主函数
asyncio.run(main())
(2)使用连接池
使用连接池可以避免频繁创建和关闭连接,适合大量并发请求的场景。
import asyncio
import aiomysqlasync def query_with_pool(pool):async with pool.acquire() as conn:async with conn.cursor() as cur:await cur.execute("SELECT * FROM example_table")result = await cur.fetchall()print(result)async def main():# 创建连接池pool = await aiomysql.create_pool(host='localhost', port=3306,user='root', password='password',db='test_db', maxsize=10)# 执行查询await query_with_pool(pool)pool.close()await pool.wait_closed() # 关闭连接池asyncio.run(main())
(3)插入数据示例
import asyncio
import aiomysqlasync def insert_data():conn = await aiomysql.connect(host='localhost', port=3306,user='root', password='password',db='test_db')async with conn.cursor() as cur:await cur.execute("INSERT INTO example_table (name, age) VALUES (%s, %s)",('Alice', 25))await conn.commit() # 提交事务conn.close()asyncio.run(insert_data())
(4)异步事务处理
在数据需要严格一致性时,可以使用事务:
async def transaction_example():conn = await aiomysql.connect(host='localhost', port=3306,user='root', password='password',db='test_db')async with conn.cursor() as cur:try:await cur.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1")await cur.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2")await conn.commit() # 提交事务except Exception as e:await conn.rollback() # 回滚事务print("Transaction failed:", e)finally:conn.close()asyncio.run(transaction_example())
(5)常见注意事项
-
错误处理:在异步环境中,尽量在执行数据库操作时捕获异常,避免由于未处理的异常导致协程退出。
-
事务一致性:在批量插入、转账等操作中,建议使用事务保证数据一致性。
-
连接池管理:使用
aiomysql
的连接池,尤其在高并发场景中,能够显著提高数据库访问的性能。
六、总结
Python异步编程通过非阻塞的事件循环实现了并发任务调度,特别适合处理I/O密集型任务,如网络请求、文件读写等。在本文中,我们探讨了异步编程的核心概念与实现方式,包括协程、事件循环、并发控制等。基于这些技术,还展示了如何利用asyncio
和aiohttp
构建高效的异步爬虫。掌握这些异步编程方法,不仅能大幅提升代码执行效率,还为处理大规模数据和并发任务提供了强有力的工具。
相关文章:

【Python爬虫实战】深入理解Python异步编程:从协程基础到高效爬虫实现
#1024程序员节|征文# 🌈个人主页:易辰君-CSDN博客 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、异步 (一)核心概念 (二)…...

OpenCV图像处理方法:腐蚀操作
腐蚀操作 前提 图像数据为二值的(黑/白) 作用 去掉图片中字上的毛刺 显示图片 读取一个图像文件,并在一个窗口中显示它。用户可以查看这个图像,直到按下任意键,然后程序会关闭显示图像的窗口 # cv2是OpenCV库的P…...
PG数据库之流复制详解
一、流复制的定义 PostgreSQL流复制(Streaming Replication)是一种数据复制技术,它允许实时传输数据更改,从而在主服务器和一个或多个备用服务器之间保持数据同步。流复制是PostgreSQL数据库管理系统(DBMS)…...

Python酷库之旅-第三方库Pandas(174)
目录 一、用法精讲 801、pandas.Categorical类 801-1、语法 801-2、参数 801-3、功能 801-4、返回值 801-5、说明 801-6、用法 801-6-1、数据准备 801-6-2、代码示例 801-6-3、结果输出 802、pandas.Categorical.from_codes方法 802-1、语法 802-2、参数 802-3、…...

【Linux网络】基于TCP的全连接队列与文件、套接字、内核之间的关系
W...Y的主页 😊 代码仓库管理💕 前言:之前我们已经学习了TCP传输协议,而无论是TCP还是UDP都是使用socket套接字进行网络传输的,而TCP的socket是比UDP复杂的,当时我们学习TCPsocket编程时使用listen函数进行…...
IDE(集成开发环境)
IDE(集成开发环境)是软件开发过程中不可或缺的工具,它集成了代码编写功能、分析功能、编译器、调试器等开发工具,旨在提高开发效率。不同的IDE支持不同的语言和框架,下面是一些通用的IDE使用技巧和插件推荐,…...

一键导入Excel到阿里云PolarDB-MySQL版
今天,我将分享如何一键导入Excel到阿里云PolarDB-MySQL版数据库。 准备数据 这里,我们准备了一张excel表格如下: 连接到阿里云PolarDB 打开的卢导表,点击新建连接-选择阿里云PolarDB-MySQL版。如果你还没有这个工具,…...
Oracle有哪些版本
目录 Oracle 1(1979年) Oracle 2(1983年) Oracle 7(1992年) Oracle 8i(1999年) Oracle 9i(2001年) Oracle 10g(2004年) Oracle 11g(2007年) Oracle 12c(2013年) Oracle 18c(2018年) Oracle 19c(2019年) Oracle 21c(2023年) Oracle 23ai(202…...
先来先服务(FCFS,First-Come, First-Served)调度算法
有利于CPU繁忙作业的原因 充分利用CPU资源: 当一个CPU繁忙型的作业到达后,它会立即被执行,并且在没有其他作业等待的情况下,可以一直占用CPU直到完成。这使得CPU能够持续地执行作业,最大化利用CPU资源。 减少上下文切换…...
Windows操作系统忘记密码怎么办 这个方法屡试不爽 还不来试一下
Windows操作系统重置密码的操作步骤如下: 本方法适用于Windows Server 2008R2及其之后的操作系统。 第一步:从Windows 2008R2之后的操作系统光盘启动到安装界面,一直下一步到磁盘分区界面,按shiftF10调出cmd命令行界面。 第二步&…...

基于java的山区环境监督管理系统(源码+定制+开发)环境数据可视化、环境数据监测、 环境保护管理 、污染防治监测系统 大数据分析
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...
jQuery Mobile 表单输入
jQuery Mobile 表单输入 引言 在移动设备上,表单输入是用户与移动应用交互的重要方式。jQuery Mobile 是一个基于 jQuery 的移动设备友好的开发框架,它提供了丰富的组件和工具来帮助开发者创建响应式和交互式的移动界面。本文将详细介绍如何使用 jQuery Mobile 来创建和定制…...

IoC详解
共有两类注解类型可以实现: 1. 类注解:Controller、Service、Repository、Component、Configuration. 2. 方法注解:Bean. 类注解 Controller(控制器存储) 使⽤Controller存储bean的代码如下所⽰: Con…...

基于 ThinkPHP+Mysql 灵活用工_灵活用工系统_灵活用工平台
基于 ThinkPHPMysql 灵活用工灵活用工平台灵活用工系统灵活用工小程序灵活用工源码灵活用工系统源码 开发语言 ThinkPHPMysql 源码合作 提供完整源代码 软件界面展示 一、企业管理后台 二、运用管理平台 三、手机端...
etcd之etcd分布式锁及事务(四)
1、etcd分布式锁及事务 1.1 前言 分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如 果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要…...

智慧旅游微信小程序平台
作者介绍:✌️大厂全栈码农|毕设实战开发,专注于大学生项目实战开发、讲解和毕业答疑辅导。 🍅获取源码联系方式请查看文末🍅 推荐订阅精彩专栏 👇🏻 避免错过下次更新 Springboot项目精选实战案例 更多项目…...

C++设计模式创建型模式———简单工厂模式、工厂方法模式、抽象工厂模式
文章目录 一、引言二、简单工厂模式三、工厂方法模式三、抽象工厂模式四、总结 一、引言 创建一个类对象的传统方式是使用关键字new , 因为用 new 创建的类对象是一个堆对象,可以实现多态。工厂模式通过把创建对象的代码包装起来,实现创建对…...

C++ 类与对象(中) 默认成员函数
我们知道在类中,有成员变量和成员函数,我们可以通过创造不同的成员函数来实现这个类不同的功能,如果我们创造一个类,却不实现它的成员函数会如何呢?这个就涉及到类中的默认成员函数的概念了。但在本文我们主要介绍以下…...
中间人攻击(https降级攻击)和iptables命令分析
中间人攻击 以下是一个简单的中间人攻击示例,结合 ARP 欺骗和流量修改: 1. 进行 ARP 欺骗 首先,使用 arpspoof 进行 ARP 欺骗,将受害者的流量重定向到攻击者的机器上: sudo arpspoof -i eth0 -t 172.29.144.50 172…...
开源生活-分布式管理
开源竞争(当自己没有办法彻底掌握一门技术的时候就彻底开源掉;培养出更多的依赖,让更多人帮助你完善你的技术,那么这不就是在砸罐子吗?一个行业里面总会有人先砸罐子的,你不如先砸罐子,还能听个…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...