ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python+Flask实现手机号识别微信性别:微信授权与数据落库全解析

Python+Flask实现手机号识别微信性别:微信授权与数据落库全解析 简介针对通过手机号识别微信性别这一需求提供了一套基于Python与uiautomator的实例脚本方案。脚本封装了getGender方法调用微信搜索后自动提取性别字段并对“用户不存在”“账号状态异常”“未设置性别”等分支做了监控处理同时附有Excel读写与追加写入功能便于对结果进行分表保存和查看。整个资源以单个PDF文档呈现大小仅51KB方便收藏与离线阅读。已有1394人学习适合有Python基础、希望借助自动化工具完成微信端信息识别的开发者参考也可作为uiautomator界面自动化调用微信的入门示例。该方案通过模拟界面操作获取信息不修改微信客户端底层逻辑代码结构清晰关键步骤附有说明PDF中包含了从手机号列表导入、逐条查询到结果分sheet写入Excel的完整流程可快速迁移到实际任务中。1. “手机号识别微信性别”这个需求先得把话说明白先说个我接到过的真实需求某业务方找到我说想做个功能——客户把手机号填进来系统自动识别出这个号码对应的微信性别用于用户画像打标。乍一听好像是个很常规的需求但干过微信生态开发的人都知道微信官方从来没有开放过“手机号反查用户性别”这种接口。手机号本身只是一串号码它不携带任何性别信息微信也不会允许你输入任意手机号就拉取到对应的微信资料。那标题里说的“通过手机号识别出对应的微信性别”还能不能做能。只是真正的技术实现路径不是“反查”而是“正向授权”——你的用户主动走进你的小程序或公众号完成手机号授权和微信资料授权你的后端才能合法拿到这个人在微信侧填写的性别字段再和手机号做绑定存储。这一步做完以后再遇到同一个手机号你不需要再次询问微信直接从自己的库里就能查到性别。所以这篇文章要讲的实例代码本质上是一套微信生态内的正规授权数据链路从小程序端拿到手机号验证码换取用户手机号再通过用户授权拿到微信资料中的性别字段最后落库形成“手机号 - 微信性别”的映射。适合正在做小程序用户体系、会员画像、私域用户标签系统的开发者参考也适合刚入门微信开发的人理解整个授权流程的数据走向。整个过程我会给出一份可直接运行的 PythonFlask后端实例包含微信登录凭证校验、手机号快速验证组件解析、用户资料性别字段存取以及最终的查询封装。代码不复杂但链路比较长很多人就是死在链路中的某一个环节上。2. 合规前提下性别信息到底从哪里来整套数据链路设计2.1 微信侧到底提供了哪些获取性别的正规入口在写代码之前必须先把数据来源搞清楚。微信生态内开发者能合法拿到用户性别字段的途径并不多我梳理了一下常用的几个微信小程序用户资料授权用户通过button open-typegetUserProfile或新版头像昵称填写能力同意授权后开发者可以获得昵称、头像、性别gender等公开资料。性别用数字表示1代表男性2代表女性0代表未知。微信公众号网页授权用户通过 OAuth2.0 授权后调用sns/userinfo接口可以拿到用户的性别、昵称、头像、所在城市等信息同样依赖用户点击“同意授权”。微信开放平台网站应用扫码登录用户在第三方网站扫码并授权后可以获取相同的用户资料字段适合 PC 端场景。这三个入口的共同特点是用户主动授权开发者才能拿性别。它们解决的问题都是“拿到数据”但都不是“输入手机号就能查性别”。那手机号怎么和性别打通真正的桥梁是手机号授权组件。微信小程序现在的标准做法是用户在页面上点击“手机号快速验证”按钮微信弹出授权框用户确认后小程序获取到一个动态 code把 code 传给后端后端调用微信服务端接口换取到这个微信号绑定过的真实手机号。如果你的业务同时让用户完成了资料授权那么在同一套用户体系里手机号和性别就能自然关联起来了。2.2 一句话说清完整流程正向授权 数据落库说穿了这套系统的数据链路就是一个“注册 / 登录”流程的变体用户进入小程序点击“微信一键登录”前端用wx.login()获取临时code。用户点击“手机号快速验证”按钮前端拿到phoneCode。用户点击“获取头像昵称/授权性别”按钮前端拿到userInfo包含 gender。前端把三个凭证一次性发给后端/api/login。后端先用code调用jscode2session接口换取openid和session_key。后端再用phoneCode调用getuserphonenumber接口解析出纯手机号。后端把openid、手机号、性别等信息写入数据库完成绑定。以后任何业务要查“手机号对应的性别”直接查自己的库即可不再需要微信参与。说到这里可能有人会问为什么不直接用getUserProfile拿到的性别而是还要绕一圈手机号因为getUserProfile返回的性别只是“这一次授权时的快照”如果你不在用户授权那一刻记录下来之后没任何接口能补查。而手机号是稳定的用户标识把手机号和性别绑定后才真正实现了“通过手机号识别微信性别”这个业务目标。2.3 为什么不能反查微信接口权限边界很多不熟悉微信开放平台的开发者会有一个惯性思维既然微信有那么多 API那一定存在一个“传入手机号返回用户资料”的接口。抱歉这套东西在微信生态里是不存在的而且在未来可见的范围内也不会存在因为它直接冲击个人隐私保护的基本规则。微信开放的所有用户数据接口都建立在“用户主动授权”这个前提下。哪怕你是拥有高级接口权限的服务商也拿不到“任意手机号 - 用户性别”这种映射能力。所以如果你是在给自己公司的业务做内部工具务必走正规模板让用户在首次进入时完成一次授权闭环后面的路就都能走通了。如果想要在业务上线前做测试可以用自己的微信号配合测试号即“体验成员”的身份或在小程序后台添加体验者走完整流程验证。3. 可直接跑的 Python 实例从授权收回到性别落库3.1 环境准备与必要参数写代码之前先把环境梳理清楚。我这边的运行环境是 Python 3.10 Flask 2.3 requests数据库用 SQLite 做演示生产环境建议换成 MySQL 或 PostgreSQL。你没有看错这套代码最核心的依赖就是flask和requests两个库没有其他花哨的第三方包。你需要提前准备好以下参数参数来源说明APPID微信公众平台 - 小程序 - 开发管理 - 开发设置小程序唯一标识SECRET同页面小程序密钥注意不要泄露到前端TOKEN自己生成的随机字符串用于颁发给前端自定义登录态提示如果还没有小程序账号去微信公众平台注册一个小程序类目可以临时选“工具 效率”个人主体也能注册。注册后进入“开发管理 - 开发设置”页面就能看到 APPID 和 SECRET。安装依赖的命令也很简单pip install flask requests3.2 核心后端代码完整的 login 接口下面这份代码是整个实例的主干。我把注释写得比较详细因为这套流程里每一步的输入输出都容易让人晕头转向。import json import sqlite3 import uuid import requests from flask import Flask, request, jsonify app Flask(__name__) # 微信小程序配置 APPID 你的小程序APPID SECRET 你的小程序SECRET # SQLite 初始化 DB_PATH wechat_gender.db def init_db(): conn sqlite3.connect(DB_PATH) c conn.cursor() # 用户主表存储 openid、手机号、性别等核心字段 c.execute( CREATE TABLE IF NOT EXISTS user ( id INTEGER PRIMARY KEY AUTOINCREMENT, openid TEXT UNIQUE NOT NULL, phone TEXT UNIQUE NOT NULL, gender INTEGER DEFAULT 0, nickname TEXT DEFAULT , avatar TEXT DEFAULT , create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ) # 自定义登录态表sid即session id前端每次请求带上即可识别用户 c.execute( CREATE TABLE IF NOT EXISTS user_session ( sid TEXT PRIMARY KEY, openid TEXT NOT NULL, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ) conn.commit() conn.close() # 获取微信接口调用凭证 access_token # 注意access_token 有效期为7200秒生产环境必须做缓存不能每次都请求 def get_access_token(): url https://api.weixin.qq.com/cgi-bin/token params { grant_type: client_credential, appid: APPID, secret: SECRET } resp requests.get(url, paramsparams, timeout5).json() if access_token in resp: return resp[access_token] raise Exception(f获取 access_token 失败: {resp}) # 小程序登录凭证校验code 换取 openid def code2openid(code): url https://api.weixin.qq.com/sns/jscode2session params { appid: APPID, secret: SECRET, js_code: code, grant_type: authorization_code } resp requests.get(url, paramsparams, timeout5).json() if openid in resp: return resp[openid] raise Exception(fcode2openid 失败: {resp}) # 手机号快速验证phone_code 换取真实手机号 def get_phone_number(phone_code, access_token): url https://api.weixin.qq.com/wxa/business/getuserphonenumber params {access_token: access_token} data {code: phone_code} resp requests.post(url, paramsparams, jsondata, timeout5).json() if resp.get(errcode) 0: return resp[phone_info][purePhoneNumber] raise Exception(f获取手机号失败: {resp}) # 登录接口前端一次性提交三个凭证 app.route(/api/login, methods[POST]) def login(): body request.get_json() code body.get(code) # wx.login() 返回的登录凭证 phone_code body.get(phone_code) # 手机号快速验证组件返回的 code user_info body.get(user_info) # 用户授权资料含 gender if not code or not phone_code or not user_info: return jsonify({code: 400, msg: 缺少必要参数}), 400 # Step 1: code 换 openid openid code2openid(code) # Step 2: phone_code 换手机号 access_token get_access_token() phone get_phone_number(phone_code, access_token) # Step 3: 从用户资料里取性别 gender int(user_info.get(gender, 0)) nickname user_info.get(nickName, ) avatar user_info.get(avatarUrl, ) # Step 4: upsert 用户数据 conn sqlite3.connect(DB_PATH) c conn.cursor() c.execute( INSERT INTO user (openid, phone, gender, nickname, avatar) VALUES (?, ?, ?, ?, ?) ON CONFLICT(openid) DO UPDATE SET phoneexcluded.phone, genderexcluded.gender, nicknameexcluded.nickname, avatarexcluded.avatar , (openid, phone, gender, nickname, avatar)) conn.commit() # Step 5: 生成自定义登录态 sid后续请求可凭 sid 识别用户 sid uuid.uuid4().hex c.execute(INSERT INTO user_session (sid, openid) VALUES (?, ?), (sid, openid)) conn.commit() conn.close() # Step 6: 把“手机号-性别”映射结果返回给前端 return jsonify({ code: 0, msg: ok, data: { sid: sid, phone: phone, gender: gender, gender_text: 男 if gender 1 else (女 if gender 2 else 未知) } }) # 查询接口通过手机号识别微信性别 app.route(/api/query_gender, methods[POST]) def query_gender(): body request.get_json() phone body.get(phone) if not phone: return jsonify({code: 400, msg: 缺少手机号}), 400 conn sqlite3.connect(DB_PATH) c conn.cursor() c.execute(SELECT phone, gender, nickname FROM user WHERE phone ?, (phone,)) row c.fetchone() conn.close() if not row: return jsonify({code: 404, msg: 该手机号尚未完成微信授权绑定, data: None}), 404 gender row[1] return jsonify({ code: 0, msg: ok, data: { phone: row[0], gender: gender, gender_text: 男 if gender 1 else (女 if gender 2 else 未知) } }) if __name__ __main__: init_db() app.run(host0.0.0.0, port5000, debugTrue)这段代码就是你所要的“实例代码”核心。它做了三件事授权登录、数据绑定、查询映射。前端的 wx.login、手机号快速验证、用户信息授权这三件事做完后把所有凭证 POST 到/api/login即可。3.3 小程序前端关键代码怎么把三个凭证凑齐后端写得再好前端不配合也跑不通。这里给出小程序端关键页面的核心片段同样贴注释。// pages/login/login.js Page({ data: {}, onLoad() { // 1. 先静默登录拿 code wx.login({ success: (res) { this.setData({ code: res.code }); } }); }, // 2. 用户点击“手机号快速验证”按钮 onGetPhone(e) { this.setData({ phone_code: e.detail.code }); }, // 3. 用户点击“授权资料”按钮这里用新版 getAppBaseInfo 之前的传统 getUserProfile 写法 onGetUserProfile() { wx.getUserProfile({ desc: 用于完善会员资料, success: (res) { this.setData({ user_info: res.userInfo }); this.submitLogin(); } }); }, // 4. 三个凭证集齐后一次性提交后端 submitLogin() { const { code, phone_code, user_info } this.data; if (!code || !phone_code || !user_info) { wx.showToast({ title: 请先完成授权, icon: none }); return; } wx.request({ url: https://你的域名.com/api/login, method: POST, data: { code, phone_code, user_info }, success: (res) { if (res.data.code 0) { wx.setStorageSync(sid, res.data.data.sid); wx.showToast({ title: 绑定成功, icon: success }); } else { wx.showToast({ title: res.data.msg, icon: none }); } } }); } });对应的 wxml 里要放两个按钮一个是open-typegetPhoneNumber绑定的手机号验证按钮一个是点击后触发getUserProfile的授权按钮。需要注意wx.getUserProfile从基础库 2.27.1 开始在部分版本上有新的调整实际开发时建议做能力判断如果接口不存在就退回用头像昵称填写能力。4. 把“手机号 - 性别”的查询闭环打通缓存与“第二次就秒回”4.1 生产环境必须做的三件优化演示代码能跑但离生产可用还有距离。回看我们刚才实现的流程每次调用/api/login时都会调用一次get_access_token()而微信官方限制 access_token 的获取频率是每天 2000 次每次有效期只有 7200 秒。如果用户量稍大这种每次请求都拉取 token 的写法会直接写爆接口限额。生产环境的正确做法是把 access_token 缓存到 Redis 或本地文件里过期再刷新。逻辑很简单import time import json TOKEN_CACHE_FILE access_token_cache.json def get_access_token_with_cache(): try: with open(TOKEN_CACHE_FILE, r) as f: cache json.load(f) if cache[expire_time] time.time(): return cache[access_token] except Exception: pass access_token get_access_token() with open(TOKEN_CACHE_FILE, w) as f: json.dump({ access_token: access_token, expire_time: time.time() 7000 # 提前200秒过期 }, f) return access_token另外两处优化是登录接口加幂等校验和服务端缓存查询结果。幂等校验是指同一个code或phone_code不能重复使用微信侧的 code 是一次性的重复提交必然报错所以前端要控制请求不能重复发送查询结果的缓存是指在/api/query_gender中如果一个手机号已经查过一次性别完全可以用 Redis 以phone:gender为 key 缓存起来默认查库即可秒回。4.2 当用户拒绝授权时怎么办微信的授权流程最大的变数就是用户点不点“允许”。即使你的前端写得再流畅也会遇到用户拒绝手机号授权或者拒绝资料授权的情况。而且注意一个细节手机号快速验证和 getUserProfile 是两套独立授权用户可能同意手机号但拒绝性别资料授权。我在实际项目里遇到这类情况处理方案是把性别设置为“未知”并允许用户后续在个人中心里手动补全。很多业务对性别的要求不是强制的用户拒绝权限时后台自动记录 gender0然后给用户一个“完善资料”的入口。等用户下次主动点了授权再更新信息。更稳妥的做法是在用户进入页面时给出明确的授权引导文案告诉用户性别字段用于个性化推荐让用户理解授权目的。这个文案虽然看着不起眼但在审核和用户体验双重维度上都很关键。4.3 防沉迷于“性别识别”数据的归属权与使用边界业务做到后面你会拥有一个“手机号 性别”的映射表。这本质上属于用户授权数据的二次加工结果不是你自己凭空产生的数据。在使用边界上必须格外小心只能在你的业务场景内部使用不能向第三方出售或共享这份映射表。用户注销账号或要求删除数据时需要能一键清除手机号、openid、性别等所有字段。在小程序提审时如果涉及用户信息收集需要在小程序后台声明收集和使用目的。我在第一次做类似功能的时候就因为没有在主隐私协议里写明“会记录性别”被审核打回了一次。后来把文案调整成“用于完善会员资料与内容推荐”同时在代码里提供user/delete接口才顺利过审。这些都是血泪教训提前写进需求文档里能省不少事。5. 实战排错记录与合规红线5.1 高频报错对照表把代码写完只是第一步联调阶段才是真正掉头发的时候。我把自己踩过以及带过的团队踩过的坑整理成一张对照表各位可以直接对着排查报错或现象根本原因解决方案errcode: 40029, errmsg: invalid code前端传的 code 已被使用或已过期每次 wx.login 必须重新生成 code且一个 code 只能换一次 openiderrcode: 41002, errmsg: appid missing请求参数少了 appid或者 APPID 配置错误检查小程序后台的 APPID 是否与代码中一致errcode: 40001, errmsg: invalid credentialaccess_token 失效或与 appid 不匹配检查 token 是否被 Redis 缓存过期或是否用错 appid 的 secretgetuserphonenumber返回errcode: 48001接口权限未开通或小程序类目不符小程序后台-开发-开发管理-接口设置确认“手机号快速验证”权限已开通前端 wx.getUserProfile 不弹窗基础库版本过低或接口被废弃升级基础库或改用新版头像昵称填写能力用户进入页面后性别一直为 0用户拒绝授权或前端没有把 user_info 传给后端增加“完善资料”入口主动请求补录这六个坑覆盖了我见过的 80% 的联调失败场景。特别是手机号快速验证的 48001 报错很多新人第一次遇到会以为是代码写错了其实是小程序类目和权限没配置好需要在微信公众平台后台确认。5.2 关于手机号与性别的隐私合规红线最后必须多说几句。到处有人在问“能不能输入手机号直接查微信性别”“手机号查 QQ”“手机号查微博”之类的问题这些方向天然带着黑产和社工库的属性。作为一个写过这套代码的开发者我可以明确地讲凡是绕过用户授权去获取用户身份信息的行为都是违规的也是不可持续的。微信生态的接口权限和数据风控不是摆设一旦发现异常调用模式轻则接口权限被收回重则小程序被下架封禁。我们的正确姿势只有一种让用户主动走进来在清楚知晓的前提下授权我们对数据负责只用于合理业务支持用户删除不私下沉淀、不出售、不提供给任何未经授权的第三方。这套规则不仅是平台要求的红线也是一名开发者该有的职业底线。5.3 后续还能怎么扩展这套基于手机号和微信性别的数据链路打通之后能做的事情其实不少。我自己的一个客户在此基础上扩展了会员等级体系用户授权后系统把gender和phone结合订单数据做消费偏好分析给用户打上“男性用户偏好数码/女性用户偏好美妆”之类的营销标签。注意这里的数据来源是业务行为而不是单纯依赖微信返回的性别字段两者相互补充画像才更完整。另外如果你有多个小程序或公众号可以通过微信开放平台把它们绑定到同一个账号下用 UnionID 机制统一不同应用中的同一用户身份。这样用户在小程序 A 授权了手机号在小程序 B 里就能直接通过 UnionID 识别为同一人不需要让用户重复授权体验能提升一大截。不过这个需要稍微复杂的账号体系设计代码里要加一张 unionid 映射表这是一个不错的进阶方向。本文还有配套的精品资源点击获取
返回列表