Selenium-介绍下其他骚操作

Chrome DevTools 简介

Chrome DevTools 是一组直接内置在基于 Chromium 的浏览器(如 Chrome、Opera 和 Microsoft Edge)中的工具,用于帮助开发人员调试和研究网站。

借助 Chrome DevTools,开发人员可以更深入地访问网站,并能够:

  • 检查 DOM 中的元素
  • 即时编辑元素和 CSS
  • 检查和监控网站的性能
  • 模拟用户的地理位置
  • 模拟更快/更慢的网络速度
  • 执行和调试 JavaScript
  • 查看控制台日志
  • 等等

Selenium 4 Chrome DevTools API

图片

Selenium 是支持 web 浏览器自动化的一系列工具和库的综合项目。Selenium 4 添加了对 Chrome DevTools API 的原生支持。借助这些新的 API,我们的测试现在可以:

捕获和监控网络流量和性能
模拟地理位置,用于位置感知测试、本地化和国际化测试
更改设备模式并测试应用的响应性
这只是冰山一角!

Selenium 4 引入了新的 ChromiumDriver 类,其中包括两个方法用于访问 Chrome DevTools:getDevTools() 和 executeCdpCommand()。

getDevTools() 方法返回新的 DevTools 对象,允许您使用 send() 方法发送针对 CDP 的内置 Selenium 命令。这些命令是包装方法,使调用 CDP 函数更加清晰和简便。

executeCdpCommand() 方法也允许您执行 CDP 方法,但更加原始。它不使用包装的 API,而是允许您直接传入 Chrome DevTools 命令和该命令的参数。如果某个 CDP 命令没有 Selenium 包装 API,或者您希望以与 Selenium API 不同的方式进行调用,则可以使用 executeCdpCommand()。

像 ChromeDriver 和 EdgeDriver 这样的基于 Chromium 的驱动程序现在继承自 ChromiumDriver,因此您也可以从这些驱动程序中访问 Selenium CDP API。

让我们探索如何利用这些新的 Selenium 4 API 来解决各种使用案例。

模拟设备模式

我们今天构建的大多数应用都是响应式的,以满足来自各种平台、设备(如手机、平板、可穿戴设备、桌面)和屏幕方向的终端用户的需求。

作为测试人员,我们可能希望将我们的应用程序放置在不同的尺寸中,以触发应用程序的响应性。

我们如何使用 Selenium 的新 CDP 功能来实现这一点呢?

用于修改设备度量的 CDP 命令是 Emulation.setDeviceMetricsOverride,并且此命令需要输入宽度、高度、移动设备标志和设备缩放因子。这四个键在此场景中是必需的,但还有一些可选的键。

在我们的 Selenium 测试中,我们可以使用 DevTools::send() 方法并使用内置的 setDeviceMetricsOverride() 命令,但是这个 Selenium API 接受 12 个参数 - 除了 4 个必需的参数外,还有 8 个可选的参数。对于我们不需要发送的这 8 个可选参数中的任何一个,我们可以传递 Optional.empty()。

然而,为了简化这个过程,只传递所需的参数,我将使用下面代码中的原始 executeCdpCommand() 方法。

package com.devtools;

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import java.util.HashMap;
import java.util.Map;

public class SetDeviceMode {

    final static String PROJECT_PATH = System.getProperty("user.dir");

    public static void main(String[] args){
        System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver");
        ChromeDriver driver;
        driver = new ChromeDriver();

        DevTools devTools = driver.getDevTools();
        devTools.createSession();
        Map deviceMetrics = new HashMap()
        {{
            put("width", 600);
            put("height", 1000);
            put("mobile", true);
            put("deviceScaleFactor", 50);
        }};
        driver.executeCdpCommand("Emulation.setDeviceMetricsOverride", deviceMetrics);
        driver.get("https://www.google.com");
    }
}

在第19行,我创建了一个包含此命令所需键的映射。

然后在第26行,我调用 executeCdpCommand() 方法,并传递两个参数:命令名称为 “Emulation.setDeviceMetricsOverride”,以及包含参数的设备度量映射。

在第27行,我打开了渲染了我提供的规格的 “Google” 首页,如下图所示。

图片

借助像 Applitools Eyes 这样的解决方案,我们不仅可以使用这些新的 Selenium 命令在不同的视口上快速进行测试,还可以在规模上保持任何不一致性。Eyes 足够智能,不会对由于不同的浏览器和视口导致的 UI 中微小且难以察觉的变化报告错误的结果。

模拟地理位置

在许多情况下,我们需要测试特定的基于位置的功能,例如优惠、基于位置的价格等。为此,我们可以使用DevTools API来模拟位置。

  @Test
    public void mockLocation(){
        devTools.send(Emulation.setGeolocationOverride(
                Optional.of(48.8584),
                Optional.of(2.2945),
                Optional.of(100)));
        driver.get("https://mycurrentlocation.net/");
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

模拟网络速度

许多用户通过连接到 Wi-Fi 或蜂窝网络的手持设备访问 Web 应用程序。遇到信号弱的网络信号,因此互联网连接速度较慢是很常见的。

在互联网连接速度较慢(2G)或间歇性断网的情况下,测试应用程序在这种条件下的行为可能很重要。

伪造网络连接的 CDP 命令是 Network.emulateNetworkConditions。关于此命令的必需和可选参数的信息可以在文档中找到。

通过访问 Chrome DevTools,就可以模拟这些场景。让我们看看如何做到这一点。

package com.devtools;

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.network.Network;
import org.openqa.selenium.devtools.network.model.ConnectionType;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class SetNetwork {

    final static String PROJECT_PATH = System.getProperty("user.dir");

    public static void main(String[] args){
        System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver");
        ChromeDriver driver;
        driver = new ChromeDriver();
        
        DevTools devTools = driver.getDevTools();
        devTools.createSession();
        devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));
        devTools.send(Network.emulateNetworkConditions(
                false,
                20,
                20,
                50,
                Optional.of(ConnectionType.CELLULAR2G)
        ));
        driver.get("https://www.google.com");
    }
}

在第21行,我们通过调用 getDevTools() 方法获取 DevTools 对象。然后,我们调用 send() 方法来启用 Network,并再次调用 send() 方法来传递内置命令 Network.emulateNetworkConditions() 和我们希望与此命令一起发送的参数。

最后,我们使用模拟的网络条件打开 Google 首页。

捕获HTTP请求

使用 DevTools,我们可以捕获应用程序发起的 HTTP 请求,并访问方法、数据、头信息等等。

让我们看看如何使用示例代码捕获 HTTP 请求、URI 和请求方法。

package com.devtools;

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.network.Network;

import java.util.Optional;

public class CaptureNetworkTraffic {

    private static ChromeDriver driver;
    private static DevTools chromeDevTools;

    final static String PROJECT_PATH = System.getProperty("user.dir");

    public static void main(String[] args){
        System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver");
        driver = new ChromeDriver();
        chromeDevTools = driver.getDevTools();
        chromeDevTools.createSession();

        chromeDevTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));
        chromeDevTools.addListener(Network.requestWillBeSent(),
                entry -> {
                    System.out.println("Request URI : " + entry.getRequest().getUrl()+"\n"
                    + " With method : "+entry.getRequest().getMethod() + "\n");
                    entry.getRequest().getMethod();
                });
        driver.get("https://www.google.com");
        chromeDevTools.send(Network.disable());
    }
}

开始捕获网络流量的 CDP 命令是 Network.enable。关于此命令的必需和可选参数的信息可以在文档中找到。

在我们的代码中,第22行使用 DevTools::send() 方法发送 Network.enable CDP 命令以启用网络流量捕获。

第23行添加了一个监听器,用于监听应用程序发送的所有请求。对于应用程序捕获的每个请求,我们使用 getRequest().getUrl() 提取 URL,并使用 getRequest().getMethod() 提取 HTTP 方法。

第29行,我们打开了 Google 的首页,并在控制台上打印了此页面发出的所有请求的 URI 和 HTTP 方法。

一旦我们完成了请求的捕获,我们可以发送 Network.disable 的 CDP 命令以停止捕获网络流量,如第30行所示。

拦截HTTP响应

为了拦截响应,我们将使用Network.responseReceived事件。当HTTP响应可用时触发此事件,我们可以监听URL、响应头、响应代码等。要获取响应正文,请使用Network.getResponseBody方法。

 @Test
    public void validateResponse() {
        final RequestId[] requestIds = new RequestId[1];
        devTools.send(Network.enable(Optional.of(100000000), Optional.empty(), Optional.empty()));
        devTools.addListener(Network.responseReceived(), responseReceived -> {
            if (responseReceived.getResponse().getUrl().contains("api.zoomcar.com")) {
                System.out.println("URL: " + responseReceived.getResponse().getUrl());
                System.out.println("Status: " + responseReceived.getResponse().getStatus());
                System.out.println("Type: " + responseReceived.getType().toJson());
                responseReceived.getResponse().getHeaders().toJson().forEach((k, v) -> System.out.println((k + ":" + v)));
                requestIds[0] = responseReceived.getRequestId();
                System.out.println("Response Body: \n" + devTools.send(Network.getResponseBody(requestIds[0])).getBody() + "\n");
            }
        });
        driver.get("https://www.zoomcar.com/bangalore");
        driver.findElement(By.className("search")).click();
    }

访问控制台日志

我们都依赖日志来进行调试和分析故障。在测试和处理具有特定数据或特定条件的应用程序时,日志可以帮助我们调试和捕获错误消息,提供更多在 Chrome DevTools 的控制台选项卡中发布的见解。

我们可以通过调用 CDP 日志命令来通过我们的 Selenium 脚本捕获控制台日志,如下所示。

package com.devtools;

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.log.Log;

public class CaptureConsoleLogs {
    
    private static ChromeDriver driver;
    private static DevTools chromeDevTools;
    final static String PROJECT_PATH = System.getProperty("user.dir");

    public static void main(String[] args){
        System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver");
        driver = new ChromeDriver();
        chromeDevTools = driver.getDevTools();
        chromeDevTools.createSession();

        chromeDevTools.send(Log.enable());
        chromeDevTools.addListener(Log.entryAdded(),
                logEntry -> {
                    System.out.println("log: "+logEntry.getText());
                    System.out.println("level: "+logEntry.getLevel());
                });
        driver.get("https://testersplayground.herokuapp.com/console-5d63b2b2-3822-4a01-8197-acd8aa7e1343.php");
    }
}

在我们的代码中,第19行使用 DevTools::send() 来启用控制台日志捕获。

然后,我们添加一个监听器来捕获应用程序记录的所有控制台日志。对于应用程序捕获的每个日志,我们使用 getText() 方法提取日志文本,并使用 getLevel() 方法提取日志级别。

最后,打开应用程序并捕获应用程序发布的控制台错误日志。

捕获性能指标

在当今快节奏的世界中,我们以如此快的速度迭代构建软件,我们也应该迭代性地检测性能瓶颈。性能较差的网站和加载较慢的页面会让客户感到不满。

我们能够在每次构建时验证这些指标吗?是的,我们可以!

捕获性能指标的 CDP 命令是 Performance.enable。关于这个命令的信息可以在文档中找到。

让我们看看如何在 Selenium 4 和 Chrome DevTools API 中完成这个过程。

package com.devtools;

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.performance.Performance;
import org.openqa.selenium.devtools.performance.model.Metric;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class GetMetrics {

    final static String PROJECT_PATH = System.getProperty("user.dir");

    public static void main(String[] args){
        System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver");
        ChromeDriver driver = new ChromeDriver();
        DevTools devTools = driver.getDevTools();
        devTools.createSession();
        devTools.send(Performance.enable());

        driver.get("https://www.google.org");

        List<Metric> metrics = devTools.send(Performance.getMetrics());
        List<String> metricNames = metrics.stream()
                .map(o -> o.getName())
                .collect(Collectors.toList());

        devTools.send(Performance.disable());

        List<String> metricsToCheck = Arrays.asList(
                "Timestamp", "Documents", "Frames", "JSEventListeners",
                "LayoutObjects", "MediaKeySessions", "Nodes",
                "Resources", "DomContentLoaded", "NavigationStart");

        metricsToCheck.forEach( metric -> System.out.println(metric +
                " is : " + metrics.get(metricNames.indexOf(metric)).getValue()));
    }
}

首先,我们通过调用 DevTools 的 createSession() 方法创建一个会话,如第19行所示。

接下来,我们通过将 Performance.enable() 命令发送给 send() 来启用 DevTools 来捕获性能指标,如第20行所示。

一旦启用了性能捕获,我们可以打开应用程序,然后将 Performance.getMetrics() 命令发送给 send()。这将返回一个 Metric 对象的列表,我们可以通过流式处理来获取捕获的所有指标的名称,如第25行所示。

然后,我们通过将 Performance.disable() 命令发送给 send() 来禁用性能捕获,如第29行所示。

为了查看我们感兴趣的指标,我们定义了一个名为 metricsToCheck 的列表,然后通过循环遍历该列表来打印指标的值。

基本身份验证

在 Selenium 中,无法与浏览器弹出窗口进行交互,因为它只能与 DOM 元素进行交互。这对于身份验证对话框等弹出窗口构成了挑战。

我们可以通过使用 CDP API 直接与 DevTools 处理身份验证来绕过此问题。设置请求的附加标头的 CDP 命令是 Network.setExtraHTTPHeaders。

以下是在 Selenium 4 中调用此命令的方法。

package com.devtools;

import org.apache.commons.codec.binary.Base64;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.network.Network;
import org.openqa.selenium.devtools.network.model.Headers;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class SetAuthHeader {

  private static final String USERNAME = "guest";
  private static final String PASSWORD = "guest";
  final static String PROJECT_PATH = System.getProperty("user.dir");

  public static void main(String[] args){
    System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver");
    ChromeDriver driver = new ChromeDriver();

    //Create DevTools session and enable Network
    DevTools chromeDevTools = driver.getDevTools();
    chromeDevTools.createSession();
    chromeDevTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));

    //Open website
    driver.get("https://jigsaw.w3.org/HTTP/");

    //Send authorization header
    Map<String, Object> headers = new HashMap<>();
    String basicAuth ="Basic " + new String(new Base64().encode(String.format("%s:%s", USERNAME, PASSWORD).getBytes()));
    headers.put("Authorization", basicAuth);
    chromeDevTools.send(Network.setExtraHTTPHeaders(new Headers(headers)));

    //Click authentication test - this normally invokes a browser popup if unauthenticated
    driver.findElement(By.linkText("Basic Authentication test")).click();

    String loginSuccessMsg = driver.findElement(By.tagName("html")).getText();
    if(loginSuccessMsg.contains("Your browser made it!")){
      System.out.println("Login successful");
    }else{
      System.out.println("Login failed");
    }

    driver.quit();
  }
}

我们首先使用 DevTools 对象创建一个会话,并启用 Network。这在第25-26行中展示。

接下来,我们打开我们的网站,然后创建用于发送的身份验证标头。

在第35行,我们将 setExtraHTTPHeaders 命令发送到 send(),同时发送标头的数据。这部分将对我们进行身份验证并允许我们绕过浏览器弹出窗口。

为了测试这个功能,我们点击了基本身份验证测试链接。如果您手动尝试这个操作,您会看到浏览器弹出窗口要求您进行登录。但由于我们发送了身份验证标头,所以我们的脚本中不会出现这个弹出窗口。

相反,我们会收到消息“您的浏览器登录成功!”。

总结

通过添加 CDP API,Selenium 已经变得更加强大。现在,我们可以增强我们的测试,捕获 HTTP 网络流量,收集性能指标,处理身份验证,并模拟地理位置、时区和设备模式。以及在 Chrome DevTools 中可能出现的任何其他功能!

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言:一个数如果恰好等于除它本身外的因子之和,这个数就称为完数。例如6=1+2+3。编程找出1000以内的所有完数。

分析&#xff1a; 在主函数 main 中&#xff0c;程序首先定义三个整型变量 m、s 和 i&#xff0c;并用于计算和判断完数。然后使用 printf 函数输出提示信息。 接下来&#xff0c;程序使用 for 循环结构&#xff0c;从 2 到 999 遍历所有的数。对于每个遍历到的数 m&#xff0c…

ESP32-Web-Server编程- JS 基础 3

ESP32-Web-Server编程- JS 基础 3 概述 本示例演示通过 button 控件的 onclick 内联属性&#xff0c;实现在网页上点击按钮&#xff0c;切换 LED 灯图标的转变。 示例解析 前端设计 前端代码建立了一个 id 为 “imageLamp” 的图片对象。并建立两个按钮&#xff0c;设计两…

pinyin4j 汉字转拼音包括——多音字

一、Maven 依赖 <dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.1</version> </dependency> 二、通过多音字字典匹配 2.1&#xff0c;先看效果效果 输入&#xff1a;我在重庆…

前缀和与差分

文章目录 前缀和一维前缀和公式CODE 二维前缀和公式CODE 差分一维差分思路作用CODE 二维差分思路CODE 前缀和 一维前缀和 板子题&#xff1a;https://www.acwing.com/activity/content/problem/content/829/ 公式 S [ i ] a [ i ] S [ i − 1 ] S[i] a[i] S[i - 1] S[i]…

大数据Doris(三十):删除数据(Delete)

文章目录 删除数据(Delete) 一、​​​​​​​DELETE FROM Statement(条件删除)

【Cmake】Cmake基础学习

CMake学习 一、基础学习 1. 利用Cmake进行单个源代码构建可执行文件 (1)基础命令 最基本的 CMake项目是由单个源代码文件构建的可执行文件。对于这样的简单项目,只需要一个包含三个命令的 CMakeLists.txt 文件。 注意: 虽然 CMake 支持大写、小写和混合大小写命令,但是…

矩阵置零[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个m x n的矩阵&#xff0c;如果一个元素为0&#xff0c;则将其所在行和列的所有元素都设为0。请使用原地算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[…

[C++]六大默认成员函数详解

☃️个人主页&#xff1a;fighting小泽 &#x1f338;作者简介&#xff1a;目前正在学习C和Linux &#x1f33c;博客专栏&#xff1a;C入门 &#x1f3f5;️欢迎关注&#xff1a;评论&#x1f44a;&#x1f3fb;点赞&#x1f44d;&#x1f3fb;留言&#x1f4aa;&#x1f3fb; …

【VUE】There are multiple modules with names that only differ in casing.

报错 There are multiple modules with names that only differ in casing. This can lead to unexpected behavior when compiling on a filesystem with other case-semantic. Use equal casing. Compare these module identifiers: 图示原因&#xff1a;大小写&#xff0c;有…

C#——多线程之异步调用容易出现的问题

C#——多线程之异步调用容易出现的问题 Q1&#xff1a;For中异步调用函数且函数输入具有实时性 Q1&#xff1a;For中异步调用函数且函数输入具有实时性 在项目进行过程中&#xff0c;发现For中用异步调用带有输入参数的函数时&#xff0c;会由于闭包特性&#xff0c;以及Task.…

ELK----日志分析

ELK相关知识 ELK的概念与组件 ELK平台是一套完整的日志集中处理解决方案&#xff0c;将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用&#xff0c; 完成更强大的用户对日志的查询、排序、统计需求。 E&#xff1a;ElasticSearch &#xff08;ES&#xff09; ES是…

C#,《小白学程序》第二十一课:大数的减法(BigInteger Subtract)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// </summary> p…

C/C++ 常用加密与解密算法

计算机安全和数据隐私是现代应用程序设计中至关重要的方面。为了确保数据的机密性和完整性&#xff0c;常常需要使用加密和解密算法。C是一种广泛使用的编程语言&#xff0c;提供了许多加密和解密算法的实现。本文将介绍一些在C中常用的加密与解密算法&#xff0c;这其中包括Xo…

力扣373场周赛题解

第一题&#xff1a; 这个题是一个简单题&#xff0c;数据范围也特别小&#xff0c;所以直接使用模拟方式暴力解答。 直接进行行移动的过程&#xff0c;然后检查移动后的结果是否与移动前相同。 代码&#xff1a; ​ public class Solution {// 将指定行循环右移k次pri…

OpenCV完结篇——计算机视觉(人脸识别 || 车牌识别)

文章目录 Haar人脸识别方法Haar识别眼鼻口HaarTesseract进行车牌识别深度学习基础知识dnn实现图像分类 Haar人脸识别方法 scaleFactor调整哈尔级联器的人脸选框使其能框住人脸 官方教程指路 每个特征都是通过从黑色矩形下的像素总和减去白色矩形下的像素总和获得的单个值 级…

排序篇(六)----排序小结(不用三连,混流量券)

排序篇(六)----排序小结 排序算法复杂度及稳定性分析 直接插入排序的算法复杂度&#xff1a; 最好情况下&#xff0c;当数组已经有序时&#xff0c;直接插入排序的时间复杂度为O(n)&#xff0c;其中n是数组的大小。最坏情况下&#xff0c;当数组逆序排列时&#xff0c;直接插…

解析实人认证API的工作原理与应用场景

引言 随着数字化时代的不断发展&#xff0c;实人认证技术在各个领域中发挥着越来越重要的作用。其中&#xff0c;实人认证API作为一种先进的技术手段&#xff0c;通过输入姓名、身份证号码和一张人脸照片&#xff0c;与公安库身份证头像进行权威比对&#xff0c;从而返回比对分…

生物神经系统的基本原理 神经元Neuron

生物神经系统的基本原理涉及一系列复杂的生物学和生理学机制&#xff0c;主要可以分为以下几个方面&#xff1a; 神经元与突触&#xff1a;神经系统的基本单位是神经元&#xff0c;它们通过突触连接彼此。神经元接收并处理来自身体其他部分或环境的信息&#xff0c;然后通过电信…

FFmpeg零基础学习(二)——视频文件信息获取

目录 前言正文一、获取宽高信息1、核心代码2、AVFormatContext3、avformat_alloc_context4、avformat_open_input5、avformat_find_stream_info6、av_dump_format7、av_find_best_stream End、遇到的问题1、Qt Debug模式avformat_alloc_context 无法分配对象&#xff0c;而Rele…

【SQL Server Management】使用手册

目录 ⛳️【SQL Server Management】 ⛳️1. 启动登录 ⛳️2. 忘记密码 ⛳️3. 操作数据库和表 3.1 新建数据库text 3.2 新建表 3.3 编辑表 3.4 编写脚本 ⛳️【SQL Server Management】 ⛳️1. 启动登录 需要开启服务 ⛳️2. 忘记密码 登录windows--> 安全性 -->…