【NodeMCU实时天气时钟温湿度项目 7】和风天气API返回JSON数据信息的解压缩实现——ArduinoUZlib功能库
今天是第七专题,主要内容是:导入ArduinoUZlib功能库,借助该库把从【和风天气】官网返回的经过Gzip压缩的JSON数据,进行解压缩和t解析,在串口监视器上输出解析后的JSON信息。
如您需要了解其它专题的内容,请点击下面的链接。
第一专题内容,请参考:连接点亮SPI-TFT屏幕和UI布局设计
第二专题内容,请参考:WIFI模式设置及连接
第三专题内容,请参考:连接SHT30传感器,获取并显示当前环境温湿度数据(I2C)
第四专题内容,请参考:通过NTPClient库获取实时网络时间并显示在TFT屏幕上
第五专题内容,请参考:获取关于城市天气实况和天气预报的JSON信息(心知天气版)
第六专题内容,请参考:解析天气信息JSON数据并显示在 TFT 屏幕上(心知天气版)
一、【心知天气】官网JSON数据特点
1、订阅模式。和风天气开发服务采用订阅模式,当你创建项目时,至少需要选择一种订阅。使用和风天气的服务订阅非常简单和自由,免费或者你只需要为你实际使用的部分付费。现有三种订阅模式:免费订阅、标准订阅、高级订阅。
每种订阅模式均可获取完整的天气信息数据。区别主要体现在数据请求量和更新频率方面。

2、经过压缩的JSON数据。通过官网API接口返回的JSON数据,是进行Gzip压缩后的JSON数据,客户端需要先进行解压缩,然后再借助ArduinoJson功能库解析出解压缩后JSON数据,比心知天气返回JSON数据增加了一个解压缩过程。
3、获取和风天气数据的方法。如果需要获得通过官网API接口返回的天气信息数据,需要首先心知天气注册账号、创建项目、选择订阅模式,然后获取API访问密钥KEY。具体操作方法网上有很多文档可供参考,请自行查询,比如:如何获取和风天气Web API的KEY?
二、添加ArduinoUZlib功能库
1. ArduinoUZlib 的功能。该库是从uzlib移植到Arduino框架的功能库,主要用来解压https请求服务器返回的gzip数据。这个库占用内存比较小。
2. 添加库方法。该库暂时无法从 PlatformIO 界面 -------> Libraries 加入。
具体方法是:(1)进入该库 Github 网站,下载 zip 压缩文件。
(3)将此文件夹复制到 项目目录下的 lib 文件夹内,就可以使用该库的全部功能了。
三、主要功能函数
该库使用方法简单方便,主要是通过调用 ArduinoUZlib::decompress(inbuff, size, outbuf,outsize) 这个功能函数来实现。
size_t size = stream->available(); // 还剩下多少数据没有读完?
uint8_t inbuff[size]; // 准备一个数组来装流数据,有多少装多少
stream->readBytes(inbuff, size); // 将http流数据写入inbuff中
uint8_t *outbuf=NULL; //解压后的输出流
uint32_t outsize=0; // 解压后多大?在调用解压方法后会被赋值。
// 调用解压函数
int result=ArduinoUZlib::decompress(inbuff, size, outbuf,outsize);
// 输出解密后的数据到控制台。
Serial.write(outbuf,outsize);
详细内容可参考该库 example 目录下的示例:StreamHttpsClientGzipDemo,用来解压缩返回的 gzip数据。
/**StreamHTTPClient.inoCreated on: 24.05.2015*/
#include <ArduinoJson.h>
#include <Arduino.h>
#include "ArduinoUZlib.h"
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>#include <ESP8266HTTPClient.h>
ESP8266WiFiMulti WiFiMulti;// ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getHeapSize(), ESP.getMaxAllocHeap()
void heap(){Serial.print("FREE_HEAP[");Serial.print(ESP.getFreeHeap());Serial.print("]\n");
}
void setup() {Serial.begin(115200);// Serial.setDebugOutput(true);Serial.println();Serial.println();Serial.println();for (uint8_t t = 4; t > 0; t--) {Serial.printf("[SETUP] WAIT %d...\n", t);Serial.flush();delay(1000);}WiFi.mode(WIFI_STA);WiFiMulti.addAP("ssid", "password");
}
void log(const char *str) {Serial.println(str);
}static uint8_t buffer[1280]={0};
size_t readBytesSize=0;void fetchBuffer() {if ((WiFiMulti.run() == WL_CONNECTED)) {std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);client->setInsecure();Serial.print("[HTTPS] begin...\n");HTTPClient https;if (https.begin(*client, "https://192.168.2.144:8082/test")) {https.addHeader("Accept-Encoding", "gzip");Serial.print("[HTTPS] GET...\n");// start connection and send HTTP headerint httpCode = https.GET();if (httpCode > 0) {// HTTP header has been send and Server response header has been handledSerial.printf("[HTTPS] GET... code: %d\n", httpCode);// file found at serverif (httpCode == HTTP_CODE_OK) {// get length of document (is -1 when Server sends no Content-Length header)int len = https.getSize();// create buffer for readstatic uint8_t buff[128] = { 0 };// read all data from serverint offset=0;Serial.println("allocate");// 为什么这里分配内存会报错?// if(inbuf==NULL) inbuf=(uint8_t*)malloc(sizeof(uint8_t)*128);while (https.connected() && (len > 0 || len == -1)) {// get available data sizesize_t size = client->available();if (size) {// read up to 128 byteint c = client->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));// int c = client->readBytes(buff, size);// Serial.println("memcpy");memcpy(buffer+offset, buff, sizeof(uint8_t)*c);offset+=c;if(c>0 && c!=16) {log("======rb====");Serial.printf("%d,", buff[c-3]);Serial.printf("%d,", buff[c-2]);Serial.printf("%d,", buff[c-1]);log("\n======rb end====");}// write it to Serial// Serial.write(buff, c);if (len > 0) {len -= c;}}delay(1);}readBytesSize=offset;Serial.printf("offset=%d\n", offset);Serial.write(buffer, offset);Serial.print("[HTTPS] connection closed or file end.\n");}} else {Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());}https.end();} else {Serial.printf("Unable to connect\n");}}
}void loop() {uint8_t *outbuf1=NULL;// wait for WiFi connectionfetchBuffer();Serial.printf("\nAfter fetch, buffer size=%d\n", readBytesSize);delay(1000);if(readBytesSize) {// write it to Seriallog("===buf===");Serial.printf("%d,", readBytesSize-3);Serial.printf("%d,", readBytesSize-2);Serial.printf("%d,", readBytesSize-1);log("\n===buf end==="); Serial.write(buffer,readBytesSize);uint32_t out_size=0;int result=ArduinoUZlib::decompress(buffer, readBytesSize, outbuf1, out_size);printf("outsize=%d, result=\n", out_size,result);parseJSON((char*)outbuf1, out_size);// Serial.write(outbuf,out_size);}else {Serial.println("no avali size!");}
if (outbuf1!=NULL){free(outbuf1);outbuf1=NULL;
}Serial.println("Wait 10s before the next round...");delay(5000);
}void parseJSON(char *input, int inputLength) {// char* input;// size_t inputLength; (optional)DynamicJsonDocument doc(6144);DeserializationError error = deserializeJson(doc, input, inputLength);if (error) {Serial.print(F("deserializeJson() failed: "));Serial.println(error.f_str());return;}const char* code = doc["code"]; // "200"const char* updateTime = doc["updateTime"]; // "2022-12-05T15:35+08:00"const char* fxLink = doc["fxLink"]; // "http://hfx.link/1u0r1"for (JsonObject hourly_item : doc["hourly"].as<JsonArray>()) {// const char* hourly_item_fxTime = hourly_item["fxTime"]; // "2022-12-05T17:00+08:00", ...const char* hourly_item_fxTime = hourly_item["fxTime"]; // "2022-12-05T17:00+08:00", ...const char* hourly_item_temp = hourly_item["temp"]; // "15", "13", "13", "12", "11", "11", "10", "10", ...Serial.printf("%s,", hourly_item_temp);const char* hourly_item_icon = hourly_item["icon"]; // "100", "150", "150", "150", "150", "150", "150", ...const char* hourly_item_text = hourly_item["text"]; // "晴", "晴", "晴", "晴", "晴", "晴", "晴", "多云", "多云", ...const char* hourly_item_wind360 = hourly_item["wind360"]; // "22", "24", "30", "33", "33", "31", "30", ...const char* hourly_item_windDir = hourly_item["windDir"]; // "东北风", "东北风", "东北风", "东北风", "东北风", "东北风", ...const char* hourly_item_windScale = hourly_item["windScale"]; // "3-4", "3-4", "3-4", "3-4", "3-4", ...const char* hourly_item_windSpeed = hourly_item["windSpeed"]; // "16", "16", "16", "16", "14", "14", ...const char* hourly_item_humidity = hourly_item["humidity"]; // "57", "63", "63", "65", "66", "67", "68", ...const char* hourly_item_pop = hourly_item["pop"]; // "1", "3", "6", "6", "6", "6", "6", "6", "7", "7", ...const char* hourly_item_precip = hourly_item["precip"]; // "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", ...const char* hourly_item_pressure = hourly_item["pressure"]; // "1013", "1013", "1012", "1012", "1012", ...const char* hourly_item_cloud = hourly_item["cloud"]; // "5", "5", "4", "4", "7", "9", "11", "33", "54", ...const char* hourly_item_dew = hourly_item["dew"]; // "7", "6", "6", "6", "5", "5", "5", "5", "5", "4", ...}Serial.println();JsonArray refer_sources = doc["refer"]["sources"];const char* refer_sources_0 = refer_sources[0]; // "QWeather"const char* refer_sources_1 = refer_sources[1]; // "NMC"const char* refer_sources_2 = refer_sources[2]; // "ECMWF"const char* refer_license_0 = doc["refer"]["license"][0]; // "CC BY-SA 4.0"}
四、和风天气JSON数据的解压缩实现
这是个实现解压缩和风天气JSON数据的简单示例:(1)将服务器进行Gzip压缩后返回的JSON数据,接收并保存到缓冲区 buffer 中;(2)调用 ArduinoUZlib::decompress(inbuffer, size, outbuffer,outsize) 解压 buffer 中的经过压缩的JSON数据,同时将解压后JSON数据保存到输出 outbuffer 中;(3)调用 ArduinoJson 库的 deserializeJson(doc, outbuffer) 函数,对明文JSON数据进行解析,并保存到实况天气数据结构 wd 中,然后通过串口监视器输出。
具体内容,请仔细阅读下面的代码实现。
// 实时天气
struct weather_data
{int code = -1; // API状态码,具体含义请参考状态码String updateTime = ""; // 当前API的最近更新时间String now_obsTime = ""; // 数据观测时间String now_temp = "0"; // 温度,默认单位:摄氏度int now_feelsLike = 0; // 体感温度,默认单位:摄氏度String now_icon = ""; // 天气状况和图标的代码,图标可通过天气状况和图标下载String now_text = ""; // 天气状况的文字描述,包括阴晴雨雪等天气状态的描述String now_wind360 = "-1"; // 风向360角度String now_windDir = ""; // 风向String now_windScale = "-1"; // 风力等级int now_windSpeed = -1; // 风速,公里/小时int now_humidity = -1; // 相对湿度,百分比数值int now_precip = -1; // 当前小时累计降水量,默认单位:毫米int now_pressure = -1; // 大气压强,默认单位:百帕int now_vis = -1; // 能见度,默认单位:公里
} wd;void get_now_weather_data(JsonDocument &doc);size_t readBytesSize = 0;// 用来存放解压前的JSON数据
static uint8_t buffer[1280] = {0};// 用来存放解压后的JSON数据
uint8_t *outbuffer = NULL;// 获取实时天气数据
void get_now_Weather()
{// 检查WIFI是否连接if ((WiFi.status() == WL_CONNECTED)){// 准备发起请求std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);client->setInsecure();Serial.print("[HTTPS] begin...\n");HTTPClient https;if (https.begin(*client, "https://devapi.qweather.com/v7/weather/now?key=" + key + "&location=" + cityid)){https.addHeader("Accept-Encoding", "gzip");Serial.print("[HTTPS] GET...\n");// start connection and send HTTP headerint httpCode = https.GET();if (httpCode > 0){// HTTP header has been send and Server response header has been handledSerial.printf("[HTTPS] GET... code: %d\n", httpCode);// file found at serverif (httpCode == HTTP_CODE_OK){// get length of document (is -1 when Server sends no Content-Length header)int len = https.getSize();// create buffer for readstatic uint8_t buff[128] = {0};// read all data from serverint offset = 0;// 为什么这里分配内存会报错?// if(inbuf==NULL) inbuf=(uint8_t*)malloc(sizeof(uint8_t)*128);while (https.connected() && (len > 0 || len == -1)){// get available data sizesize_t size = client->available();if (size){// read up to 128 byteint c = client->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));memcpy(buffer + offset, buff, sizeof(uint8_t) * c);offset += c;// write it to Serial// Serial.write(buff, c);if (len > 0){len -= c;}}delay(1);}readBytesSize = offset;delay(1000);if (readBytesSize){// write it to SerialSerial.write(buffer, readBytesSize);Serial.println("");uint32_t out_size = 0;ArduinoUZlib::decompress(buffer, readBytesSize, outbuffer, out_size);Serial.write(outbuffer, out_size);// 调用解析函数JsonDocument doc;DeserializationError err = deserializeJson(doc, outbuffer);if (err.code() == DeserializationError::Ok){get_now_weather_data(doc);}else{Serial.println("数据解析出错");}}else{Serial.println("no avali size!");}if (outbuffer != NULL){free(outbuffer);outbuffer = NULL;}}}else{Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());}https.end();}else{Serial.printf("Unable to connect\n");}}
}void get_now_weather_data(JsonDocument &doc)
{// 将数据保存到weahter_data 的结构体,方便后续调用Serial.println("");wd.code = doc["code"];wd.updateTime = doc["updateTime"].as<String>().substring(0, 16);wd.now_obsTime = doc["now"]["obsTime"].as<String>().substring(0, 16);wd.updateTime.replace("T", " ");wd.now_obsTime.replace("T", " ");wd.now_temp = doc["now"]["temp"].as<String>();wd.now_feelsLike = doc["now"]["feelsLike"].as<int>();wd.now_icon = doc["now"]["icon"].as<String>();wd.now_text = doc["now"]["text"].as<String>();wd.now_wind360 = doc["now"]["wind360"].as<String>();wd.now_windDir = doc["now"]["windDir"].as<String>();wd.now_windScale = doc["now"]["windScale"].as<String>();wd.now_windSpeed = doc["now"]["windSpeed"].as<int>();wd.now_humidity = doc["now"]["humidity"].as<int>();wd.now_precip = doc["now"]["precip"].as<int>();wd.now_pressure = doc["now"]["pressure"].as<int>();wd.now_vis = doc["now"]["vis"].as<int>();Serial.print("wd.code: ");Serial.println(wd.code);Serial.print("wd.updateTime: ");Serial.println(wd.updateTime);Serial.print("wd.now_obsTime: ");Serial.println(wd.now_obsTime);Serial.print("wd.now_temp: ");Serial.println(wd.now_temp);Serial.print("wd.now_feelsLike: ");Serial.println(wd.now_feelsLike);Serial.print("wd.now_icon: ");Serial.println(wd.now_icon);Serial.print("wd.now_text: ");Serial.println(wd.now_text);Serial.print("wd.now_wind360: ");Serial.println(wd.now_wind360);Serial.print("wd.now_windDir: ");Serial.println(wd.now_windDir);Serial.print("wd.now_windScale: ");Serial.println(wd.now_windScale);Serial.print("wd.now_windSpeed: ");Serial.println(wd.now_windSpeed);Serial.print("wd.now_humidity: ");Serial.println(wd.now_humidity);Serial.print("wd.now_precip: ");Serial.println(wd.now_precip);Serial.print("wd.now_pressure: ");Serial.println(wd.now_pressure);Serial.print("wd.now_vis: ");Serial.println(wd.now_vis);
}
五、解压缩JSON数据源代码下载和运行效果展示
百度网盘下载:UZlib_Qweather_CompressedJsonData_7, 提取码:ivfq
友情提示:(1)请务必将 ssid 和 password 修改成您所在环境的名称和密码;(2)请务必const String key 修改成您自己申请的和风天气API密钥。
如果您能在串口监视器看到如下信息,那么恭喜您程序运行成功了。

参考文档
1. JSON 基本使用_json怎么用-CSDN博客
2. 如何获取和风天气Web API的KEY?(简要步骤)_天气预报web api key-CSDN博客
3. JSON——概述、JSON语法、序列化和反序列化_所有文档都可以通过json序列化吗-CSDN博客
相关文章:
【NodeMCU实时天气时钟温湿度项目 7】和风天气API返回JSON数据信息的解压缩实现——ArduinoUZlib功能库
今天是第七专题,主要内容是:导入ArduinoUZlib功能库,借助该库把从【和风天气】官网返回的经过Gzip压缩的JSON数据,进行解压缩和t解析,在串口监视器上输出解析后的JSON信息。 如您需要了解其它专题的内容,请…...
leetcode题目9
回文数 简单 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数:是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 思路 对于数字进行反转&a…...
CNAME记录
CNAME记录 维基百科,自由的百科全书 (重定向自CNAME) 真实名称记录(英语:Canonical Name Record),即CNAME记录,是域名系统(DNS)的一种记录。CNAME记录用于…...
pytest + yaml 框架 -69.新增depend 关键字,导入其它yaml用例
前言 有小伙伴提到,test_a.yml 中已经写了几个流程,test_b.yml 中希望能接着test_a.yml去写用例,于是就需要先导入test_a.yml用例。 为了满足此需求,v1.6.3版本 在config 中新增 depend 关键字。 需求场景 test_a.yml 中已经写…...
【网络】tcp的初始化序列号为什么要随机生成
TCP序列号和确认序列号 在TCP协议中,每个数据包都包含一个序列号和一个确认序列号,用于实现可靠的数据传输和流量控制。 序列号(Sequence Number):序列号是发送端为每个发送的数据包分配的唯一标识,用于标…...
【SRC实战】利用APP前端加密构造数据包
挖个洞先 https://mp.weixin.qq.com/s/ZnaRn222xJU0MQxWoRaiJg “ 以下漏洞均为实验靶场,如有雷同,纯属巧合” 01 — 漏洞证明 “ 参数加密的情况,不会逆向怎么办?” 1、新用户首次设置密码时抓包,此处设置为0000…...
ThreadLocal描述
ThreadLocal是Java中的一个类,用于在多线程环境下存储和获取线程相关的数据。每个ThreadLocal对象都可以维护一个线程本地的变量副本,这意味着每个线程都可以独立地改变自己的副本,而不会影响其他线程的副本。这种特性使得ThreadLocal非常适合…...
Linux-基础命令第三天
1、命令:wc 作用:统计行数、单词数、字符数 格式:wc 选项 文件名 例: 统计文件中的行数、单词数、字符数 说明:59代表行数,111代表单词数,2713代表字符数,a.txt代表文件名 选项…...
Windows Server 2022 环境下WEB和DNS服务器配置方法
目录 实验名称:WEB和DNS服务器配置实验目的实验原理:主要设备、器材:实验内容:配置本地WEB站点配置本地DNS服务器 实验名称:WEB和DNS服务器配置 实验目的 掌握 Windows Server 2022 环境下WEB服务器配置方法 掌握 Wi…...
静态住宅代理 IP 的影响
在不断发展的在线业务和数字营销领域,保持领先地位势在必行。在业界掀起波澜的最新创新之一是静态住宅代理 IP 的利用。这些知识产权曾经是为精通技术的个人保留的利基工具,现在正在成为各行业企业的游戏规则改变者。 一、静态住宅代理IP到底是什么&…...
IP代理中的SOCKS5代理是什么?安全吗?
在互联网世界中,网络安全和个人隐私保护变得日益重要。SOCKS5代理作为一种安全高效的网络工具,不仅可以保护个人隐私安全,还可以提供更稳定、更快度的网络连接。本文将带大家深入了解SOCKS5代理在网络安全领域中的应用。 什么是SOCKS5代理 …...
一个用Kotlin编写简易的串行任务调度器
引言 由于项目中有处理大量后台任务并且串行执行的需求,特意写了一个简易的任务调度器,方便监控每个任务执行和异常情况,任务之间互不影响。正如上所述,Kotlin中的TaskScheduler类提供了一个强大的解决方案,用于使用S…...
JavaScript异步编程——11-异常处理方案【万字长文,感谢支持】
异常处理方案 在JS开发中,处理异常包括两步:先抛出异常,然后捕获异常。 为什么要做异常处理 异常处理非常重要,至少有以下几个原因: 防止程序报错甚至停止运行:当代码执行过程中发生错误或异常时&#x…...
python如何做一个服务器fastapi 和flask
用 fastapi 方式的话 from fastapi import FastAPIapp FastAPI()app.get("/api") def index():return "hello world"然后需要安装 uvicorn 并执行下面的命令 uvicorn server:app --port 8000 --reload最终 如果是用 flask 直接写下面的代码 # -*- cod…...
Element-ui el-table组件单选/多选/跨页勾选讲解
文章目录 一、el-table介绍二、el-table单选三、el-table多选四、el-table跨页勾选五、热门文章 一、el-table介绍 el-table 是 Element UI(一个基于 Vue.js 的高质量 UI 组件库)中的一个组件,用于展示表格数据。通过 el-table,你…...
CentOS 安装 SeaweedFS
1. SeaweedFS 介绍 SeaweedFS 是一个简单且高度可扩展的分布式文件系统。有两个目标: to store billions of files! (存储数十亿个文件!)to serve the files fast! (快速提供文件!) Seaweedfs的中心节点(center master)…...
Redis如何避免数据丢失?——AOF
目录 AOF日志 1. 持久化——命令写入到AOF文件 写到用户缓冲区 AOF的触发入口函数——propagate 具体的实现逻辑——feedAppendOnlyFile 从用户缓冲区写入到AOF文件(磁盘) 函数write、fsync、fdatasync Redis的线程池 AOF文件的同步策略 触发的入口函数——…...
xFormers
文章目录 一、关于 xFormers二、安装 xFormers三、基准测试(可选)测试安装 四、使用 xFormers1、Transformers 关键概念2、Repo 地图注意力机制Feed forward mechanismsPositional embeddingResidual pathsInitializations 3、主要特征4、安装故障排除 一…...
LQ杯当时的WP
RC4 32位程序用IDA打开看看 进行反汇编 RC4提示,就是一个加密 在sub_401005函数中找到输出的变量,并且立下断点 动调 Packet 字符串搜索flag 看到是给192.168.11.128发送了cat flag的命令 看到它回传 Base64加密了 解一下密码就可以 CC 密码这…...
数据结构与算法学习笔记三---栈和队列
目录 前言 一、栈 1.栈的表示和实现 1.栈的顺序存储表示和实现 1.C语言实现 2.C实现 2.栈的链式存储表示和实现 1.C语言实现 2.C实现 2.栈的应用 1.数制转换 二、队列 1.栈队列的表示和实现 1.顺序队列的表示和实现 2.链队列的表示和实现 2.循环队列 前言 这篇文…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
