Python爬虫(二)- Requests 高级使用教程
文章目录
- 前言
- 一、Session 对象
- 1. 简介
- 2. 跨请求保持 Cookie
- 3. 设置缺省数据
- 4. 方法级别参数不被跨请求保持
- 5. 会话作为上下文管理器
- 6. 移除字典参数中的值
- 二、请求与响应
- 1. 请求与响应对象
- 1.1 获取响应头信息
- 1.2 获取发送到服务器的请求头信息
- 三、SSL 证书验证
- 1. 忽略 SSL 证书验证
- 四、流式上传和请求
- 1. 流式上传
- 2. 流式请求
- 2.1 流式请求和普通请求的区别
- 2.2 示例
- 2.2.1 iter_lines() 使用
- 2.2.2 iter_content() 使用
- 五、代理
- 1. 获取免费代理地址
- 2. 使用代理配置单个请求
- 3. 使用代理池
- 4. 使用 HTTP Basic Auth 的代理
- 5. 针对特定主机或连接方式设置代理
- 六、编码方式
- 1. 编码方式处理
- 1.1 自动检测编码
- 1.2 手动设置编码
- 1.3 使用原始字节数据
- 七、身份认证
- 1. 基本身份认证 (HTTP Basic Auth)
前言
在现代网络应用中,HTTP 请求和响应的处理是至关重要的。Python 的 requests 库以其简洁易用的接口,成为了开发者进行网络请求的首选工具。无论是简单的 GET 请求,还是复杂的身份认证、会话管理、代理设置,requests 都能轻松应对。本文将深入探讨 requests 库的各个方面,包括 Session 对象的使用、请求与响应的处理、SSL 证书验证、流式上传和请求、代理配置、编码方式处理以及身份认证等。
一、Session 对象
1. 简介
Session 对象允许跨多个请求保持某些参数不变。它在同一个 Session 实例发出的所有请求之间保持 cookie,并利用 urllib3 的连接池功能来重用底层的 TCP 连接,从而为向同一主机发送的多个请求提供显著的性能提升。
主要特性:
- 所有 Requests API 方法:Session 对象拥有主要的 Requests API 的所有方法。
- 持久性 Cookie 和 Headers:可以跨请求保持某些数据,如认证信息和自定义头部。
- 连接池复用:对于同一主机的多次请求,能够复用TCP连接,提高效率。
2. 跨请求保持 Cookie
import requests# 创建一个会话对象
session = requests.session()# 设置 Cookie:通过会话发送 GET 请求,设置一个名为 sessioncookie 的 cookie,值为 123456789。
session.get('http://httpbin.org/cookies/set/sessioncookie/123456789')# 获取 Cookie:再次使用同一个会话发送 GET 请求,获取当前会话中的所有 cookies。
response = session.get("http://httpbin.org/cookies")# 打印服务器返回的 cookie 信息
print(response.text)
打印的结果为:
{"cookies": {"sessioncookie": "123456789"}
}
3. 设置缺省数据
通过为 Session 对象的属性提供数据,可以为请求方法提供缺省数据,例如认证信息或头部信息。
import requests# 创建一个会话对象
session = requests.session()# 设置会话的认证信息,用户名为 'user',密码为 'pass'
session.auth = ('user', 'pass')# 更新会话头部信息,添加自定义头 'x-test',其值为 'true'
session.headers.update({'x-test': 'true'})# 发送 GET 请求到 http://httpbin.org/headers,同时在此请求中添加另一个自定义头 'x-test2'
response = session.get('http://httpbin.org/headers', headers={'x-test2': 'true'})# 打印服务器返回的响应内容,以查看请求头和其他信息
print(response.text)
打印的结果为:
任何传递给请求方法的字典都会与已设置会话层数据合并,方法层的参数覆盖会话的参数。
4. 方法级别参数不被跨请求保持
就算使用了 Session,方法级别的参数也不会被跨请求保持。
import requests# 创建一个会话对象
session = requests.session()# 只有第一个请求发送 cookie
response = session.get('http://httpbin.org/cookies', cookies={'from-my': 'browser'})
print(response.text)# 第二个请求没有 cookie
response = session.get('http://httpbin.org/cookies')
print(response.text)
打印的结果为:
{"cookies": {"from-my": "browser"}
}{"cookies": {}
}
从打印的结果可以看出,重复对同一个地址发起访问,第一个请求设置的 cookie 并没有被保存,所以第二个请求中没有 cookie,也就是说就算使用了 Session,方法级别的参数也不会被跨请求保持。
5. 会话作为上下文管理器
为了确保会话在完成后能被正确关闭,可以使用它作为上下文管理器。这样就能确保 with 区块退出后会话能被关闭,即使发生了异常也一样。
import requestswith requests.session() as session:response = session.get('http://httpbin.org/cookies/set/sessioncookie/123456789')print(response.text)
打印的结果为:
{"cookies": {"sessioncookie": "123456789"}
}
6. 移除字典参数中的值
可以通过在方法级别的参数中将键的值设置为 None
来移除会话层字典参数中的某个键,从而让该键不会被发送。
二、请求与响应
1. 请求与响应对象
任何时候当你调用 requests.get()
或其他类似方法时,实际上你在执行两个主要操作:构建一个 Request
对象以向服务器请求或查询资源;以及接收一个从服务器返回的 Response
对象。这个 Response
对象包含了来自服务器的所有信息,并且也包含了你最初创建的 Request
对象。
1.1 获取响应头信息
import requestsurl = 'http://www.baidu.com'response = requests.get(url)print(response.headers)
打印的结果为:
1.2 获取发送到服务器的请求头信息
import requestsurl = 'http://www.baidu.com'response = requests.get(url)print(response.request.headers)
打印的结果为:
{'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
三、SSL 证书验证
Requests 可以为 HTTPS 请求验证 SSL 证书,就像 web 浏览器一样。SSL 验证默认是开启的,如果证书验证失败,Requests 会抛出 SSLError
。
1. 忽略 SSL 证书验证
在某些特殊情况下,比如在测试环境中或者你信任但证书不受信任的情况下,你可能想要忽略 SSL 证书验证。
import requests
from urllib3.exceptions import InsecureRequestWarningurl = 'https://example.com'# 禁用不安全请求警告
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)# 忽略 SSL 证书验证
response = requests.get(url, verify=False)
print(response.status_code)
四、流式上传和请求
1. 流式上传
Requests支持流式上传,这允许你发送大的数据流或文件而无需先把它们读入内存。要使用流式上传,仅需为你的请求体提供一个类文件对象即可。
with open('massive-body', 'rb') as f:requests.post('http://some.url/streamed', data=f)
data=f
:这里将文件对象 f
直接赋值给了 data
参数。这意味着 requests
将会逐块读取文件内容,并通过 HTTP 请求进行流式传输。这样做的好处是,即使文件非常大,也不会占用过多的内存,因为数据是一部分一部分地发送出去的。
2. 流式请求
2.1 流式请求和普通请求的区别
流式请求(Streaming Requests)和普通请求(Non-streaming Requests)是使用 requests
库进行 HTTP 请求的两种不同方式,它们在处理响应内容时有着显著的区别。下面我们将详细介绍这两种请求类型,并说明其适用场景。
普通请求
-
一次性读取:当发起一个普通的 GET 或 POST 请求时,
requests
会立即将整个响应体下载到内存中。这意味着如果响应体很大,可能会占用大量的内存。 -
简单易用:对于小文件或轻量级的数据交换,这种方式非常方便,因为它不需要额外的配置就可以直接获取完整的响应内容。
流式请求
-
逐块读取:通过设置参数
stream=True
,你可以告诉requests
不要立即下载整个响应体。相反,它会在需要时逐步从网络流中读取数据。这允许你处理超大文件或长时间运行的数据流,而不会一次性占用大量内存。 -
节省资源:流式请求非常适合于处理大型文件、长连接 API 响应或者实时数据流,因为你可以一边接收数据一边处理,从而有效管理资源。
-
更复杂的逻辑:由于数据是分块到达的,你需要编写额外的代码来处理这些数据块,例如将它们写入文件或进行增量处理。
流式请求迭代器方法
-
iter_content()
:以字节为单位返回响应内容的迭代器。可以指定chunk_size
参数来控制每次读取的大小。 -
iter_lines()
:以行为单位返回响应内容的迭代器,适用于按行处理的文本响应。
2.2 示例
2.2.1 iter_lines() 使用
import json
import requests# 发送 GET 请求到指定的 URL,使用 stream=True 以便逐行读取响应内容
response = requests.get('http://httpbin.org/stream/20', stream=True)# 检查响应的编码,如果未设置,则将其设置为 'utf-8'
if response.encoding is None:response.encoding = 'utf-8'# 逐行迭代响应内容,使用 decode_unicode=True 将内容解码为字符串
for line in response.iter_lines(decode_unicode=True):# 检查当前行是否非空if line:# 将 JSON 格式的字符串解析为 Python 对象并打印print(json.loads(line))
iter_lines
不保证重进入时的安全性。多次调用该方法 会导致部分收到的数据丢失。如果要在多处调用它,应该使用生成的迭代器对象。
import json
import requests# 发送 GET 请求到指定的 URL,使用 stream=True 以便逐行读取响应内容
response = requests.get('http://httpbin.org/stream/20', stream=True)# 检查响应的编码,如果未设置,则将其设置为 'utf-8'
if response.encoding is None:response.encoding = 'utf-8'# 使用 iter_lines() 方法创建一个可迭代的行生成器
lines = response.iter_lines()# 使用 next() 函数获取并跳过第一行,first_line 存储的是第一行的内容
first_line = next(lines)# 逐行处理剩余的响应内容
for line in lines:# 打印当前行的内容print(json.loads(line))
2.2.2 iter_content() 使用
import requests# 定义要请求的 URL
url = 'https://api.github.com/events'# 发送 GET 请求到指定的 URL,使用 stream=True 以便逐块下载内容
response = requests.get(url=url, stream=True)# 打开一个文件以写入二进制数据,路径为 'D:\\demo.txt'
with open('D:\\demo.txt', 'wb') as fd:# 遍历响应内容,按块读取数据,块大小为 8192 字节for chunk in response.iter_content(chunk_size=8192):# 将读取的块写入文件fd.write(chunk)
五、代理
1. 获取免费代理地址
点击连接访问快代理网站:https://www.kuaidaili.com/free/inha/
如下图所示,可以获取免费的代理。
2. 使用代理配置单个请求
如果需要使用代理,可以通过为任意请求方法提供 proxies
参数来配置单个请求。
import requestsurl = 'http://www.baidu.com'proxies = {"http": "47.119.22.92:8008"
}# 发送 GET 请求,并使用指定的代理
response = requests.get(url=url, proxies=proxies)print(response.status_code)
打印的结果为:
200
3. 使用代理池
在进行网络请求时,特别是当你需要频繁地访问某个网站或希望隐藏自己的真实 IP 地址时,使用代理池可以提高请求的成功率和匿名性。通过每次发送请求时从多个代理服务器中随机选择一个来发送,可以分散请求源,减少被目标网站封禁的风险。
import randomimport requestsurl = 'http://www.baidu.com'# 使用代理池
proxies_pool = [{'http': '47.122.65.254:8080'},{'http': '8.130.34.44:8800'},{'http': '47.121.183.107:8443'},{'http': '111.1.61.50:3128'},{'http': '47.119.164.33:3128'}
]proxies = random.choice(proxies_pool)# 发送 GET 请求,并使用指定的代理
response = requests.get(url=url, proxies=proxies)print(response.status_code)
打印的结果为:
200
4. 使用 HTTP Basic Auth 的代理
如果代理需要使用 HTTP Basic Auth,可以使用 username:password@host
的语法来配置代理。
# 定义代理字典,包含用户名和密码
proxies = {"http": "username:password@10.10.1.10:3128",
}
5. 针对特定主机或连接方式设置代理
要为某个特定的连接方式或主机设置代理,可以使用 scheme://hostname
作为键。这种方式将针对指定的主机和连接方式进行匹配。
import requestsurl = 'http://www.baidu.com'# 针对特定主机设置代理
proxies = {"http://127.0.0.1": "http://47.121.183.107:8443"
}# 发送 GET 请求,并使用指定的代理
response = requests.get(url=url, proxies=proxies)print(response.status_code)
打印的结果为:
200
六、编码方式
1. 编码方式处理
当你收到一个 HTTP 响应时,requests
库会猜测响应内容的编码方式,以便在你调用 Response.text
方法时能够正确解码响应内容。以下是 requests
处理编码方式的具体机制。
1.1 自动检测编码
-
优先检查 HTTP 头部:
requests
首先会在 HTTP 响应头部查找Content-Type
字段中的字符集声明。如果存在明确指定的字符集(例如charset=UTF-8
),则使用该字符集进行解码。 -
使用 charade 猜测编码:如果 HTTP 头部没有明确指定字符集,并且
Content-Type
包含text
类型,则requests
会使用内置的chardet
库(原名为charade
)来推测最可能的编码方式。 -
默认编码:根据 RFC 2616 的规定,当
Content-Type
是text
类型但没有指定字符集时,默认字符集应该是ISO-8859-1
。requests
遵循这一规范并默认采用ISO-8859-1
进行解码。
1.2 手动设置编码
如果你知道正确的编码方式并且希望覆盖 requests
的自动检测结果,可以通过直接设置 Response.encoding
属性来实现。
import requestsurl = 'https://api.github.com/events'response = requests.get(url=url)# 查看推测的文本编码
print("自动推测的编码方式:" + response.encoding)# 手动指定编码为 ISO-8859-1
response.encoding = 'ISO-8859-1'
# 打印编码方式
print("手动指定的编码方式:" + response.encoding)
打印的结果为:
自动推测的编码方式:utf-8
手动指定的编码方式:ISO-8859-1
1.3 使用原始字节数据
如果你不确定编码或者不想依赖于 requests
的自动解码功能,可以直接访问 Response.content
属性以获取未经解码的原始字节数据。然后根据需要自行解码。
import requestsurl = 'https://api.github.com/events'response = requests.get(url=url)# 获取未经解码的原始字节数据,返回的是服务器返回的二进制内容
raw_data = response.content# 使用 UTF-8 编码方式对原始字节数据进行解码,转换为字符串
decoded_text = raw_data.decode('utf-8')
print(decoded_text)
七、身份认证
1. 基本身份认证 (HTTP Basic Auth)
HTTP Basic Authentication 是一种简单的认证机制,广泛用于需要认证的 Web 服务中。requests
库对这种认证方式提供了直接的支持。
可以通过导入 HTTPBasicAuth
类来使用 HTTP Basic Auth。
import requests
from requests.auth import HTTPBasicAuthurl = 'https://api.github.com/user'
auth = HTTPBasicAuth('user', 'pass')
# 发送带有基本身份认证的 GET 请求
response = requests.get(url=url, auth=auth)print(response.status_code)
简写形式:由于 HTTP Basic Auth 非常常见,requests
提供了一种更为简洁的方式来传递认证信息——直接在 auth
参数中提供一个元组。
import requestsurl = 'https://api.github.com/user'
# 发送带有基本身份认证的 GET 请求
response = requests.get(url=url, auth=('user', 'pass'))print(response.status_code)
参考链接:
- requests 官方文档:http://cn.python-requests.org/zh_CN/latest/
相关文章:

Python爬虫(二)- Requests 高级使用教程
文章目录 前言一、Session 对象1. 简介2. 跨请求保持 Cookie3. 设置缺省数据4. 方法级别参数不被跨请求保持5. 会话作为上下文管理器6. 移除字典参数中的值 二、请求与响应1. 请求与响应对象1.1 获取响应头信息1.2 获取发送到服务器的请求头信息 三、SSL 证书验证1. 忽略 SSL 证…...

并联带阻滤波器带通滤波器对幅值和相位的影响(IIR)
一、背景 输入信号input分别经过bp(带通滤波器)和bs(带阻滤波器)处理后相加输出。分析输出信号的幅值和相位受到的影响。 根据上图公式推导可知,并联滤波器对输出的影响可以直接分析,带通滤波器与带阻滤波器在频域上的加和。 二、…...

攻防世界web新手第五题supersqli
这是题目,题目看起来像是sql注入的题,先试一下最常规的,输入1,回显正常 输入1‘,显示错误 尝试加上注释符号#或者–或者%23(注释掉后面语句,使1后面的单引号与前面的单引号成功匹配就不会报错…...

vue3学习笔记(10)-$subscribe,store组合式写法
1.$subscribe订阅,监视vuex中数据得修改 2.localStorage里面穿的都是字符串,关掉浏览器数据还在 只能获取字符串,用ts语法写明,作为字符串使用 3.组合式写法...

操作系统论文导读(八):Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个
Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个关键性规范的零星任务的可调度性分析 目录 一、论文核心思想 二、基本定义 2.1 关键性指标 2.2 任务及相关参数定义 2.3 几个基础定义 三、可调度性分析 3.1 调度算法分…...
计算机网络与通信复习
因特网的核心部分(电路交换与分组交换的不同点,分组交换的优点) 核心部分:路由器、交换机 我们假如数据就是一个货物,比如说一千公斤的大米,电路交换要有专用通道,不管从起点到终点经过多少个…...

【Scala】图书项目系统代码演练3.1/BookService
package org.app package serviceimport models.{BookModel, BorrowRecordModel}import org.app.dao.{BookDAO, BorrowRecordDAO}import java.time.LocalDateTime import scala.collection.mutable.ListBuffer// 图书业务逻辑层 class BookService {private val bookDAO new B…...

人工智能基础软件-Jupyter Notebook
简介: Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果。 Jupyter Notebook是以网页的形式打开,可以在网页页面中直接编写代码和运行代码,代码的运行结果也会直…...
C++ 设计模式:模板方法(Template Method)
链接:C 设计模式 链接:C 设计模式 - 策略模式 链接:C 设计模式 - 观察者模式 模板方法(Template Method)是一种行为设计模式,它定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。通过这…...
GDPU Vue前端框架开发 跨年大礼包
目录 选择题 填空题 简答题 记住,年底陪你跨年的不会仅是方便面跟你的闺蜜,还有孑的笔记。 选择题 1.下列选项用于设置Vue.js页面视图的元素是()。 A. Template B. script C. style D. title 2.下列选项中能够定义Vuejs根…...
搭建一个高效且安全的APP分发平台
搭建一个高效且安全的APP分发平台需要经历一系列精心规划和实施的步骤。以下是一个详细的指南,涵盖从准备阶段到后续维护阶段的各个环节: 一、准备阶段 明确目标与需求 确定平台的目标用户群体,了解他们的需求和偏好。分析竞争对手的分发平台…...

Leetcode打卡:二叉树中的链表
执行结果:通过 题目 1367 二叉树中的链表 给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表。 如果在二叉树中,存在一条一直向下的路径,且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值,那么请你返回 …...

大数据技术-Hadoop(四)Yarn的介绍与使用
目录 一、Yarn 基本结构 1、Yarn基本结构 2、Yarn的工作机制 二、Yarn常用的命令 三、调度器 1、Capacity Scheduler(容量调度器) 1.1、特点 1.2、配置 1.2.1、yarn-site.xml 1.2.2、capacity-scheduler.xml 1.3、重启yarn、刷新队列 测试 向hi…...

算法 class 004(选择,冒泡,插入)
选择排序: 刚进入 j 循环的样子 j 跳出循环后,b 指向最小值的坐标 然后交换 i 和 b 位置的 值 随后 i , b i , i j1; 开始新一轮的排序, void SelectAQort(int* arr,int size)//选择排序 {for (int i 0; i < size-1; i){ //i 的位置就是…...
linux---awk命令详细教程
awk是一种强大的编程语言,用于在Linux/Unix系统下对文本和数据进行处理。以下是对awk的详细教程: 一、awk简介 awk由Alfred Aho、Brian Kernighan和Peter Weinberger三人开发,其名称分别代表这三位作者姓氏的第一个字母。awk支持用户自定义…...

一个通用的居于 OAuth2的API集成方案
在现代 web 应用程序中,OAuth 协议是授权和认证的主流选择。为了与多个授权提供商进行无缝对接,我们需要一个易于扩展和维护的 OAuth 解决方案。本文将介绍如何构建一个灵活的、支持多提供商的 OAuth 系统,包括动态 API 调用、路径参数替换、…...

STM32配合可编程加密芯片SMEC88ST的防抄板加密方案设计
SMEC88ST SDK开发包下载 目前市场上很多嵌入式产品方案都是可以破解复制的,主要是因为方案主芯片不具备防破解的功能,这就导致开发者投入大量精力、财力开发的新产品一上市就被别人复制,到市场上的只能以价格竞争,最后工厂复制的产…...

QML学习(五) 做出第一个简单的应用程序
通过前面四篇对QML已经有了基本的了解,今天先尝试做出第一个单页面的桌面应用程序。 1.首先打开Qt,创建项目,选择“QtQuick Application - Empty” 空工程。 2.设置项目名称和项目代码存储路径 3.这里要注意选择你的编译器类型,以及输出的程…...
深入解析Android Framework中的android.location包:架构设计、设计模式与系统定制
深入解析Android Framework中的android.location包:架构设计、设计模式与系统定制 目录 引言android.location包概述核心类解析 LocationManagerLocationProviderLocationCriteriaGpsStatusGpsStatus.ListenerLocationListener位置服务的工作原理位置信息的获取与处理GPS状态…...

【C++11】类型分类、引用折叠、完美转发
目录 一、类型分类 二、引用折叠 三、完美转发 一、类型分类 C11以后,进一步对类型进行了划分,右值被划分纯右值(pure value,简称prvalue)和将亡值 (expiring value,简称xvalue)。 纯右值是指那些字面值常量或求值结果相当于…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...