【NodeMCU实时天气时钟温湿度项目 7】和风天气API返回JSON数据信息的解压缩实现——ArduinoUZlib功能库

news2024/11/18 17:36:08

        今天是第七专题,主要内容是:导入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 压缩文件。

        (2)解压 zip 文件,生 成ArduinoUZlib-main 文件夹。
        (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.ino

    Created 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 header
      int httpCode = https.GET();
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK) {

          // get length of document (is -1 when Server sends no Content-Length header)
          int len = https.getSize();

          // create buffer for read
          static uint8_t buff[128] = { 0 };

          // read all data from server
          int 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 size
            size_t size = client->available();
            
            if (size) {
              // read up to 128 byte
              int 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 connection
  fetchBuffer();
  Serial.printf("\nAfter fetch, buffer size=%d\n", readBytesSize);
  delay(1000);
  if(readBytesSize) {
    // write it to Serial
    log("===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 header
      int httpCode = https.GET();
      if (httpCode > 0)
      {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK)
        {
          // get length of document (is -1 when Server sends no Content-Length header)
          int len = https.getSize();

          // create buffer for read
          static uint8_t buff[128] = {0};
          // read all data from server
          int offset = 0;
          //  为什么这里分配内存会报错?
          // if(inbuf==NULL) inbuf=(uint8_t*)malloc(sizeof(uint8_t)*128);
          while (https.connected() && (len > 0 || len == -1))
          {
            // get available data size
            size_t size = client->available();

            if (size)
            {
              // read up to 128 byte
              int 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 Serial
            Serial.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博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1675818.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

做抖店不能踩的几个坑,新手要照做,老玩家要听劝~

我是王路飞。 很多人都说抖店的运营很简单&#xff0c;选选品、对接一下达人&#xff0c;就可以坐等店铺出单了。 这话骗骗还没开店的小白也就得了&#xff0c;但凡做抖店超过一个月的&#xff0c;都不会相信这句话。 细心耐心是做抖店最基本的态度。 拿到一个好结果的前提…

24深圳杯C题18页高质量论文+可执行代码+图表

比赛题目的完整版思路可执行代码数据参考论文都会在第一时间更新上传的&#xff0c;大家可以参考我往期的资料&#xff0c;所有的资料数据以及到最后更新的参考论文都是一次付费后续免费的。注意&#xff1a;&#xff08;建议先下单占坑&#xff0c;因为随着后续我们更新资料数…

Host is not allowed to connect to this MySQL server解决方法

在阿里云服务器上安装了Mysql数据库&#xff0c;在阿里云上使用一切正常。我用navicat 去连接服务器时显示Host is not allowed to connect to this MySQL server。 ​ 看见这个错误&#xff0c;第一反应是是不是阿里云服务器防火墙没有配置mysq的出入站规则。去阿里云检查了一…

08 必会框架 - Spring全家桶

本课时主要介绍 Java 中常用的应用框架&#xff0c;重点讲解如下三部分内容。 Spring 框架中的主要知识点&#xff1b; NIO 框架 Netty 以及基于 Netty 实现的主流 RPC 框架 Motan、Dubbo 和 gRPC&#xff1b; ORM 框架 MyBatis。 常用框架汇总 先来看常用框架的知识点汇总…

基于springboot实现的在线动漫信息平台

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

129.哈希表:有效的字母异位词(力扣)

242. 有效的字母异位词 - 力扣&#xff08;LeetCode&#xff09; 题目描述 代码解决以及思路 这个方法的时间复杂度为O(N)&#xff0c;其中N是字符串的长度&#xff0c;空间复杂度为O(1)&#xff08;因为辅助数组的大小是固定的26&#xff09;。 class Solution { public:bo…

ASP.NET银行大厅自助信息系统的开发与实现

摘 要 本毕业设计在基于银行业务大厅现有业务的基础上&#xff0c;针对自助银行的概念和其独有特点&#xff0c;通过.NETSQL技术&#xff0c;开发一个简单的银行大厅自助信息系统&#xff0c;完成一些自助银行的业务需求如帐户信息查询、帐户挂失、自助交费、留言、新闻查询…

某攻防演练心得之随笔记

最近太忙了&#xff0c;忙于各种奇奇怪怪的事情&#xff0c;有攻防&#xff0c;有应急&#xff0c;有渗透&#xff0c;还成为了一段时间内的“word高级工程师”......有师傅说我现在更新的越来越慢了&#xff0c;是呀&#xff0c;其实我也不知道怎么了&#xff0c;每天各种新闻…

原生小程序开发如何使用 tailwindcss

原生小程序开发如何使用 tailwindcss 原生小程序开发如何使用 tailwindcss 前言什么是 weapp-tailwindcss ?0. 准备环境以及小程序项目1. 安装与配置 tailwindcss 0. 使用包管理器安装 tailwindcss1. 在项目目录下创建 postcss.config.js 并注册 tailwindcss2. 配置 tailwind…

idea控制台日志控制

1.清除控制台log日志 测试的时候&#xff0c;控制台打印的日志比较多&#xff0c;速度有点慢而且不利于查看运行结果&#xff0c;所以接下来我们把这个日志处理下: 取消初始化spring日志打印&#xff0c;resources目录下添加logback.xml&#xff0c;名称固定&#xff0c;内容如…

基于Springboot的校园疫情防控信息管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校园疫情防控信息管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…

嵌入式学习-通用定时器

简介 框图介绍 时钟选择 计数器部分 输入捕获和输出比较框图 嵌入式学习全文参考&#xff08;小向是个der&#xff09;做笔记&#xff1a;https://blog.csdn.net/qq_41954556/article/details/129735708

AI助力内容创作:让效率与质量齐飞

简述&#xff1a; 本文介绍了AI如何帮助创作者在保持内容质量的同时&#xff0c;大幅度提升生产效率的一些方法&#xff0c;希想 对大家有帮助。 一、自动化内容生成 1. 文本内容生成 使用GPT等模型&#xff1a;利用如GPT-3或GPT-4等大型语言模型&#xff0c;可以直接输入关…

CentOS 7安装Nginx错误

说明&#xff1a;本文记录两个CentOS 7安装Nginx时的错误&#xff1b; 场景&解决 CentOS 7安装Nginx&#xff0c;参考下面这篇文章&#xff1a; CentOS 7安装Nginx 进入nginx目录&#xff0c;运行configure文件时&#xff0c;报下面的错误 错误信息&#xff1a;./confi…

NSSCTF Web方向的例题和相关知识点(二)

[SWPUCTF 2021 新生赛]Do_you_know_http 解题&#xff1a; 点击打开环境&#xff0c;是 提示说请使用wLLm浏览器访问 我们可以更改浏览器信息&#xff0c;在burp重放器中发包后发现是302重定向&#xff0c;但是提示说success成功&#xff0c;说明 我们修改是成功的&#xff…

视频号小店从开店到爆单,最详细的攻略教学,来了!

大家好&#xff0c;我是喷火龙 视频号小店从推出到现在一直备受关注&#xff0c;我的团队已经入局视频号小店一年多了&#xff0c; 可以说&#xff0c;新手做视频号小店采用无货源模式和达人带货的玩法依旧是最合适的。 虽然说这个模式和玩法很多人之前都接触过&#xff0c;…

【iOS】——RunLoop学习

文章目录 一、RunLoop简介1.RunLoop介绍2.RunLoop功能3.RunLoop使用场景4.Run Loop 与线程5.RunLoop源代码和模型图 二、RunLoop Mode1.CFRunLoopModeRef2.RunLoop Mode的五种模式3.RunLoop Mode使用 三、RunLoop Source1.CFRunLoopSourceRefsourc0&#xff1a;source1: 2.CFRu…

深入了解 npm:Node.js 包管理工具详解

文章目录 一、npm 基本概念1.1 什么是 npm&#xff1f;1.2 package.json 文件 二、npm 常用命令2.1 初始化项目2.2 安装依赖2.2.1 安装单个包2.2.2 全局安装包2.2.3 安装开发依赖 2.3 移除依赖2.4 更新依赖2.5 查看已安装的包2.6 发布包 三、npm 高级用法3.1 使用 npm scripts3…

冯喜运:5.14今日黄金原油涨跌走势分析操作建议

【黄金消息面分析】&#xff1a;本周黄金市场将迎来关键的美国通胀数据&#xff0c;包括周二的生产者价格指数(PPI)和周三的消费者物价指数(CPI)。这些数据对美联储的政策路径至关重要&#xff0c;可能会影响市场对利率调整的预期。目前&#xff0c;现货黄金价格小幅上涨&#…

echarts实现金价可视化大屏(项目实战)

前言 最近由于某种原因参加了一个比赛&#xff0c;三天时间肝出来一个可视化大屏项目&#xff08;无后端&#xff09;&#xff0c;代码已开源&#xff0c;但是还在比赛期间不知道会不会影响到 技术使用&#xff1a;html&#xff0c;css&#xff0c;js&#xff0c;echarts&#…