微信网页授权之使用完整服务解决方案

目录

微信网页授权能力调整造成的问题

能力调整的内容和理由

原有运行方案

is_snapshotuser字段 

改造原有方案

如何复现测试场景

小结


微信网页授权能力调整造成的问题

依附于第三方的开发,做为开发者经常会遇到第三方进行规范和开发的调整,如开发腾讯微信的相关应用。我所经历的如小程序隐私政策调整、信息备案调整、微信授权获取个人信息限制调整等。

最近我们的一些项目因为微信页面授权能力的调整出现了一些问题,对于新用户未经授权前,微信开发团队给出的输出是快照页,该页内所获取的openId等均为虚拟账号数据,并在屏幕下方非常不明显的显示“使用完整服务”,如下图所示:

此图即是微信给出的授权提示,也是我们折中的解决方案,图中所示的提示框源自己于我们通过携带的参数反馈给用户的提示,以引导用户点击下方的“使用完整服务”链接,并进行授权。

能力调整的内容和理由

微信团队给出的解释是当开发者在网页中在不规范使用发起 snsapi_userinfo 网页授权时,微信将默认打开网页快照页模式进行基础浏览。

微信网页授权规范

  1. 授权流程需引导清晰、准确:在申请获取用户信息的弹窗出现前,应该清晰、准确地告知用户获取信息的范围及获取信息的目的;
  2. 必要场景申请:在必须获取用户信息时才申请,而不是用户尚未了解服务前就强制弹窗。如使用医院挂号时才需要获取用户信息;
  3. 不强制登录:提供游客模式,供用户了解网页提供的基础服务,不强制用户允许网页获取用户信息后才能使用网页服务。

常见的微信网页授权不规范使用案例

  1. 强制登录:在用户打开网页时立即要求用户授权,用户拒绝后无法使用网页提供的服务;
  2. 违规收集个人信息:未在网页提前告知使用个人信息的目的、方式和范围;
  3. 非必要收集:非必要获取用户信息的网页,如文章、视频等,要求用户在浏览内容前登录;
  4. 差别对待微信用户:同样的网页在浏览器内可以无需登录直接访问,在微信内却要求用户先登录才可访问。

原有运行方案

微信OA2授权访问地址如下(示例url为C#字符串):

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx7964497eb8bad783&redirect_uri=https%3A//www.leadihr.com/weixin/oa2.aspx%3F&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect&connect_redirect = 1

重定向接收地址 OA2.ASPX程序 (C#版本)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Collections;
using System.Net;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using LitJson;
using System.Data;
using System.Data.SqlClient;
using CosysJaneCommonAPI;
using System.Web.Script.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;public partial class oa2 : System.Web.UI.Page
{string Appid = "";string appsecret = "";string domain = "";public class OAuth_Token{public OAuth_Token(){}//access_token  网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同  //expires_in    access_token接口调用凭证超时时间,单位(秒)  //refresh_token 用户刷新access_token  //openid    用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID  //scope 用户授权的作用域,使用逗号(,)分隔  public string access_token { get; set; }public string expires_in { get; set; }public string refresh_token { get; set; }public string openid { get; set; }public string scope { get; set; }}public class OAuthUser{public OAuthUser(){ }#region 数据库字段private string _openID;private string _searchText;private string _unionid;private string _nickname;private string _sex;private string _province;private string _city;private string _country;private string _headimgUrl;
//        private string _privilege;#endregion#region 字段属性/// <summary>  /// 用户的唯一标识  /// </summary>  public string openid{set { _openID = value; }get { return _openID; }}public string SearchText{set { _searchText = value; }get { return _searchText; }}/// <summary>  /// 用户昵称   /// </summary>  public string nickname{set { _nickname = value; }get { return _nickname; }}public string unionid{set { _unionid = value; }get { return _unionid; }}/// <summary>  /// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知   /// </summary>  public string sex{set { _sex = value; }get { return _sex; }}/// <summary>  /// 用户个人资料填写的省份  /// </summary>  public string province{set { _province = value; }get { return _province; }}/// <summary>  /// 普通用户个人资料填写的城市   /// </summary>  public string city{set { _city = value; }get { return _city; }}/// <summary>  /// 国家,如中国为CN   /// </summary>  public string country{set { _country = value; }get { return _country; }}/// <summary>  /// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空  /// </summary>  public string headimgurl{set { _headimgUrl = value; }get { return _headimgUrl; }}/// <summary>  /// 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)其实这个格式称不上JSON,只是个单纯数组  /// </summary>  //public string privilege//{//    set { _privilege = value; }//    get { return _privilege; }//}#endregion}      protected void Page_Load(object sender, EventArgs e)  {if (!IsPostBack)  {if (!string.IsNullOrEmpty(Request.QueryString["code"]))  {  string Code = Request.QueryString["code"].ToString();string State = Request.QueryString["state"].ToString();//获得Token  OAuth_Token Model = Get_token(Code);OAuthUser OAuthUser_Model = Get_UserInfo(Model.access_token, Model.openid);string content=Model.access_token+ "用户OPENID:" + OAuthUser_Model.openid + "<br>用户昵称:" + OAuthUser_Model.nickname + "<br>性别:" + OAuthUser_Model.sex + "<br>所在省:" + OAuthUser_Model.province + "<br>所在市:" + OAuthUser_Model.city + "<br>所在国家:" + OAuthUser_Model.country + "<br>头像地址:" + OAuthUser_Model.headimgurl + "<br>用户特权信息:";Response.Redirect("https://x.x.com/index.aspx?&oid=" + OAuthUser_Model.openid);}  }  }
public class JsonHelper
{/// <summary>/// 生成Json格式/// </summary>/// <typeparam name="T"></typeparam>/// <param name="obj"></param>/// <returns></returns>public static string GetJson<T>(T obj){DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType());using (MemoryStream stream = new MemoryStream()){json.WriteObject(stream, obj);string szJson = Encoding.UTF8.GetString(stream.ToArray()); return szJson;}}/// <summary>/// 获取Json的Model/// </summary>/// <typeparam name="T"></typeparam>/// <param name="szJson"></param>/// <returns></returns>public static T ParseFromJson<T>(string szJson){T obj = Activator.CreateInstance<T>();using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson))){DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());return (T)serializer.ReadObject(ms);}}
}  //获得Token  protected OAuth_Token Get_token(string Code)  {  string Str = GetJson("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + Appid + "&secret=" + appsecret + "&code=" + Code + "&grant_type=authorization_code");OAuth_Token Oauth_Token_Model = JsonHelper.ParseFromJson<OAuth_Token>(Str);  return Oauth_Token_Model;  }  //刷新Token  protected OAuth_Token refresh_token(string REFRESH_TOKEN)  {  string Str = GetJson("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + Appid + "&grant_type=refresh_token&refresh_token=" + REFRESH_TOKEN);  OAuth_Token Oauth_Token_Model = JsonHelper.ParseFromJson<OAuth_Token>(Str);  return Oauth_Token_Model;  }  //获得用户信息  protected OAuthUser Get_UserInfo(string REFRESH_TOKEN, string OPENID)  {  // Response.Write("获得用户信息REFRESH_TOKEN:" + REFRESH_TOKEN + "||OPENID:" + OPENID);  string Str = GetJson("https://api.weixin.qq.com/sns/userinfo?access_token=" + REFRESH_TOKEN + "&openid=" + OPENID + "&lang=zh_CN");  OAuthUser OAuthUser_Model = JsonHelper.ParseFromJson<OAuthUser>(Str);return OAuthUser_Model;  }  protected string GetJson(string url)  {  WebClient wc = new WebClient();  wc.Credentials = CredentialCache.DefaultCredentials;  wc.Encoding = Encoding.UTF8;string returnText = "";try{returnText = wc.DownloadString(url);}catch (Exception e){Response.Write(e.Message);Response.End();}if (returnText.Contains("errcode"))  {  //可能发生错误  }  //Response.Write(returnText);  return returnText;  }  }

is_snapshotuser字段 

通过code换取网页授权access_token
请求方法是获取code后,请求以下链接获取access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

正确时会返回具有如下图所示的JSON数据包:

因此可能通过判断 is_snapshotuser 字段是否为1,判断是否快照页模式

改造原有方案

主要是增加 string is_snapshotuser = "0" 和后续对JSON返回值的判断,并返回回调的url并携带此参数。示例代码如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Collections;
using System.Net;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using LitJson;
using System.Data;
using System.Data.SqlClient;
using CosysJaneCommonAPI;
using System.Web.Script.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;public partial class oa2 : System.Web.UI.Page
{string Appid = "";string appsecret = "";string domain = "";string is_snapshotuser = "0";public class OAuth_Token{public OAuth_Token(){}//access_token  网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同  //expires_in    access_token接口调用凭证超时时间,单位(秒)  //refresh_token 用户刷新access_token  //openid    用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID  //scope 用户授权的作用域,使用逗号(,)分隔  public string access_token { get; set; }public string expires_in { get; set; }public string refresh_token { get; set; }public string openid { get; set; }public string scope { get; set; }}public class OAuthUser{public OAuthUser(){ }#region 数据库字段private string _openID;private string _searchText;private string _unionid;private string _nickname;private string _sex;private string _province;private string _city;private string _country;private string _headimgUrl;
//        private string _privilege;#endregion#region 字段属性/// <summary>  /// 用户的唯一标识  /// </summary>  public string openid{set { _openID = value; }get { return _openID; }}public string SearchText{set { _searchText = value; }get { return _searchText; }}/// <summary>  /// 用户昵称   /// </summary>  public string nickname{set { _nickname = value; }get { return _nickname; }}public string unionid{set { _unionid = value; }get { return _unionid; }}/// <summary>  /// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知   /// </summary>  public string sex{set { _sex = value; }get { return _sex; }}/// <summary>  /// 用户个人资料填写的省份  /// </summary>  public string province{set { _province = value; }get { return _province; }}/// <summary>  /// 普通用户个人资料填写的城市   /// </summary>  public string city{set { _city = value; }get { return _city; }}/// <summary>  /// 国家,如中国为CN   /// </summary>  public string country{set { _country = value; }get { return _country; }}/// <summary>  /// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空  /// </summary>  public string headimgurl{set { _headimgUrl = value; }get { return _headimgUrl; }}/// <summary>  /// 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)其实这个格式称不上JSON,只是个单纯数组  /// </summary>  //public string privilege//{//    set { _privilege = value; }//    get { return _privilege; }//}#endregion}      protected void Page_Load(object sender, EventArgs e)  {if (!IsPostBack)  {if (!string.IsNullOrEmpty(Request.QueryString["code"]))  {  string Code = Request.QueryString["code"].ToString();string State = Request.QueryString["state"].ToString();//获得Token  OAuth_Token Model = Get_token(Code);OAuthUser OAuthUser_Model = Get_UserInfo(Model.access_token, Model.openid);string content=Model.access_token+ "用户OPENID:" + OAuthUser_Model.openid + "<br>用户昵称:" + OAuthUser_Model.nickname + "<br>性别:" + OAuthUser_Model.sex + "<br>所在省:" + OAuthUser_Model.province + "<br>所在市:" + OAuthUser_Model.city + "<br>所在国家:" + OAuthUser_Model.country + "<br>头像地址:" + OAuthUser_Model.headimgurl + "<br>用户特权信息:";Response.Redirect("https://x.x.com/index.aspx?&oid=" + OAuthUser_Model.openid+"&is_snapshotuser="+is_snapshotuser);}  }  }
public class JsonHelper
{/// <summary>/// 生成Json格式/// </summary>/// <typeparam name="T"></typeparam>/// <param name="obj"></param>/// <returns></returns>public static string GetJson<T>(T obj){DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType());using (MemoryStream stream = new MemoryStream()){json.WriteObject(stream, obj);string szJson = Encoding.UTF8.GetString(stream.ToArray()); return szJson;}}/// <summary>/// 获取Json的Model/// </summary>/// <typeparam name="T"></typeparam>/// <param name="szJson"></param>/// <returns></returns>public static T ParseFromJson<T>(string szJson){T obj = Activator.CreateInstance<T>();using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson))){DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());return (T)serializer.ReadObject(ms);}}
}  //获得Token  protected OAuth_Token Get_token(string Code)  {  string Str = GetJson("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + Appid + "&secret=" + appsecret + "&code=" + Code + "&grant_type=authorization_code");if (Str.IndexOf("\"is_snapshotuser\":1") != -1||Str.IndexOf("\"is_snapshotuser\": 1")!=-1){is_snapshotuser = "1";}OAuth_Token Oauth_Token_Model = JsonHelper.ParseFromJson<OAuth_Token>(Str);  return Oauth_Token_Model;  }  //刷新Token  protected OAuth_Token refresh_token(string REFRESH_TOKEN)  {  string Str = GetJson("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + Appid + "&grant_type=refresh_token&refresh_token=" + REFRESH_TOKEN);  OAuth_Token Oauth_Token_Model = JsonHelper.ParseFromJson<OAuth_Token>(Str);  return Oauth_Token_Model;  }  //获得用户信息  protected OAuthUser Get_UserInfo(string REFRESH_TOKEN, string OPENID)  {  // Response.Write("获得用户信息REFRESH_TOKEN:" + REFRESH_TOKEN + "||OPENID:" + OPENID);  string Str = GetJson("https://api.weixin.qq.com/sns/userinfo?access_token=" + REFRESH_TOKEN + "&openid=" + OPENID + "&lang=zh_CN");  OAuthUser OAuthUser_Model = JsonHelper.ParseFromJson<OAuthUser>(Str);return OAuthUser_Model;  }  protected string GetJson(string url)  {  WebClient wc = new WebClient();  wc.Credentials = CredentialCache.DefaultCredentials;  wc.Encoding = Encoding.UTF8;string returnText = "";try{returnText = wc.DownloadString(url);}catch (Exception e){Response.Write(e.Message);Response.End();}if (returnText.Contains("errcode"))  {  //可能发生错误  }  //Response.Write(returnText);  return returnText;  }  }

这样可以在业务页面,如上述代码中的index.aspx进行如下判断:

if (Request.QueryString["is_snapshotuser"] == "1")
{Layer.open("使用前微信要求您的授权,请点击下方使用完整服务后继续...", "'确定'", "info");return;
}

如何复现测试场景

已经授权的用户,如果想测试重新授权的场景,请打开微信,依如下步骤进行设置:

 

 

 

 

小结

以上示例是一种较小改动的解决方案,个人比较习惯于应用程序稳定性第一的思路。如果已经使用新规则设计方案则可仅供参考。

另外在此介绍一下关于网页授权的两种scope的区别:
1、以snsapi_base为scope发起的网页授权,可以直接获取进入页面的用户的openid,且是静默授权并自动跳转到业务页面。
2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。需要用户手动同意,无须关注,就可在授权后获取该用户的基本信息。

以上是个人的一些观点和解决方案,感谢阅读,并提出指正。

 

 

 

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

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

相关文章

【EI会议征稿通知】2024年材料物理与复合材料国际学术会议

2024年材料物理与复合材料国际学术会议 2024 International Conference on Materials Physics and Composites(ICMPC 2024) 2024年材料物理与复合材料国际学术会&#xff08;ICMPC 2024&#xff09;将于2024年5月24-26日在中国成都举行。ICMPC 2024将吸引顶尖的研究人员和从业…

Python flask 模板详解

文章目录 1 概述1.1 模板简介1.2 templates 文件1.3 简单应用 2 模板语法2.1 for 循环2.2 if 判断 3 模板的继承3.1 格式要求3.2 实现示例3.3 复用父模板的内容&#xff1a;super 1 概述 1.1 模板简介 定义&#xff1a;定义好的 html 文件&#xff0c;用于快速开发 web 页面J…

【不单调的代码】还在嫌弃Ubuntu终端?快来试试做些Ubuntu终端的花式玩法。

&#x1f38a;专栏【不单调的代码】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Love Story】 &#x1f970;大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 注意&#xff1a; 本文是在Ubuntu环境下进…

Unity中blendtree和state间的过渡

混合树状态之间的过渡 如果属于此过渡的当前状态或下一状态是混合树状态&#xff0c;则混合树参数将出现在 Inspector 中。通过调整这些值可预览在混合树值设置为不同配置时的过渡表现情况。 如果混合树包含不同长度的剪辑&#xff0c;您应该测试在显示短剪辑和长剪辑时的过渡表…

明道云入选亿欧智库《AIGC入局与低代码产品市场的发展研究》

2023年12月27日&#xff0c;亿欧智库正式发布**《AIGC入局与低代码产品市场的发展研究》**。该报告剖析了低代码/零代码市场的现状和发展趋势&#xff0c;深入探讨了大模型技术对此领域的影响和发展洞察。其中&#xff0c;亿欧智库将明道云作为标杆产品进行了研究和分析。 明…

指针的学习2

目录 数组名的理解 使用指针访问数组 一维数组传参的本质 冒泡排序 二级指针 指针数组 指针数组模拟二维数组 数组名的理解 数组名是数组首元素的地址 例外&#xff1a; sizeof(数组名),sizeof中单独放数组名&#xff0c;这里的数组名表示整个数组&#xff0c;计算的…

mac如何实现升级node版本、切换node版本

一、 查看node所有版本&#xff08;前提:安装了nodejs&#xff09; npm view node versions二、安装指定node版本 sudo n 版本号三、检查目前安装了哪些版本的node&#xff0c;会出现已安装的node版本 n四、切换已安装的node版本 sudo n 版本号其他命令 1、sudo npm cache…

Git快速入门+常用指令+提交规范

目录 Git创建本地仓库 IDEA集成Git Git和IDEA连接使用2 忽略文件 本地仓库常用命令 远程仓库常用命令 分支常用命令 标签操作 提交规范 Git创建本地仓库 1、创建一个文件夹&#xff0c;右键选择Git Bash Here 2、选择下列其中一个方法 方法一&#xff1a;创建初始化…

一篇文章了解区分指针数组,数组指针,函数指针,链表。

最近在学习指针&#xff0c;发现指针有这许多的知识&#xff0c;其中的奥妙还很多&#xff0c;需要学习的也很多&#xff0c;今天那我就将标题中的有关指针知识&#xff0c;即指针数组&#xff0c;数组指针&#xff0c;函数指针&#xff0c;给捋清楚这些知识点&#xff0c;区分…

react native错误记录

第一次运行到安卓失败 Could not find implementation class com.facebook.react.ReactRootProjectPlugin for plugin com.facebook.react.rootproject specified in jar:file:/D:/Android_Studio_Data/.gradle/caches/jars-9/o_3a1fd35320f05989063e7069031b710f/react-nativ…

LabVIEW智能温度直流模件自动测试系统

LabVIEW智能温度直流模件自动测试系统 自动化测试系统在提高测试效率和准确性方面发挥着越来越重要的作用。介绍了一种基于LabVIEW的智能温度直流模件&#xff08;TDCA&#xff09;自动测试系统的设计与实施&#xff0c;旨在提高测控装置的产品质量。 系统的硬件平台主要由PS…

一篇文章搞懂CNN(卷积神经网络)及其所含概念

目录 1. 什么是卷积神经网络&#xff1a;2. 应用领域&#xff1a;3. 架构&#xff1a;4. 卷积层的参数和名词参数&#xff1a;名词&#xff1a; 5. 注意&#xff1a;6. 经典网络&#xff1a;小结&#xff1a; 当下&#xff0c;计算机视觉在人工智能领域中扮演着至关重要的角色。…

matlab使用jdbc连接数据库

1、打包jdbc 2、在matlab安装目录下&#xff0c;进去toolbox目录下&#xff0c;新建一个对应放jdbc包的文件夹&#xff0c;加入放入的是mysql的jdbc驱动包&#xff0c;就新建一个mysql目录&#xff0c;将驱动包放入mysql目录下 3、在toolbox目录下&#xff0c;找到local目录&a…

手工方式安装19.22RU

使用手工方式打RU19.22 参考文档&#xff1a; Supplemental Readme - Grid Infrastructure Release Update 12.2.0.1.x / 18c /19c (Doc ID 2246888.1) 操作步骤&#xff1a; 1 Stop the CRS managed resources running from DB homes. 2 Run the pre root script. 3 Patch G…

C语言问题汇总

指针 #include <stdio.h>int main(void){int a[4] {1,2,3,4};int *p &a1;int *p1 a1;printf("%#x,%#x",p[-1],*p1);} 以上代码中存在错误。 int *p &a1; 错误1&#xff1a;取a数组的地址&#xff0c;然后1&#xff0c;即指针跳过int [4]大小的字节…

SQL 函数(十二)

SQL 函数&#xff08;十二&#xff09; 一、函数分类 1.1 单行函数 单行函数仅对单个行进行运算&#xff0c;并且每行返回一个结果。 常见的函数类型&#xff1a; 字符、数字、日期、转换 1.2 多行函数 多行函数能够操纵成组的行&#xff0c;每个行组给出一个结果&#x…

创新大赛专访丨南沙人才荣膺2023年度人才寻猎标杆品牌:吸纳海内外高学历人才,助力南沙精准“选苗”

日前&#xff0c;2023第三届全国人力资源创新大赛颁奖典礼暨成果展圆满举行。自2023年10月份启动以来&#xff0c;大赛共吸引了457个案例报名参赛&#xff0c;经组委会专家团队评审严格审核&#xff0c;企业赛道共有103个案例获奖、72家企业、13位个人、7个产业园斩获荣誉。 广…

Unity引擎学习笔记之【角色按键器操作】

角色按键Character Controls 一、脚本操作 设置脚本 设置基本键盘操作 //水平轴float horizontal Input.GetAxis("Horizontal");//垂直轴float vertical Input.GetAxis("Vertical");//创建方向向量Vector3 dir new Vector3(horizontal,0,vertical);/…

Unity根据落点和抛物线运行时间,求初始力

抛物线运行时长为2秒&#xff1a; 抛物线运行时长为4秒&#xff1a; 原理就是&#xff1a; 在竖直方向只受重力&#xff0c;做匀加速直线运动&#xff0c;水平不受力&#xff0c;做匀速直线运动。 代码&#xff1a; public void Update(){if (Input.GetKeyDown(KeyCode.Space)…

《Python 网络爬虫简易速速上手小册》第2章:网络爬虫准备工作(2024 最新版)

文章目录 2.1 选择合适的爬虫工具和库2.1.1 重点基础知识讲解2.1.2 重点案例&#xff1a;使用 Scrapy 抓取电商网站2.1.3 拓展案例 1&#xff1a;使用 Requests 和 BeautifulSoup 抓取博客文章2.1.4 拓展案例 2&#xff1a;使用 Selenium 抓取动态内容 2.2 设置开发环境2.2.1 重…