个人开发者实现微信扫码登录

article/2025/9/21 20:59:17

使用码上登录中转微信扫码登录

使用之前最好有一个公网服务器,能够公网访问的 redismysql 数据库,并且能够部署公网访问的服务

码上登录是一个小程序,对个体开发者提供了免费的微信扫一扫登录入口:官网 http://login.vicy.cn/

针对微信扫码登录需要进行企业认证,个人开发者无法使用的问题,我们可以使用码上登录进行桥接,将微信扫码登录的信息转发给我们的程序

在开发之前,我们需要有一个能被公网访问的地址,用来接收码上登录回调给我们的用户数据

更多信息参考码上登录 Api 文档:http://login.vicy.cn/apiWord.html

使用步骤

进入码上登录官网创建我们的应用:http://login.vicy.cn/

  • 微信扫码登录,进入首页,点击 马上创建应用

    image-20220629122032966
  • 点击创建应用,输入网站名称和回调 URL ,填写完成后创建回得到 secretKey

    网站名称就是用户扫码后看到的你的网站名称

    回调 URL 就是用户确认登录后,接收用户信息的 controller ,可以先随便写,再后期修改

    image-20220629122305663

    image-20220629122747300

创建后台应用

  • 先创建一个 web 模块 service-ucenter 用于编写代码,需要整合 mybatisredis ,我使用 SpringBootweb 项目

    导入 commons 和对应的数据库依赖,该依赖的作用是让我们发送 HTTP 请求,获取二维码信息

    <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId>
    </dependency>
    <dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
    </dependency>
    <dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId>
    </dependency>
    <!--http相关依赖-->
    <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId>
    </dependency>
    <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId>
    </dependency>
    <!-- redis -->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!--mybatis-plus-->
    <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId>
    </dependency>
    <!--mysql-->
    <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
    </dependency>
    

    配置文件如下,拿去使用记得修改对应的数据库配置

    server:port: 8085servlet:application-display-name: service-ucenter
    spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://IP:3306/guli_college?useUnicode=true&characterEncoding=utf8&useSSL=falseusername: rootpassword: root# 配置 druid 连接池type: com.alibaba.druid.pool.DruidDataSourceredis:host: IPport: 6379database: 0timeout: 1800000mvc:pathmatch:matching-strategy: ant_path_matcher# 开启rest风格hiddenmethod:filter:enabled: true
    
  • 编写 HttpClientUtils 工具类,直接粘过去用

    package com.zym.utils;import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.http.Consts;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.config.RequestConfig.Builder;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.ConnectTimeoutException;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLContextBuilder;
    import org.apache.http.conn.ssl.TrustStrategy;
    import org.apache.http.conn.ssl.X509HostnameVerifier;
    import org.apache.http.entity.ContentType;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.message.BasicNameValuePair;import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLException;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.SSLSocket;
    import java.io.IOException;
    import java.net.SocketTimeoutException;
    import java.security.GeneralSecurityException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;/***  依赖的jar包有:commons-lang-2.6.jar、httpclient-4.3.2.jar、httpcore-4.3.1.jar、commons-io-2.4.jar* @author zhaoyb**/
    public class HttpClientUtils {public static final int connTimeout=10000;public static final int readTimeout=10000;public static final String charset="UTF-8";private static HttpClient client = null;static {PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();cm.setMaxTotal(128);cm.setDefaultMaxPerRoute(128);client = HttpClients.custom().setConnectionManager(cm).build();}public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception{return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);}public static String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) throws ConnectTimeoutException, SocketTimeoutException, Exception{return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);}public static String postParameters(String url, Map<String, String> params) throws ConnectTimeoutException,SocketTimeoutException, Exception {return postForm(url, params, null, connTimeout, readTimeout);}public static String postParameters(String url, Map<String, String> params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,SocketTimeoutException, Exception {return postForm(url, params, null, connTimeout, readTimeout);}public static String get(String url) throws Exception {return get(url, charset, null, null);}public static String get(String url, String charset) throws Exception {return get(url, charset, connTimeout, readTimeout);}/*** 发送一个 Post 请求, 使用指定的字符集编码.** @param url* @param body RequestBody* @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3* @param charset 编码* @param connTimeout 建立链接超时时间,毫秒.* @param readTimeout 响应超时时间,毫秒.* @return ResponseBody, 使用指定的字符集编码.* @throws ConnectTimeoutException 建立链接超时异常* @throws SocketTimeoutException  响应超时* @throws Exception*/public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)throws ConnectTimeoutException, SocketTimeoutException, Exception {HttpClient client = null;HttpPost post = new HttpPost(url);String result = "";try {if (StringUtils.isNotBlank(body)) {HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));post.setEntity(entity);}// 设置参数Builder customReqConf = RequestConfig.custom();if (connTimeout != null) {customReqConf.setConnectTimeout(connTimeout);}if (readTimeout != null) {customReqConf.setSocketTimeout(readTimeout);}post.setConfig(customReqConf.build());HttpResponse res;if (url.startsWith("https")) {// 执行 Https 请求.client = createSSLInsecureClient();res = client.execute(post);} else {// 执行 Http 请求.client = HttpClientUtils.client;res = client.execute(post);}result = IOUtils.toString(res.getEntity().getContent(), charset);} finally {post.releaseConnection();if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {((CloseableHttpClient) client).close();}}return result;}/*** 提交form表单** @param url* @param params* @param connTimeout* @param readTimeout* @return* @throws ConnectTimeoutException* @throws SocketTimeoutException* @throws Exception*/public static String postForm(String url, Map<String, String> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,SocketTimeoutException, Exception {HttpClient client = null;HttpPost post = new HttpPost(url);try {if (params != null && !params.isEmpty()) {List<NameValuePair> formParams = new ArrayList<NameValuePair>();Set<Entry<String, String>> entrySet = params.entrySet();for (Entry<String, String> entry : entrySet) {formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));}UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);post.setEntity(entity);}if (headers != null && !headers.isEmpty()) {for (Entry<String, String> entry : headers.entrySet()) {post.addHeader(entry.getKey(), entry.getValue());}}// 设置参数Builder customReqConf = RequestConfig.custom();if (connTimeout != null) {customReqConf.setConnectTimeout(connTimeout);}if (readTimeout != null) {customReqConf.setSocketTimeout(readTimeout);}post.setConfig(customReqConf.build());HttpResponse res = null;if (url.startsWith("https")) {// 执行 Https 请求.client = createSSLInsecureClient();res = client.execute(post);} else {// 执行 Http 请求.client = HttpClientUtils.client;res = client.execute(post);}return IOUtils.toString(res.getEntity().getContent(), "UTF-8");} finally {post.releaseConnection();if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {((CloseableHttpClient) client).close();}}}/*** 发送一个 GET 请求** @param url* @param charset* @param connTimeout  建立链接超时时间,毫秒.* @param readTimeout  响应超时时间,毫秒.* @return* @throws ConnectTimeoutException   建立链接超时* @throws SocketTimeoutException   响应超时* @throws Exception*/public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)throws ConnectTimeoutException,SocketTimeoutException, Exception {HttpClient client = null;HttpGet get = new HttpGet(url);String result = "";try {// 设置参数Builder customReqConf = RequestConfig.custom();if (connTimeout != null) {customReqConf.setConnectTimeout(connTimeout);}if (readTimeout != null) {customReqConf.setSocketTimeout(readTimeout);}get.setConfig(customReqConf.build());HttpResponse res = null;if (url.startsWith("https")) {// 执行 Https 请求.client = createSSLInsecureClient();res = client.execute(get);} else {// 执行 Http 请求.client = HttpClientUtils.client;res = client.execute(get);}result = IOUtils.toString(res.getEntity().getContent(), charset);} finally {get.releaseConnection();if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) {((CloseableHttpClient) client).close();}}return result;}/*** 从 response 里获取 charset** @param ressponse* @return*/@SuppressWarnings("unused")private static String getCharsetFromResponse(HttpResponse ressponse) {// Content-Type:text/html; charset=GBKif (ressponse.getEntity() != null  && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) {String contentType = ressponse.getEntity().getContentType().getValue();if (contentType.contains("charset=")) {return contentType.substring(contentType.indexOf("charset=") + 8);}}return null;}/*** 创建 SSL连接* @return* @throws GeneralSecurityException*/private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {try {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {@Overridepublic boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {return true;}}).build();SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {@Overridepublic boolean verify(String arg0, SSLSession arg1) {return true;}@Overridepublic void verify(String host, SSLSocket ssl)throws IOException {}@Overridepublic void verify(String host, X509Certificate cert)throws SSLException {}@Overridepublic void verify(String host, String[] cns,String[] subjectAlts) throws SSLException {}});return HttpClients.custom().setSSLSocketFactory(sslsf).build();} catch (GeneralSecurityException e) {throw e;}}
    }
    
  • 编写 controllerservice 代码,处理前端操作,获取二维码信息

    Controller 代码

    /*** 微信扫码登录* @author zym*/
    @RestController
    @CrossOrigin
    @RequestMapping("/wx")
    public class WxLogin {@Resourceprivate MemberService memberServiceImpl;@Resourceprivate RedisTemplate redisTemplate;/*** 向码上登录服务器请求二维码信息* @return*/@GetMapping("/login")public String login(HttpSession session) throws GuLiError {return memberServiceImpl.getQrCode();}
    }
    

    编写 Service 代码,通过 HttpClentUtils 发送 HTTP 请求,得到用户扫码登录的二维码信息

    请求地址为:

    https://server01.vicy.cn/8lXdSX7FSMykbl9nFDWESdc6zfouSAEz/wxlogin/wxLogin/tempUserId?secretKey=你的secretKey

    secretKey 更改为自己刚刚在码上登录创建应用得到的 secretKey

    返回值 codeUrl 里面存放了二维码信息,具体参数如下:

    {"errcode":0,"data":{"qrCodeReturnUrl":"http://login.vicy.cn?tempUserId=18d55e78f66848e781bc7ce65a1fe5b4", "tempUserId":"18d55e78f66848e781bc7ce65a1fe5b4"},"message":"成功"}

    属性类型说明
    qrCodeReturnUrlstring把qrCodeReturnUrl发送给前端生成二维码
    tempUserIdstring该次登录会话的凭证,一个二维码的 tempUserId 在回调的时候会传递给后端
    /*** @author zym*/
    @Service
    public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {@Resourceprivate RedisTemplate redisTemplate;/*** 通过码上登录获取二维码信息* @return*/@Overridepublic String getQrCode() {String codeUrl = null;try {codeUrl = HttpClientUtils.get("https://server01.vicy.cn/8lXdSX7FSMykbl9nFDWESdc6zfouSAEz/wxlogin/wxLogin/tempUserId?secretKey=06a0b50645544c58ba32cb475ae6330a");} catch (Exception e) {e.printStackTrace();}return codeUrl;}
    }
    

前端展示二维码

使用 vue-qriously 利用二维码信息 qrCodeReturnUrl 生成二维码,展示给用户,代码如下

<template><div class="main"><div v-show="!showform"><qriously :value="qrCodeReturnUrl" :size="250"/><font aligen="center">请使用微信扫码登录</font><!-- initQCode: 是你在你的vue实例中定义好的变量   size:是这个Canvas的大小,这里要根据你的视觉稿来决定--></div><!-- 更多登录方式 --><div class="more-sign"><h6>社交帐号登录</h6><ul><li><a id="weixin" class="weixin" target="_blank" @click="getQrCodeReturnUrl()"><iclass="iconfont icon-weixin" /></a></li></ul></div></div></div>
</template><script>import '~/assets/css/sign.css'import '~/assets/css/iconfont.css'import cookie from 'js-cookie'import register from '@/api/register'import Qriously from 'vue-qriously'export default {layout: 'sign',data () {return {loginInfo:{},qrCodeReturnUrl:'',tempUserId:'',showform:true}},methods: {// 获取扫码登录信息getQrCodeReturnUrl(){// 请求刚刚写的控制器 http://localhost:8085/wx/login,可以直接 ajax 异步调用,这里使用 vue-admin 模板作了封装register.getQrCodeReturnUrl().then(response => {if (response.data.errcode === 0){console.log(response.data.data);this.qrCodeReturnUrl = response.data.data.qrCodeReturnUrl;this.tempUserId = response.data.data.tempUserIdthis.showform = false;}})}}
</script>
<style>.el-form-item__error{z-index: 9999999;}
</style>

编写码上登录传递信息给我们的地址

同样在上面的 controller 中添加回调方法,此方法必须是 post 请求类型,接收如下五个参数

属性类型说明
userIdstring用户唯一ID
tempUserIdstring该次会话的凭证
nicknamestring登录用户的昵称(用户授权后,可获得,可能为空)
avatarstring登录用户的头像url(用户授权后,可获得,可能为空)
ipAddrstring登录地点的ip

该方法还需要返回扫码登录状态,码上登录会根据返回的信息在用户手机上提示是否登录成功,返回信息如下,使用 map 封装这两个属性,需要将其转换成 json 格式进行返回

属性类型说明
errcodenumber错误码(0:请求成功)
messagestring接口调用情况描述,如:”成功”

详细代码如下:注意:此方法需要解决跨域问题,我使用了 Getway 网关解决,也可以加上 @CrossOrigin 注解或者其他方式

/**
* 微信登录回调
* @return
*/
@PostMapping("/callback")
@ResponseBody
public String callback(@RequestParam(value = "userId",required = false)  String userId,@RequestParam(value = "tempUserId",required = false) String tempUserId,@RequestParam(value = "nickname",required = false) String nickname,@RequestParam(value = "avatar",required = false) String avatar,@RequestParam(value = "ipAddr",required = false) String ipAddr,HttpServletResponse httpServletResponse) {try {// 判断用户是否第一次登录Member memberById = memberServiceImpl.getById(userId);if (memberById == null) {// 第一次登录,创建用户Member member = new Member();member.setId(userId);member.setNickname(nickname);member.setAvatar(avatar);memberServiceImpl.save(member);memberById = memberServiceImpl.getById(userId);}// 使用 JwtUtils 生成 tokenString token = JwtUtils.getJwtToken(memberById.getId(), memberById.getNickname());// 将用户 token 存放进 redis,键是 tempUserIdredisTemplate.opsForValue().set(tempUserId, token, 1, TimeUnit.MINUTES);HashMap<String, Object> map = new HashMap<>(1);if (userId != null) {map.put("errcode", 0);map.put("message", "登录成功");}Gson gson = new Gson();return gson.toJson(map);} catch (Exception e) {HashMap<String, Object> map = new HashMap<>(1);map.put("errcode", 1);map.put("message", "登录失败");Gson gson = new Gson();return gson.toJson(map);}
}

JwtUtils 如下:

package com.zym.utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.StringUtils;import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Optional;/*** JWT工具类* @author zym*/
public class JwtUtils {public static final long EXPIRE = 1000 * 60 * 60 * 24;public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";public static String getJwtToken(String id, String nickname){String JwtToken = Jwts.builder().setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256").setSubject("guli-user").setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRE)).claim("id", id).claim("nickname", nickname).signWith(SignatureAlgorithm.HS256, APP_SECRET).compact();return JwtToken;}/*** 判断token是否存在与有效* @param jwtToken* @return*/public static boolean checkToken(String jwtToken) {if(StringUtils.isEmpty(jwtToken)) {return false;}try {Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 判断token是否存在与有效* @param request* @return*/public static boolean checkToken(HttpServletRequest request) {try {String jwtToken = request.getHeader("token");if(StringUtils.isEmpty(jwtToken)) {return false;}Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 根据token获取会员id* @param request* @return*/public static String getMemberIdByJwtToken(HttpServletRequest request) {String jwtToken = request.getHeader("guli_token");if(!Optional.ofNullable(jwtToken).isPresent()) {return "";}Jws<Claims> claimsJws =Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);Claims claims = claimsJws.getBody();return (String)claims.get("id");}
}

将本项目打包放到公网服务器上运行

登录码上登录官网,修改之前创建应用的回调 URLcallback 方法的公网请求路径

image-20220629134031603

前端获取登录状态

在之前创建的 controller 中新增 getToken 方法,根据 tempUserId 循环查询 redis 中是否有这个用户的信息,如果有,就将其返回给前端

一段时间后,redis 都没有查询到用户的 token 则视为登录过期,提示用户刷新二维码后重新登录

    /*** 微信登录回调,根据用户 tempUserId 从 redis 中获取 token* @return*/@GetMapping("/getToken/{tempUserId}")public R getToken(@PathVariable String tempUserId) {System.out.println("tempUserId = " + tempUserId);boolean flag = false;for (int i = 0; i < 60; i++) {String token = (String) redisTemplate.opsForValue().get(tempUserId);if (token != null) {return R.ok().setData("token", token);}else {try {sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}}return R.error().setData("message", "登录超时,点击微信图标刷新二维码后重试");}

前端编写 getToken 函数,调用这个 controller 查询登录状态,这里只展示 js 代码

<script>import '~/assets/css/sign.css'import '~/assets/css/iconfont.css'import cookie from 'js-cookie'import register from '@/api/register'import Qriously from 'vue-qriously'export default {layout: 'sign',data () {return {loginInfo:{},qrCodeReturnUrl:'',tempUserId:'',showform:true}},methods: {// 获取扫码登录信息getQrCodeReturnUrl(){register.getQrCodeReturnUrl().then(response => {if (response.data.errcode === 0){console.log(response.data.data);this.qrCodeReturnUrl = response.data.data.qrCodeReturnUrl;this.tempUserId = response.data.data.tempUserIdthis.showform = false;// 调用 getToken 函数this.getToken();}})},// 获取扫码登录用户tokengetToken(){// 请求后端刚刚写的控制器 http://localhost:8085/wx/getToken/这里是tempUserId ,查询这个二维码的登录信息register.getToken(this.tempUserId).then(response => {// 成功获取到登录信息,则将用户 token 保存到 cookie 中,并跳转到网站首页if (response.data.status === true) {console.log(response.data.data);cookie.set("token", response.data.data.token);this.$router.push("/");} else {// 获取用户信息超时的逻辑请自己编写}})}},}
</script>

注意:这里使用jwt做单点登录,你也可以直接存储用户信息


http://chatgpt.dhexx.cn/article/HR0qlZ1M.shtml

相关文章

深度解读企业微信与个人微信的区别?

收到我们售前服务团队同事的反馈&#xff0c;很多老板或运营小伙伴并不是很清楚个人微信与企业微信具体有哪些本质区别&#xff0c;很多人还停留在企业微信只是作为OA办公打卡工具的认知内。 今天我们将从11个要点28个细分点来聊一聊企业微信作为私域流量运营必备工具&#xff…

个人小程序申请微信支付

个人小程序如何申请微信支付功能&#xff1f; 给你们看一下效果 一、准备材料 ① 个体户营业执照 1️⃣可以去当地 工商局办理&#xff0c;免费&#xff08;一般提供一个地址&#xff0c;提供3张身份证复印件&#xff09; 2️⃣可以去淘宝叫人代理办理&#xff0c;收费&…

VC/MFC 检查指定的文件是否存在 判断文件是否存在

#include <iostream> #include <windows.h> #include <tchar.h>/*功能: 检查指定的文件是否存在编译环境: VS2017, 字符集可随意切换 */// 函数功能: 检查指定的文件是否存在, 文件存在则返回 TRUE, 不存在则返回 FALSE // LPCTSTR lpszFile 要检查的文件的绝…

html 判断本地文件存在,javascript怎么判断文件是否存在?

javascript怎么判断文件是否存在&#xff1f;下面本篇文章就来给大家介绍一下利用javascript判断文件是否存在的方法&#xff0c;希望对大家有所帮助。 在JavaScript中&#xff0c;可以通过ActiveXObject对象判断本地文件路径来判断本地文件是否存在&#xff0c;网络文件通过判…

matlab怎么分析数据,MATLAB应用——数据分析与统计

数学建模是用数学方法解决各种实际问题的桥梁,它已经渗透到各个领域,而且发挥出越来越重要的作用。面对自然科学和工程应用中的难题,大部分人无从入手,而个别人却能短时间内给出切实可行的解决方案,其差别往往在于驾驭数学知识的能力不同。现代计算机技术的应用不仅减少了…

大数据分析那点事

写在前文&#xff0c;首先声明博主对数据分析领域也在不断学习当中&#xff0c;文章中难免可能会出现一些错误&#xff0c;欢迎大家及时指正&#xff0c;博主在此之前也曾对不同量级、不同领域的数据进行过分析&#xff0c;但是在过程中总是感觉有许多困惑&#xff0c;即自己也…

【python与数据分析】Python与数据分析概述

目录 一、认识数据分析 1、数据分析的方法论与数据分析方法 &#xff08;一&#xff09;七何分析法——建立框架 &#xff08;二&#xff09;演绎树分析法——问题分层 &#xff08;三&#xff09;PEST分析法——设计环境 &#xff08;四&#xff09;金字塔原理分析法——…

2022年10个最佳地理空间数据分析 GIS 软件

数据可视化并不是简单的把数据变成图表, 而是以数据为视角看待世界。换言之&#xff0c;数据可视化的客体是数据&#xff0c;但我们往往想要的其实是数据视觉&#xff0c;以数据为工具&#xff0c;以可视化为手段&#xff0c;目的是描述真实&#xff0c;探索世界。GIS 就是这样…

数据分析报告编写规范

Ⅰ、数据分析报告编写规范 - 资料来源&#xff1a;百度文库 一份专业的数据分析报告&#xff0c;除了图表化呈现数据分析结果&#xff0c;还需要介绍此项分析的背景/目的&#xff0c;通过此次分析得到结论&#xff0c;以及结合业务知识给出的建议。在做数据报告之前&#xff0…

python数据分析常用图大集合

我们在做数据分析的时候&#xff0c;难免会用到图像来表示你要展示的东西&#xff0c;接下来写一下demo来表示一下各种图&#xff1a; 以下默认所有的操作都先导入了numpy、pandas、matplotlib、seaborn import numpy as np import pandas as pd import matplotlib.pyplot as…

数据分析自学路线

首先必须要对想要自学数据分析的朋友表示敬佩&#xff01;数据分析是个很庞大的学科体系&#xff0c;零零碎碎的知识点可能一辈子都学不尽&#xff0c;敢自学挑战的一定是个学习力和行动力超强的人&#xff01; 作为一个非科班转型的初级数据分析师&#xff0c;常有身边朋友问…

Python数据分析常用的类库

本节只对这些库进行一个简单介绍。 1. NumPy NumPy&#xff08;Numerical Python&#xff09;是 Python 科学计算的基础包&#xff0c;它可以提供以下功能。口快速高效的多维数组对象 ndarray。 口用于对数组执行元素级计算和直接对数组执行数学运算的函数。口用于读写硬盘…

10 个最佳地理空间数据分析 GIS 软件

有人说&#xff1a;一个人从1岁活到80岁很平凡&#xff0c;但如果从80岁倒着活&#xff0c;那么一半以上的人都可能不凡。 生活没有捷径&#xff0c;我们踩过的坑都成为了生活的经验&#xff0c;这些经验越早知道&#xff0c;你要走的弯路就会越少。 数据可视化并不是简单的把…

云计算机平台的特性,云平台对比传统平台特点分析

云计算的一个核心理念就是通过不断提高“云”的处理能力来减少用户终端的处理负担,最终使用户终端简化成一个单纯的输入输出设备,并能够按需享受“云”的强大计算能力。 而云计算平台与传统应用模式相比,具有如下特点。 1、虚拟化技术 现有的云计算平台的最大的特点是利用软…

什么是SAP Cloud Platform(SAP云平台) ?

1. 引言 SAP Cloud Platform (SCP) 是SAP目前主推的一个发展方向&#xff0c;从2012年SAP HANA Cloud Portfolio到后来的SAP HANA Cloud Platform&#xff0c;再到2017年SAP Cloud Platform的发布&#xff0c;SAP的云平台经过了一系列的演化过程。 在讨论SCP这一技术时&#…

云计算机是什么原理,云电脑的运行原理是什么?

大家好&#xff0c;这里是酷乐米小编龙牧&#xff0c;达龙云电脑这样的云游戏平台时什么原理来实现让玩家性能不是很好的电脑可以运行大型游戏呢&#xff1f; 这里就要说下云游戏的概念了&#xff0c;云游戏是以云计算为基础的游戏方式&#xff0c;在云游戏的运行模式下&#x…

云测试是什么?

云测&#xff08;Cloud Testing&#xff09;&#xff0c;是基于云计算的一种新型测试方案&#xff0c;服务商提供多种平台&#xff0c;多种浏览器、移动设备、服务器的平台&#xff0c;一般的用户在本地用自动化测试框架&#xff08;Appium、Selenium、Airtest等&#xff09;把…

物联网云平台概念及系统架构

物联网云平台概念 联动感知层和应用层的中枢系统&#xff0c;功能与价值凝聚的PaaS软件 物联网云平台是由物联网中间件这一概念逐步演进形成。简单而言&#xff0c;物联网云平台是物联网平台与云计算的技术融合&#xff0c;是架设在IaaS层上的PaaS软件&#xff0c;通过联动感知…

容器云平台详细介绍

前言 容器是一种轻量级、可移植、自包含的软件打包技术&#xff0c;使应用程序可以在几乎任何地方以相同的方式运行。开发人员在自己笔记本上创建并测试好的容器&#xff0c;无需任何修改就能够在生产系统的虚拟机、物理服务器或公有云主机上运行。“从过去以物理机和虚拟机为…

什么是PaaS云平台?

什么是PaaS云平台&#xff1f; PaaS是&#xff08;Platform as a Service&#xff09;的缩写&#xff0c;是指平台即服务。把服务器平台作为一种服务提供的商业模式&#xff0c;通过网络进行程序提供的服务称之为SaaS(Software as a Service)&#xff0c;而云计算时代相应的服务…