c# 通过webView2模拟登陆小红书网页版,解析无水印视频图片,以及解决X-s,X-t签名验证【2023年4月15日】

news2024/9/27 17:32:04

一、c# WebView2简介
  1.一开始使用WebBrowser,因为WebBrowser控件使用的是ie内核,经过修改注册表切换为Edge内核后,
发现Edge内核版本较低,加载一些视频网站提示“浏览器版本过低“,”视频无法加载“。

2.WebBrowser内核版本与WebView2比较

WebBrowser内核版本:
内核版本 (Version) Edge 18.9200 兼容 WebKit 537.36  Chrome 70 
UserAgent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.9200

当前Edge内核版本:
内核版本 (Version)    WebKit 537.36  Chrome 111.0.0.0
UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54

WebView2内核版本:
内核版本 (Version)    WebKit 537.36  Chrome 111.0.0.0
UserAgent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.51

可见,WebView2内核版本跟Edge一样,能顺利打开视频网站。WebBrowser内核版本过低。

WebView2加载视频网站

3.WebView2概述
  Microsoft Edge WebView2 控件允许在本机应用中嵌入 web 技术(HTML、CSS 以及 JavaScript)。 WebView2 控件使用 Microsoft Edge 作为绘制引擎,以在本机应用中显示 web 内容。
虽说无法跨平台,但是在windows应用下做为原浏览器控件替代品还是不错的。

4.安装webview2
   打开NuGet,搜索WebView2,安装之后,可以看到左侧就有了webview2控件,可以直接拖到窗体内。

二、问题分析
1、关于登陆会话的问题
网页端必须打开小红书网站。小红书打开后,在浏览器Cookie里,有一个字段:
web_session=040069b3b3f6625dade26f8d1d364b44f72186
这是记录登陆会话信息的。请求时headers中需要x-s、x-t,cookie中需要有web_session。
经测试,这个web_session会在浏览器保存一段时间,具体多久还有待验证(B站也有个类似的session,是一个月)。其它字段无关紧要。
不使用WebView2打开网站的话,需要到网站申请web_session,这里WebView2已经替我们弄好了。
通过c# WebView2获取cookie信息的方法:

private Dictionary<string, string> mCookies = new Dictionary<string, string>();//保存Cookie到字典中

/// <summary>
        /// WebView2异步获取cookie
        /// </summary>
        /// <param name="url">与cookie关联的域名</param>
        private async void getCookie(string url)
        {
            List<CoreWebView2Cookie> cookieList = await webView.CoreWebView2.CookieManager.GetCookiesAsync(url);
            mCookies.Clear();
            for (int i = 0; i < cookieList.Count; ++i)
            {
                CoreWebView2Cookie cookie = webView.CoreWebView2.CookieManager.CreateCookieWithSystemNetCookie(cookieList[i].ToSystemNetCookie());
                mCookies.Add(cookie.Name, cookie.Value);
            }

        }

        /// <summary>
        /// 提取cookie中的一个字段;
        /// </summary>
        /// <param name="url">域名</param>
        /// <param name="key">关键字,如:web_session</param>
        /// <param name="t">延时(没用到)</param>
        /// <returns></returns>
        public string getCookieEx(string url, string key, int t)
        {
            getCookie(url);
            if (mCookies.ContainsKey(key))
            {
                string cookies = "";
                foreach (var cookie in mCookies)
                {
                    cookies += cookie.Key + "=" + cookie.Value + ";";
                }
                cookies = key + "=" + mCookies[key];
                return cookies;
            }


            return null;
        }

2.笔记信息接口

目前笔记信息接口: /api/sns/web/v1/feed
请求时headers中需要x-s、x-t,cookie中需要有web_session。

3.X-S
定位方法很多,可以全局搜 "X-s" 。往上找可以发现该段为 sign 方法,function sign(e, t) {}

全部复制到本地,然后根据报错把缺的方法和环境补一下,比如a0_0x4dee00、a0_0x5c27、a0_0x543e等方法,

然后把常用的navigator、location、document、window加上就好了。

该过程中根据具体错误再调试分析, 比如sign方法的 case "6",修改为var vr = window 、在case "7"中可以手动修改为 dr = ur['sNYMU']
这里已经拿到了function sign(e, t) {}的JavaScript版,需要的+v:byc6352

三、WebView2中C#和JavaScript代码互操作
 1.需要创建一个ScriptHost对象,并注册到WebView2中:

    /// <summary>
    /// 网页调用C#方法
    /// </summary>
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisible(true)]
    public class ScriptHost

2.在WebView2初始化完成事件中注册ScriptHost对象

        /// <summary>
        /// CoreWebView2初始化完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void webView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
        {
            //注册winning,winasync脚本c#互操作
            webView.CoreWebView2.AddHostObjectToScript("scriptHost", scriptHost);
            //注册全局变量winning 同步操作;winasync:异步操作;
            webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var winasync= window.chrome.webview.hostObjects.scriptHost;");
            webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var winning= window.chrome.webview.hostObjects.sync.scriptHost;");
        }

3.ScriptHost中暴露的公共方法,都可以在前端JavaScript中调用。

        /// <summary>
        /// 日志记录(JavaScript前端调用
        /// </summary>
        /// <param name="message">JavaScript前端信息</param>
        public void log(string message)
        {
            Log.i(message);//记录到文本文件中
            //MessageBox.Show(message);
        }
..............................................
winning.log(data);//JavaScript端调用(同步调用);

四、下载封面及视频


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Configuration;
using System.Text;
using System.Threading.Tasks;

namespace XhsVideo
{
    /// <summary>
    /// 下载视频
    /// </summary>
    internal class VideoDown
    {
        public int id { get; set; }
        public VideoInfo video { get; set; }
        public string savedir { get; set; }
        public string msg { get; set; }
        public bool success { get; set; }
        public string headers { get; set; }
        public VideoDown(int id,VideoInfo video,string savdir,string headers=null) {
            this.id = id;
            this.video = video;
            this.savedir = savdir;
            if (System.IO.Directory.Exists(savdir)) System.IO.Directory.CreateDirectory(savdir);
            this.headers = headers;
        }
        public void process()
        {
            string filename = MakeValidFileName( video.title,"");  //去除文件名中的非法字符
            string videoname = savedir + "\\" + filename + ".mp4";
            string covername = savedir + "\\" + filename + ".webp";
            if (System.IO.File.Exists(covername)) System.IO.File.Delete(covername);
            if (System.IO.File.Exists(videoname)) System.IO.File.Delete(videoname);
            Log.i(videoname);
            Log.i(covername);
            //NetHelper.downloadfileAsync(video.videoUrl, videoname);
            NetHelper.downloadfileAsync(video.coverUrl, covername);
            NetHelper.DownloadFileAsync(video.videoUrl, videoname, showProgress);//显示下载视频的进度
        }






        /**
            * @param text: 原始串
            * @param replacement: 要替换的字符串
        */
        public static string MakeValidFileName(string text, string replacement = "_")
        {
            StringBuilder str = new StringBuilder();
            var invalidFileNameChars = System.IO.Path.GetInvalidFileNameChars();
            foreach (var c in text)
            {
                if (invalidFileNameChars.Contains(c))
                {
                    str.Append(replacement ?? "");
                }
                else
                {
                    str.Append(c);
                }
            }

            return str.ToString();
        }
        /// <summary>
        /// 下载视频的进度回调函数
        /// </summary>
        /// <param name="msg">下载进度信息</param>
        public void showProgress(string msg)
        {
            this.msg = msg;
            Log.i(msg);
            fMainForm.GetFMainForm().syncContext.Send(fMainForm.GetFMainForm().SetTextSafePost, this);//Post 将信息发送到窗体显示

        }

    }


    /// <summary>
    /// 视频信息类,由:标题,封面地址,视频地址组成。
    /// </summary>

    public class VideoInfo
    {
        public string title { get; set; }
        public string coverUrl { get; set; }
        public string videoUrl { get; set; }
        public VideoInfo(string title,string coverUrl,string videoUrl)
        {
            this.title = title;
            this.coverUrl = coverUrl;
            this.videoUrl = videoUrl;
        }
    }
}

五、日志记录


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XhsVideo
{
    /// <summary>
    /// 日志记录 到文本文件
    /// </summary>
    internal class Log
    {
        private static  Log log;
        private static string logName;
        private Log(string filename) {
            logName = filename;
        }
        public static Log GetLog(string filename)
        {
            if (log == null) { log = new Log(filename); }
            return log;
        }
        public static Log GetLog()
        {
            return log;
        }
        public static void i(string msg)
        {
            string now = DateTime.Now.ToString();
            string[] text = new string[2];
            text[0] = now;
            text[1] = msg;
            try
            {
                using (StreamWriter sw = new StreamWriter(logName,true,Encoding.UTF8))
                {
                    foreach (string s in text)
                    {
                        sw.WriteLine(s);

                    }
                    sw.Close();
                }
                
            }
            catch (Exception e)
            {
                //Console.WriteLine("Exception: " + e.Message);
            }
            finally
            {
                //Console.WriteLine("Executing finally block.");
            }
        }
    }
}

六、网络访问组件


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using System.Windows.Forms;

namespace XhsVideo
{
    /// <summary>
    /// 网络访问组件
    /// </summary>
    internal class NetHelper
    {

        #region 文件下载
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url">文件下载地址</param>
        /// <param name="savePath">本地保存路径+名称</param>
        /// <param name="downloadCallBack">下载回调(总长度,已下载,进度)</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static async Task DownloadFileAsync(string url, string savePath, Action<string> downloadCallBack = null)
        {
            try
            {
                downloadCallBack?.Invoke($"文件【{url}】开始下载!");
                HttpResponseMessage response = null;
                using (HttpClient client = new HttpClient())
                    response = await client.GetAsync(url);
                if (response == null)
                {
                    downloadCallBack?.Invoke("文件获取失败");
                    return;
                }
                var total = response.Content.Headers.ContentLength ?? 0;
                var stream = await response.Content.ReadAsStreamAsync();
                var file = new FileInfo(savePath);
                using (var fileStream = file.Create())
                using (stream)
                {
                    if (downloadCallBack == null)
                    {
                        await stream.CopyToAsync(fileStream);
                        downloadCallBack?.Invoke($"文件【{url}】下载完成!");
                    }
                    else
                    {
                        byte[] buffer = new byte[1024];
                        long readLength = 0;
                        int length;
                        double temp = 0;
                        string msg = "";
                        while ((length = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
                        {
                            // 写入到文件
                            fileStream.Write(buffer, 0, length);

                            //更新进度
                            readLength += length;
                            double progress = Math.Round((double)readLength / total * 100, 2, MidpointRounding.AwayFromZero);//.ToZero

                            if ((progress % 1) == 0 && (progress % 1) != temp)
                            { 
                                msg = $"总大小:【{total}】,已下载:【{readLength}】,进度:【{progress}】";
                                downloadCallBack?.Invoke(msg);
                            }
                            temp = progress % 1;
                            //下载完毕立刻关闭释放文件流
                            if (total == readLength && progress == 100)
                            {
                                fileStream.Close();
                                fileStream.Dispose();
                                msg = $"总大小:【{total}】,已下载:【{readLength}】,进度:【{progress}】下载完成。";
                                downloadCallBack?.Invoke(msg);
                            }


                        }
                    }
                }
            }
            catch (Exception ex)
            {
                downloadCallBack?.Invoke($"下载文件失败:{ex.Message}!");
            }
        }
        #endregion




        /// <summary>
        /// 异步下载文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="filename"></param>
        public static async void downloadfileAsync(string url,string filename)
        {
            using (var web = new WebClient())
            {
                await web.DownloadFileTaskAsync(url, filename);
            }
        }
      
        /// <summary>
        /// 地址重定向
        /// </summary>
        /// <param name="url">原地址</param>
        /// <param name="domain">域名</param>
        /// <param name="ua">userAgent</param>
        /// <returns>重定向后的地址</returns>
        public static string getRedirectedUrl(string url, string domain, string ua)
        {
            var str = getRedirectedUrl_T(url);
            return str.Result;
        }
        /// <summary>
        /// 异步地址重定向
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private static async Task<string> getRedirectedUrl_T(string url)
        {
            try
            {
                var handler = new HttpClientHandler()
                {
                    AllowAutoRedirect = false
                };
                var client = new HttpClient(handler);

                var response = await client.GetAsync(url).ConfigureAwait(continueOnCapturedContext: false);
                int statuscode = (int)response.StatusCode;
                if (statuscode == 307)
                {
                    string location = response.Headers.Location.ToString();
                    return location;
                }
                if (statuscode == 302)
                {
                    string location = response.Headers.Location.ToString();
                    return location;
                }
                else
                {
                    return "";
                }
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("getRedirectedUrl_T:" + e.ToString());
                return "";
            }
        }
        //---------------------------------------------------------------post---------------------------------------------------------------------
        /// <summary>
        /// Post访问
        /// </summary>
        /// <param name="url">访问地址</param>
        /// <param name="args">数据</param>
        /// <param name="headers">HTTP头</param>
        /// <returns>返回服务器JSON数据</returns>
        public static string getPostResult(string url, string args, string headers)
        {
            var str = getPostResult_T(url, args, headers);
            return str.Result;
        }
        /// <summary>
        /// 异步post调用
        /// </summary>
        /// <param name="url"></param>
        /// <param name="args"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        private static async Task<string> getPostResult_T(string url, string args, string headers)
        {
            try
            {
                var handler = new HttpClientHandler() { UseCookies = false };
                var client = new HttpClient(handler);// { BaseAddress = baseAddress };
                client.Timeout = TimeSpan.FromSeconds(20);
                var message = new HttpRequestMessage(HttpMethod.Post, url);
                message.Content = new StringContent(args);
                message.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                //message.Headers;
                Dictionary<string, string> dictionary = ParseToDictionary(headers);
                foreach (var pair in dictionary)
                {
                    if (pair.Key.Equals("content-type")) continue;
                    if (pair.Key.Equals("Content-Type")) continue;
                    message.Headers.Add(pair.Key, pair.Value);
                }

                var result = await client.SendAsync(message).ConfigureAwait(continueOnCapturedContext: false);
                result.EnsureSuccessStatusCode();
                return await result.Content.ReadAsStringAsync();
            }
            catch (Exception e)
            {
                //EventLog.GetEventLogs(e.ToString);
                System.Diagnostics.Debug.WriteLine("getPostResultEx_T:" + e.ToString());
                ///console.write(e.ToString());
                return "";
            }
        }
        
        /// <summary>
        /// 字符串解析为字典数据
        /// </summary>
        /// <param name="str">以回车换行符分割的字符串</param>
        /// <returns>字典数据</returns>
        private static Dictionary<string, string> ParseToDictionary(string str)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            string str1 = str;
            int i = str1.IndexOf("\r\n");
            int j = 0;
            while (i > 0)
            {
                string str2 = str1.Substring(0, i);
                j = str2.IndexOf(":");
                if (j > 0)
                {
                    string str21 = str2.Substring(0, j);
                    string str22 = str2.Substring(j + 1);
                    result.Add(str21, str22);
                }
                str1 = str1.Substring(i + 2);
                i = str1.IndexOf("\r\n");
            }
            j = str1.IndexOf(":");
            if (j > 0)
            {
                string str21 = str1.Substring(0, j);
                string str22 = str1.Substring(j + 1);
                result.Add(str21, str22);
            }
            return result;
        }
        //-------------------------------------------------------------------GET -------------------------------------------------------------------
        /// <summary>
        /// 获取服务器端的HTML代码
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string getHtmlCode(string url)
        {
            var str = getHtmlCode_T(url);
            return str.Result;
        }
        /// <summary>
        /// 异步获取服务器端的HTML代码
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static async Task<string> getHtmlCode_T(string url)
        {
            try
            {
                var http = new HttpClient();
                http.Timeout = TimeSpan.FromSeconds(10);
                var result = await http.GetStringAsync(url).ConfigureAwait(continueOnCapturedContext: false);
                return result;
            }
            catch (Exception e)
            {
                //EventLog.GetEventLogs(e.ToString);
                System.Diagnostics.Debug.WriteLine("错误信息在这儿:" + e.ToString());
                ///console.write(e.ToString());
                Log.i(e.ToString());
                return "";
            }
        }

    }
}

因为涉及的技术知识点太多了,一时半会写不完,后续继续完善。需要源码的加。


                                         (未完待续)

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

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

相关文章

CentOS上PHP源码安装和配置

CentOS上PHP源码安装和配置 此文是在CentOS 7上已经部署了Nginx的基础上进行的 关于CentOS7上安装Nginx&#xff0c;可参考我之前的文章&#xff1a; CentOS上Nginx安装记录 我们现在在这个基础上安装PHP 7。 PHP里面概念挺多的&#xff0c;没想到安装这个PHP需要花那么多时…

SpringBoot 表单提交全局日期格式转换器

参考资料 SpringBoot–LocalDateTime格式转换(前端入参)SpringBoot InitBinder注解绑定请求参数 目录 一. 实现Converter<S, T>接口的方式二. 全局ControllerAdvice InitBinder注解的方式三. RequestMappingHandlerAdapter的方式四. 效果 分析 ⏹当前台的提交数据的Con…

JVM-0418

JVM-字节码篇 虚拟机体系结构 线程共享&#xff1a;堆、方法区 线程私有&#xff1a;虚拟机栈&#xff0c;本地方法栈&#xff0c;程序计数器。其中虚拟机栈中包括局部变量表&#xff0c;和操作数栈。 字节码文件概述 字节码文件是跨平台的吗&#xff1f; 是的 Java虚拟机…

Apache Log4j2(CVE-2021-4101)远程代码执行漏洞复现

文章目录前言影响范围黑盒发现复现准备JNDILADPRMI漏洞复现Dnslog数据外带使用工具进行反弹shell防御与绕过防御绕过参考前言 Apache log4j是Apache的一个开源项目&#xff0c;Java的日志记录工具(同logback)。 log4j2中存在JNDI注入漏洞&#xff0c;当程序记录用户输入的数据…

Qt Quick - FileDialog文件对话框

FileDialog文件对话框使用总结一、概述二、使用三、常用属性四、常用例子1. 单选打开文本文件2. 单选保存文本文件一、概述 FileDialog提供了一个基本的文件选择器的功能&#xff1a;它允许用户选择现有的文件或目录&#xff0c;或者创建新的文件名。 对话框最初是不可见的。…

【性能测试学习】2023最有效的7大性能测试技术(建议收藏)

进入互联网时代&#xff0c;性能测试显得越来越重要&#xff0c;移动应用、web应用和物联网应用都需要进行性能测试和性能调优&#xff0c;而进行性能和负载测试会产生了大量的数据&#xff0c;这些数据难以分析。除了数据分析&#xff0c;我们还会遇到其它一些困难和挑战。 今…

数据结构和算法学习记录——认识二叉搜索树及二叉搜索树的查找操作(递归以及迭代实现-查找操作、查找最大和最小元素)

目录 二叉搜索树 二叉搜索树的一些操作函数 二叉搜索树的查找操作Find 递归实现 迭代实现 查找最大和最小元素 查找最小元素的递归函数 查找最大元素的迭代函数 二叉搜索树 二叉搜索树&#xff08;BST&#xff0c;Binary Search Tree&#xff09;&#xff0c;也称二…

深入了解 Hugging Face 中的生成工具:Generate方法

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

SSH升级

升级openssh版本一、安装telnet远程管理主机1、检查是否安装telnet2、安装telnet服务二、下载所需的安装包1、下载openssl、openssh、zlib安装包2、安装所需的相关软件3、备份原来的数据4、复制文件到/usr/local/bin/下增加执行权限一、安装telnet远程管理主机 1、检查是否安装…

通达信口袋支点选股公式编写和设置方法答疑

1、口袋支点选股公式成交量条件 在我编写的口袋支点选股公式中&#xff0c;成交量条件为成交量创10日新高。有网友提出&#xff0c;根据书中的定义&#xff0c;口袋支点成交量条件是成交量大于近10日下跌时的最大成交量。 这个问题确实是我没考虑周全&#xff0c;成交量创10日…

【5G NAS】NR 终端侧PDU建立过程以及数据包的过滤和映射

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

对数据去趋势

对数据去趋势 测量的信号可能显示数据中非固有的整体模式。这些趋势有时会妨碍数据分析&#xff0c;因此必须进行去趋势。 以具有不同趋势的两种心电图 (ECG) 信号为例。ECG 信号对电源干扰等扰动很敏感。加载信号并绘制它们。 load(ecgSignals.mat) t (1:length(ecgl));su…

LaTeX+Overleaf 论文速通教程

一、文本/排版二、章节和段落三、数学公式四、插入图片五、插入表格六、参考文献与交叉引用不使用BibTeX使用BibTeX(推荐)七、交叉引用label和refOverleaf开发界面 latex命令&#xff1a;\命令[可选参数]{必选参数} Latex项目组成&#xff1a; .tex&#xff1a;正文 .bib&…

如何对数据库进行优化

数据库是什么&#xff1f; 简单来说数据库就是将数据按照一定顺序存储到磁盘上的一个软件&#xff0c;我们平时写的sql语句&#xff0c;就是用数据库软件能识别的语言&#xff0c;对数据进行增删改查。其实数据本质上是不存在表里&#xff0c;而是存在磁盘上&#xff0c;所谓的…

掌握亚马逊,沃尔玛,东南亚平台的测评要点,测评事半功倍

测评其实最重要的两个点就是自己的资源和成号率 资源包括;商家资源&#xff0c;中介资源&#xff0c;礼品卡资源&#xff0c;还有买卖账号的渠道&#xff0c;ip资源 成号率这个直接影响的就是你个人投入成本的多&#xff0c;成号率越高&#xff0c;你的成本越低&#xff0c;但…

【Java版oj】day36Rational Arithmetic、Pre-Post

目录 一、Rational Arithmetic &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码 二、Pre-Post &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码 一、…

十七、小程序报错 真机调试预览失效 Error: Illegal Buffer

报错 电脑端微信开发者工具运行成功而真机调试预览失效 报错 MiniProgramError Illegal Buffer 报错 {errno: 600001, errMsg: “request:fail -200:net::ERR_CERT_COMMON_NAME_INVALID”} 前言&#xff1a;手头有个去年的微信小程序项目 年底甲方不在使用 所以停掉了服务器、…

互联网医院系统构建:探索开源云平台与互联网医院平台源码的融合

互联网医院系统作为一种新型医疗服务模式&#xff0c;将传统的医院门诊转化为在线咨询、远程会诊等形式&#xff0c;帮助患者更加方便地获得专业医疗服务。 在实现互联网医院系统的建设过程中&#xff0c;选择合适的云平台和医院平台源码是至关重要的。 首先&#xff0c;开源…

LVM逻辑卷管理

目录一、LVM简介1、逻辑卷管理磁盘的优点2、缺陷3、LVM概述图二、LVM的使用1、创建逻辑卷2、使用逻辑卷3、删除逻辑卷4、LVM扩容5、LVM缩容三、Snapshot&#xff08;快照功能&#xff09;1、LVM-snapshot简介2、利用snapshot做备份&#xff08;LV快照&#xff09;四、LVM数据迁…

整型在内存中的存储

在计算机底层&#xff0c;所有数据最终都会被表示为二进制形式。整型也不例外。本文将介绍在C语言中如何定义和操作整型变量&#xff0c;并解释整型在内存中的存储方式。 整型变量的定义和使用 在C语言中&#xff0c;可以用int关键字来定义一个整数型变量。例如&#xff1a; …