基于Inspeckage的安卓APP抓包逆向分析——以步道乐跑APP为例

article/2025/8/26 10:00:50

引言:本人最近稍微弄懂了inspeckage的用法,特在此以步道乐跑APP为例,较详细记录地记录APP抓包与简单的逆向分析过程,用于备忘与共同学习!另外,温馨提醒,本文图片较多,建议连接WiFi阅读!

目录:

一、准备工作

1、需要用到的APP

2、安装与配置

二、开始抓取数据

1、Inspeckage监测

2、HttpCanary抓取

三、数据分析

1、HttpCanary数据部分

2、Inspeckage数据部分

四、代码实现(Python) 

1、AES-CBC-PKCS5加解密

2、md5加密

3、请求数据构建

4、发送请求与解析响应

5、总代码(包括其他接口与其他数据)


正文:

一、准备工作

1、需要用到的APP

  • VMOS Pro
  • HttpCanary
  • JustTrustMe
  • Inspeckage

已经在蓝奏云安排上了,请自行下载!

链接:

https://huanxingke.lanzoui.com/b02069isj

密码:

lptiyu

2、安装与配置

(1)VMOS Pro的配置

Ⅰ、安装在真机上;

Ⅱ、本人为了更好的效果开了会员,用的是下图的虚拟机:

Ⅲ、成功加载虚拟机并打开后,会看到如下页面,点击文件传输:

Ⅳ、点击我要导入:

Ⅴ、点击安装包,选中Inspeckage和JustTrustMe,确认后将自动安装:

Ⅵ、安装步道乐跑:先在真机上安装步道乐跑APP,然后还是点击我要导入 --> 应用 --> 找到步道乐跑 --> 确认安装;

Ⅶ、然后回到主页,点击进入Xpose:

Ⅷ、点击左上角三杠 --> 模块 --> 选中Inspeckage和JustTrustMe模块,然后重启虚拟机以激活模块:

Ⅸ、重启虚拟机后,JustTrustMe模块已默认激活成功,然后配置Inspeckage:进入Inspeckage,当显示Module enable和Server start时,初始化成功,如下图:

(2)HttpCanary的配置

Ⅰ、安装在真机上;

Ⅱ、打开HttpCanary,点击左上角三杠 --> 点击左下角设置 --> 点击SSL证书设置,如图:

Ⅲ、点击安装证书,如图,然后按提示进行:

Ⅳ、返回上一页面,选择目标应用,如图:

Ⅴ、点击右上角+号,选择VOMS Pro,如图,注意不要选择其他应用,以免干扰:

至此,准备工作完成,准备开始抓取数据。

 

二、开始抓取数据

1、Inspeckage监测

(1)首先,请先在步道乐跑APP上登录好你的账号,然后退出;

(2)进入Inspeckage,按下图选择监测步道乐跑APP:

(3)选择好之后,保留虚拟机在后台运行,回到真机浏览器,输入127.0.0.1:8008,若看到如下界面,则配置初步成功,注意此时App is running为false,左上角开关为OFF:

(4)保留真机浏览器在后台,不要关闭,然后进行下一步;

2、HttpCanary抓取

(1)打开HttpCanary,点击右下角小飞机,小飞机变绿代表抓包开始;

(2)然后直接返回,注意不要清理后台,调出虚拟机,此时HttpCanary将会驻在屏幕右下角位置,如图,然后点击LAUNCH APP:

(3)此时Inspekage将会唤醒步道乐跑APP,抓包与监测工作均将开始,如图,可看到HttpCanary已有抓包数据:

(4)然后点击真机的方框导航键(手势导航的是按住屏幕底部上滑),调出真机浏览器后,刷新一下刚才的页面,如果App is running为true则监测成功,此时打开左上角开关,就可以获取监测的数据了,成功界面如图所示:

至此,抓包与监测工作均已开始并已经获取到步道乐跑APP启动后的网络请求数据,可以开始分析数据了。

 

三、数据分析

1、Httpcanary数据部分

(1)全屏打开HttpCanary,可以看到已经抓取到很多请求了,先拉到最底部,从最开始的请求寻找起,看有没有比较特别的、可能符合我们需要的请求;

(2)如下图,可以发现有一个请求含有Login关键词,我们可以下意识地想到:这可能是跟用户登录有关的请求,这在APP抓包上还是挺重要的一部分:

(3)那我们点击打开这一请求,点击请求 --> 点击右下角预览,如图:

(4)我们可以看到有几个值得我们留意的字段:token、access_token、refresh_token、timestamp、nonce、jpush_id、sign:

Ⅰ、前三者均为token类字段,按照经验,此类字段一般是由服务器生成的,所以我们暂时先不考虑;

Ⅱ、timestamp为时间戳,nonce为随机字符串,均是起防止重放攻击作用的,可以不予考虑(见博主@koastal的博文:https://blog.csdn.net/koastal/article/details/53456696);

综上,最值得我们考虑的就是sign值了——其实我们一开始就应该特别留意到这个sign值了,因为这是很常用的加密算法的字段,并且我们还可以发现它与md5加密后的格式十分相似,先默默记下来;

(5)然后我们再看一下响应吧,如图:

(6)很明显,响应中的data值为base64编码,但当我们拿去解密的时候,得到的是乱码:

¶"Z¥ÆÍǠЩ<í/ÅtlÎÝοaó±8Êã½BV-0ÃúCÃæOÒ;Çÿ(^ò±°Î?t(:t1ÂTº	ådä0ãùºÆ^Ü~.KÝÜ[õõ»9+ÕI5ùÄs©îÁ^Çw[Ï8
Ïϼ#>,ÌeÔPÅ¿Vú2Êç7ZzÇF£ÙÈÊn©

所以很显然,这个字段在base64之前就已经被加密过一次了,这便应当引起我们的兴趣了;

得到了以上数据之后,我们便可以去Inspeckage网页上寻找对应加密方法了。

2、Inspeckage数据部分

(1)回到Inspeckage网页,我们需要知道,网页上的Crypto(一般是签名算法,如AES)和Hash(哈希算法,如md5)是我们寻找加密方法的来源;

(2)我们先看一下Crypto里的数据吧,点击Crypto,如图(温馨提示:请先把左上角的开关关闭为OFF再来分析数据哦,否则网页的动态变化会影响我们的数据寻找过程哦):

(3)我们可以看到已经监测到很多数据了,在上面已经说到了sign可能是md5加密的,也就是Hash,所以我们先不在Crypto里寻找sign,而是先寻找data值,那么要怎么寻找呢:

Ⅰ、根据请求顺序寻找:我们知道data值是包含login字段请求的响应,而此请求在HttpCanary中属于最早发送的一批请求,那我们便应该在Inspeckage网页上也拉到最底部来寻找;

Ⅱ、使用浏览器自带的查找功能,如图:

然后输入data值来匹配寻找即可,注意:只需要复制data值开头的几位字符来寻找即可,因为页面是显示不完全的,如果使用整个data值来匹配,反而找不到结果;

(4)由(3)中的方法,我们成功找到了data的加密算法,如图:

放大后:

将它复制下来就更明显了:

(为了保护隐私, 部分数据使用*号代替)
SecretKeySpec(Wet2C8d34f62ndi3,AES) , Cipher[AES/CBC/PKCS5Padding] IV: K6iv85jBD8jgf32D (tiJapcbNx6AL0JmpPO0VL8V0bM7dEc4dvwth87E4HMrjE
L1CVi0ww5qO+kPD5k8L0jvH/xooXvKxsADOP5x0KAsSOpV0McJUugnlZOQwm+P5usZe3H4uS93cW/X1uzkQK4jVSY0eNfnEG3Op7hDBAl6PjccMd1uVzzgNz88VvCM+LMxl1FDFv1b6MsoC5zdaesdGoxiP******** , {"uid":"*******","access_token":"333C877C9429E26D4FCDC404******","refresh_token":"CC304EDBA40FF2F2AEA2D28C******","refresh_expire":1623509738})

也就是说data进行base64前的加密算法为AES-CBC对称算法,字符串使用的是PKCS5Padding格式,其中SecretKey值为:Wet2C8d34f62ndi3,偏移量iv为K6iv85jBD8jgf32D,加密前的字符串为:

{"uid":"*******","access_token":"333C877C9429E26D4FCDC404******","refresh_token":"CC304EDBA40FF2F2AEA2D28C******","refresh_expire":1623509738}

data值成功破译!

(5)按照同样的方法,我们点击Hash部分来尝试破译sign值:

(6)这里有个小技巧,因为网页默认是不完整显示的,所以会导致某些值看不到,这是我们可以点击网页里的一些>>符号可以将其展开完全显示,避免匹配失败:

(7)不出意外,sign值算法与加密前的字符串也被我们找到了:

复制下来:

Algorithm(MD5) [access_token006C31A39AED1ECAAA28C32554******jpush_id1507bfd3f7684******mobileDeviceId185818969******mobileModelBRQ-AN00
mobileOsVersion7.1.2nonce320975ostype1refresh_token9EF86DB536CEB764B430EC2BA4******school_id***student_num******timestamp1620917736token006C31A39AED1ECAAA28C325****uid******version86version_name3.3.6rDJiNB9j7vD2 : 7aeb494fc0063ec5c60cfd7ef8373929]

所以果然是md5加密!加密前的字符串为:

access_token006C31A39AED1ECAAA28C32554******jpush_id1507bfd3f7684******mobileDeviceId185818969******mobileModelBRQ-AN00
mobileOsVersion7.1.2nonce320975ostype1refresh_token9EF86DB536CEB764B430EC2BA4******school_id***student_num******timestamp1620917736token006C31A39AED1ECAAA28C325****uid******version86version_name3.3.6rDJiNB9j7vD2

至此,简单的逆向分析已经大功告成了!其他接口、其他数据加密算法都可以使用类似的方法来寻找和破译!可以开始码代码了!

 

四、代码实现(Python)

1、AES-CBC-PKCS5加解密(crypto.py)

(1)先看一下相关库的安装与使用:博客园:https://www.cnblogs.com/niuu/p/10107212.html

(2)代码实现:

from Crypto.Cipher import AES
import base64
import re# 加解密
class Crypto(object):def __init__(self):# pubkey值self.key = 'Wet2C8d34f62ndi3'.encode('utf-8')# 偏移量self.iv = b'K6iv85jBD8jgf32D'# AES-CBC对称加密self.mode = AES.MODE_CBC# AES-CBC-PKCS5格式化字符串self.bs = 16self.PADDING = lambda s: s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)# AES-CBC加密def AESEncrypt(self, text):generator = AES.new(self.key, self.mode, self.iv)crypt = generator.encrypt(self.PADDING(text).encode("utf-8"))# 加密后转base64crypted_str = base64.b64encode(crypt)result = crypted_str.decode()return result# 解密def AESDecrypt(self, text):text = base64.b64decode(text)cryptos = AES.new(self.key, self.mode, self.iv)plain_text = cryptos.decrypt(text)data = bytes.decode(plain_text)# 转中文data = data.replace(r'\/', '/').encode().decode('unicode_escape')# print(json.dumps(data))# 格式化pat = re.compile(r'<html>(.*?)</html>')html = pat.findall(data)html = html[0] if html else ""html_ = html.replace('"', "'")# 转为字典data = json.loads(data.replace(html, html_).strip('"').strip('\u000e').strip('\u0007').strip('\u0004'))return data

2、md5加密(Md5.py)

import hashlibdef Md5(text):text = text.encode()m = hashlib.md5()m.update(text)return m.hexdigest()

3、请求数据构建(data.py)

from crypto import *
import time# 打*号的数据涉及隐私, 请自行获取
data = {'version': '86', 'version_name': '3.3.6', 'mobileModel': 'BRQ-AN00', 'mobileDeviceId': '******', 'mobileOsVersion': '7.1.2', 'ostype': '1', 'student_num': '******', 'school_id': '***', 'uid': '******', 'token': '***************', 'timestamp': '', 'nonce': '******', 'access_token': '***************', 'refresh_token': '*****************', 'jpush_id': '*****************', 'sign': '*****************'}
timestamp = int(time.time())
token = '*************'
refresh_token = '************'
sign_data = 'access_token{}jpush_id*********mobileDeviceId**************mobileModelBRQ-AN00mobileOsVersion7.1.2nonce********ostype1refresh_token{}school_id***student_num********timestamp{}token{}uid******version86version_name3.3.6rDJiNB9j7vD2'.format(token, refresh_token, timestamp, token)
sign = Md5(sign_data)
data['token'] = token
data['access_token'] = token
data['refresh_token'] = refresh_token
data['timestamp'] = str(timestamp)
data['sign'] = sign
print(sign)
print(data)

4、发送请求与解析响应(req.py)

import urllib.parse
import requestsurl = "https://api2.lptiyu.com/v3/api.php/Login/RefreshToken"
headers = {'Cookie': 'PHPSESSID=*******************', 'Connection': 'close', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'Content-Length': '299', 'User-Agent': 'Dalvik/2.1.0(Linux;U;Android7.1.2;BRQ-AN00Build/NZH54D)', 'Host': 'api2.lptiyu.com', 'Accept-Encoding': 'gzip'}
data = {'version': '86', 'version_name': '3.3.6', 'mobileModel': 'BRQ-AN00', 'mobileDeviceId': '***************', 'mobileOsVersion': '7.1.2', 'ostype': '1', 'student_num': '************', 'school_id': '***', 'uid': '*******', 'token': '*************', 'timestamp': '******', 'nonce': '*********', 'access_token': '**********', 'refresh_token': '***********', 'jpush_id': '***************', 'sign': '*************'}
data = urllib.parse.urlencode(data)
response = requests.post(url=url, headers=headers, data=data).json()
print(response)

5、总代码(包括其他接口与其他数据)

from Crypto.Cipher import AES
import urllib.parse
import requests
import hashlib
import random
import string
import base64
import time
import json
import re
import os# 加解密
class Crypto(object):def __init__(self):# pubkey值self.key = 'Wet2C8d34f62ndi3'.encode('utf-8')# 偏移量self.iv = b'K6iv85jBD8jgf32D'# AES-CBC对称加密self.mode = AES.MODE_CBC# AES-CBC-PKCS5格式化字符串self.bs = 16self.PADDING = lambda s: s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)# AES-CBC加密def AESEncrypt(self, text):generator = AES.new(self.key, self.mode, self.iv)crypt = generator.encrypt(self.PADDING(text).encode("utf-8"))# 加密后转base64crypted_str = base64.b64encode(crypt)result = crypted_str.decode()return result# 解密def AESDecrypt(self, text):text = base64.b64decode(text)cryptos = AES.new(self.key, self.mode, self.iv)plain_text = cryptos.decrypt(text)data = bytes.decode(plain_text)# 转中文data = data.replace(r'\/', '/').encode().decode('unicode_escape')# print(json.dumps(data))# 格式化pat = re.compile(r'<html>(.*?)</html>')html = pat.findall(data)html = html[0] if html else ""html_ = html.replace('"', "'")# 转为字典data = json.loads(data.replace(html, html_).strip('"').strip('\u000e').strip('\u0007').strip('\u0004'))return data# md5加密@staticmethoddef Md5(text):text = text.encode()m = hashlib.md5()m.update(text)return m.hexdigest()# 生成sign/data值
class Md5Encrypt(object):def __init__(self, **kwargs):# 原始json数据self.data = {# 可自定义的值"jpush_id": "","mobileDeviceId": "","mobileModel": "","mobileOsVersion": "7.1.2",# 客户端版本号, 不建议修改"version": "86","version_name": "3.3.6","ostype": "1",# 标志值# 学校id, 默认-1为未知"school_id": "-1",# 时间戳"timestamp": "",# 六位随机数字字符串"nonce": ""}# sign末端的一个固定值self.sign_str = 'rDJiNB9j7vD2'# 用户uidself.uid = kwargs['uid'] if 'uid' in kwargs else None# 学号self.student_num = kwargs['student_num'] if 'student_num' in kwargs else None# 设置其他值for key, value in kwargs.items():self.data[key] = value# 登录data值def loginData(self, code, phone):# 继承data属性data = self.data# 更新标志值# 固定为1data['type'] = '1'# 手机号data['phone'] = str(phone)# 验证码, 30天内只能获取一次data['code'] = str(code)# 时间戳timestamp = str(int(time.time()))# 六位随机数字字符串nonce = str(random.randint(100000, 999999))# 放入datadata['timestamp'] = timestampdata['nonce'] = nonce# 生成原始sign值# 一定要先对字典排序sign_data = ''.join([(i + data[i]) for i in sorted(data)]) + self.sign_str# 加密sign值sign = Crypto().Md5(sign_data)# sign值放入datadata['sign'] = sign# 加密datadata = Crypto().AESEncrypt(json.dumps(data))# 传输的data原始json值data = {'key': data}# 转换成form-data类型data = urllib.parse.urlencode(data)# 返回data值return data# 获取用户信息def userData(self, token):# 继承data属性data = self.data# 删除jpush_id值del data['jpush_id']# 更新标志值# 用户iddata['uid'] = self.uid# token值data['token'] = token# 时间戳timestamp = str(int(time.time()))# 六位随机数字字符串nonce = str(random.randint(100000, 999999))# 放入datadata['timestamp'] = timestampdata['nonce'] = nonce# 生成原始sign值# 一定要先对字典排序sign_data = ''.join([(i + data[i]) for i in sorted(data)]) + self.sign_str# 加密sign值sign = Crypto().Md5(sign_data)# sign值放入datadata['sign'] = sign# 转换成form-data类型data = urllib.parse.urlencode(data)# 返回data值return data# 获取cookiedef ipData(self, token):# 继承data属性data = self.data# 更新标志值# 固定为2data['type'] = '2'# 学号data['student_num'] = self.student_num# 用户iddata['uid'] = self.uid# token值data['token'] = token# 时间戳timestamp = str(int(time.time()))# 六位随机数字字符串nonce = str(random.randint(100000, 999999))# 放入datadata['timestamp'] = timestampdata['nonce'] = nonce# 生成原始sign值# 一定要先对字典排序sign_data = ''.join([(i + data[i]) for i in sorted(data)]) + self.sign_str# 加密sign值sign = Crypto().Md5(sign_data)# sign值放入datadata['sign'] = sign# 转换成form-data类型data = urllib.parse.urlencode(data)# 返回data值return data# 刷新token值def refreshData(self, token, refresh_token):# 继承data属性data = self.data# 更新标志值# 学号data['student_num'] = self.student_num# 用户iddata['uid'] = self.uid# token值data['token'] = token# access_token值(与token相同)data['access_token'] = token# refresh_token值data['refresh_token'] = refresh_token# 时间戳timestamp = str(int(time.time()))# 六位随机数字字符串nonce = str(random.randint(100000, 999999))# 放入datadata['timestamp'] = timestampdata['nonce'] = nonce# 生成原始sign值# 一定要先对字典排序sign_data = ''.join([(i + data[i]) for i in sorted(data)]) + self.sign_str# 加密sign值sign = Crypto().Md5(sign_data)# sign值放入datadata['sign'] = sign# 转换成form-data类型data = urllib.parse.urlencode(data)# 返回data值return data# 获取排行榜def rankData(self, token, page):# 继承data属性data = self.data# 删除jpush_id值if 'jpush_id' in data:del data['jpush_id']if 'sign' in data:del data['sign']# 更新标志值# 固定为1data['type'] = '1'# 固定为1data['category'] = '1'# 学号data['student_num'] = self.student_num# 用户iddata['uid'] = self.uid# token值data['token'] = token# 页码data['page'] = str(page)# 时间戳timestamp = str(int(time.time()))# 六位随机数字字符串nonce = str(random.randint(100000, 999999))# 放入datadata['timestamp'] = timestampdata['nonce'] = nonce# 生成原始sign值# 一定要先对字典排序sign_data = ''.join([(i + data[i]) for i in sorted(data)]) + self.sign_str# 加密sign值sign = Crypto().Md5(sign_data)# sign值放入datadata['sign'] = sign# 转换成form-data类型data = urllib.parse.urlencode(data)# 返回data值return data# 发送请求
class GetResponse(object):def __init__(self, **kwargs):# 请求头self.headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8','User-Agent': 'Dalvik/2.1.0(Linux;U;Android7.1.2;BRQ-AN00Build/NZH54D)','Host': 'api2.lptiyu.com','Accept-Encoding': 'gzip'}# 读取用户信息userData = User().getUser()# 虚拟客户端信息jpush_id = userData['jpush_id']mobileDeviceId = userData['mobileDeviceId']mobileModel = userData['mobileModel']# 用户标识信息# 用户uidif 'uid' not in userData:self.encrypter = Md5Encrypt(jpush_id=jpush_id, mobileDeviceId=mobileDeviceId, mobileModel=mobileModel)self.login(autoLogin=False)else:self.uid = userData['uid']self.token = userData['access_token']self.refresh_token = userData['refresh_token']# 学号if 'student_num' not in userData:print('正在获取学号...')self.encrypter = Md5Encrypt(jpush_id=jpush_id, mobileDeviceId=mobileDeviceId, mobileModel=mobileModel, uid=self.uid)self.user()else:self.student_num = userData['student_num']# 重载加密器self.encrypter = Md5Encrypt(jpush_id=jpush_id, mobileDeviceId=mobileDeviceId, mobileModel=mobileModel, uid=self.uid, student_num=self.student_num)print('初始化完成!')# 重新登录def login(self, code=None, phone=None, autoLogin=True):if not autoLogin:print('请先重新登录!')phone = input('请输入手机号码: ')code = input('请输入验证码: ')print('正在登录......')url = 'https://api2.lptiyu.com/v3/api.php/Login/quickLoginV300'data = self.encrypter.loginData(code=code, phone=phone)response = requests.post(url=url, headers=self.headers, data=data).json()if 'data' not in response:raise Exception("登录失败!")tokenData = Crypto().AESDecrypt(response['data'])self.uid = tokenData['uid']self.token = tokenData['access_token']self.refresh_token = tokenData['refresh_token']# 保存token数据User().saveUser(userData=tokenData)return tokenData# 获取用户信息def user(self):url = 'https://api2.lptiyu.com/v3/api.php/User/User'data = self.encrypter.userData(token=self.token)response = requests.post(url=url, headers=self.headers, data=data).json()if 'data' not in response:raise Exception("登录失效!")user = Crypto().AESDecrypt(response['data'])self.student_num = user['student_num']User().saveUser(userData=user)return user'''# 获取cookiedef getIp(self):url = 'https://api2.lptiyu.com/v3/api.php/System/getIp'data = self.encrypter.ipData(self.token)response = requests.post(url=url, headers=self.headers, data=data)try:cookies = response.cookiescookies = requests.utils.dict_from_cookiejar(cookies)self.headers["Cookie"] = list(cookies.keys())[0] + '=' + list(cookies.values())[0]except:raise Exception("登录失效!")return cookies'''# 刷新token值def refreshToken(self):url = 'https://api2.lptiyu.com/v3/api.php/Login/RefreshToken'data = self.encrypter.refreshData(token=self.token, refresh_token=self.refresh_token)response = requests.post(url=url, headers=self.headers, data=data).json()if 'data' not in response:raise Exception("登录失效!")tokenData = Crypto().AESDecrypt(response['data'])self.token = tokenData['access_token']self.refresh_token = tokenData['refresh_token']# 保存token数据User().saveUser(userData=tokenData)return tokenData# 获取排行榜def getTotalRank(self, page):url = 'https://api2.lptiyu.com/v3/api.php/Run/getTotalRank'data = self.encrypter.rankData(token=self.token, page=page)response = requests.post(url=url, headers=self.headers, data=data).json()if 'data' not in response:raise Exception("登录失效!")rankData = Crypto().AESDecrypt(response['data'])['rank_list']return rankData# 操作user文件
class User(object):def __init__(self):# token文件路径self.file = 'user.json'# 构建客户端信息def createInfo(self):s = string.ascii_letters + string.digitsjpush_id = "".join(random.choice(s) for _ in range(0, 19))mobileDeviceId = "".join(random.choice(string.digits) for _ in range(0, 15))mobileModel = "".join(random.sample(string.digits, 3)) + '-' + "".join(random.sample(s, 4))user = {'jpush_id': jpush_id, 'mobileDeviceId': mobileDeviceId, 'mobileModel': mobileModel}with open(self.file, 'w') as fp:json.dump(user, fp)# 从本地获取User信息def getUser(self):if not os.path.exists(self.file):self.createInfo()with open(self.file, 'r') as fp:userData = json.load(fp)return userData# 保存User数据def saveUser(self, userData):with open(self.file, 'r') as fp:userData_ = json.load(fp)for key, value in userData.items():userData_[key] = valuewith open(self.file, 'w') as fp:fp.write(json.dumps(userData_))if __name__ == '__main__':handler = GetResponse()fp = open('lptiyu.csv', 'w', encoding='utf-8')fp.write('排名,姓名,已跑次数\n')for j in range(1, 4):rankData_ = handler.getTotalRank(page=j)for i in rankData_:score = i['score_num']rank = i['rank']name = i['name']fp.write('%s,%s,%s\n' % (rank, name, score))fp.close()

好了,今天的总结与分享就到这里,感谢你的阅读!


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

相关文章

2030年量子计算市场规模预计将达45310.4亿美元

&#xff08;图片来源&#xff1a;网络&#xff09; 2020年&#xff0c;量子计算市场规模占3873亿美元。据最新研究&#xff0c;预计到2030年&#xff0c;量子计算市场规模将达45310.4亿美元&#xff0c;年复合增长率为28.2%。 这项研究主要从以下几个方面进行了预测&#xff1…

量子计算(十四):超导量子芯片

文章目录 超导量子芯片 超导量子芯片 超导量子计算是基于超导电路的量子计算方案&#xff0c;其核心器件是超导约瑟夫森结。超导量子电路在设计、制备和测量等方面&#xff0c;与现有的集成电路技术具有较高的兼容性&#xff0c;对量子比特的能级与耦合可以实现非常灵活的设计…

量子计算(十五):半导体量子芯片

文章目录 半导体量子芯片 前言 半导体量子技术的发展 半导体量子芯片 前言 当传统计算模式趋近瓶颈时&#xff0c;下一代计算模式的重大变革也即将来临。在不久的将来&#xff0c;量子计算可以改变世界已经成为了共识。 一些大公司已经开始将量子计算研究视为一场竞赛。谷…

ICV光子盒:2023全球量子计算产业发展展望

近日&#xff0c;全球著名的前沿科技咨询机构ICV与国内专注量子领域的行业研究机构光子盒&#xff0c;联合发布了2023全球量子计算产业发展展望&#xff0c;为量子计算行业的决策者、投资者和政策制定者提供了宝贵的见解&#xff0c;帮助其紧跟量子计算的最新发展&#xff0c;并…

量子计算进阶:量子计算机的组建和量子计算原理(包含相关论文推荐60篇)

量子计算进阶&#xff1a;量子计算机 量子计算量子计算机的组建量子门量子存储量子CPU测控系统量子纠错 另推荐相关论文(基础领域20篇,深化领域30篇&#xff09;量子基础量子计算基础 前置所需知识&#xff1a; 量子计算入门&#xff1a;量子计算机的理解与术语科普 本文中的大…

量子计算(6)pyqpanda编程1:量子程序与量子线路

目录 一、概述 1、前言 2、构建量子程序前的几个步骤 ①导入pyqpanda包 ②创建量子虚拟机 ③申请量子比特和经典寄存器 二、QGate类 1、量子比特门 ①单量子比特无角度 ②单量子比特有角度 ③多量子比特无角度 ④多量子比特有角度 2、接口 ①对矩阵进行伴随…

量子计算(二):为什么需要量子计算

目录 为什么需要量子计算 前言 一、大数据检索 二、 量子模拟 三、 金融服务 四、人工智能 五、现代农业 六、 云计算 七、网络安全 为什么需要量子计算 前言 根据摩尔定律&#xff0c;集成电路上可容纳的晶体管数目每隔约18-24个月增加一倍&#xff0c;性能也相应增…

量子计算(1)科学背景1:量子力学基本理论(上)

一、量子技术的历史 二、量子力学 1、量子的四特性 2、量子力学基本理论 ①态矢 ②内积与外积 ③两能集系统 ④观察概率 一、量子技术的历史 我们学习一个东西&#xff0c;归根结底是要掌握他在科学上的用途。而如何去使用、历史上是如何运用的&#xff0c;值得…

量子计算(七):量子系统

文章目录 量子系统 前言 一、量子化 &#xff08;Quantization&#xff09;与量子态 &#xff08;QuantumState&#xff09; 二、量子叠加性 &#xff08;Quantum Superposition&#xff09; 三、状态的演化&#xff08;Evolution of State&#xff09; 四、测量和坍缩&…

量子计算(十):量子计算原理

文章目录 量子计算原理 一、酉变换 二、矩阵的指数函数 三、单位矩阵 四、单量子比特逻辑门 五、泡利矩阵 六、常见逻辑门 量子计算原理 经典计算中&#xff0c;最基本的单元是比特&#xff0c;而最基本的控制模式是逻辑门&#xff0c;可以通过逻辑门的组合来达到控制电…

量子计算:后摩尔时代计算能力提升的解决方案

✦ 量子计算&#xff1a; 后摩尔时代计算能力提升的解决方案 ✦ 编者按&#xff1a;由朱晓波、陆朝阳、潘建伟等人撰写的这篇文章客观介绍了量子计算的原理、发展现状以及发展趋势&#xff1a;“实现‘量子计算优越性’的阶段目标是量子计算研究的第一个里程碑&#xff0c;它验…

量子计算(十七):量子计算机硬件

文章目录 量子计算机硬件 一、量子芯片支持系统 二、量子计算机控制系统 量子计算机硬件 量子计算机的核心——量子芯片&#xff0c;具有多种不同的呈现形式。绝大多数量子芯片&#xff0c;名副其实地&#xff0c;是一块芯片&#xff0c;由集成在基片表面的电路结构构建出包…

量子计算

《目录》 量子计算的性质 量子叠加量子纠缠量子算法计算的本质量子输入量子输出 量子计算的性质 量子计算是采用量子力学原理进行计算的。 量子的特性&#xff1a; 量子叠加&#xff08;既...又...&#xff09;量子纠缠&#xff08;命是大家的&#xff0c;一个量子挂了&…

什么是量子计算?

目录 第一部分&#xff1a;量子力学基础第二部分&#xff1a;量子计算原理第三部分&#xff1a;量子计算的应用和前景 量子计算是一种基于量子力学原理的计算模型&#xff0c;利用量子比特&#xff08;qubit&#xff09;作为信息的基本单位进行计算。相比传统的经典计算机&…

量子计算(二十):量子算法简介

文章目录 量子算法简介 一、概述 二、量子经典混合算法 量子算法简介 一、概述 量子算法是在现实的量子计算模型上运行的算法&#xff0c;最常用的模型是计算的量子电路模型。经典&#xff08;或非量子&#xff09;算法是一种有限的指令序列&#xff0c;或一步地解决问题的…

量子计算基础

量子计算基础 前言一、量子计算基础1. 量子比特2. 量子并行特性 二、量子基本门1. 单量子比特门2. 多量子比特门 前言 量子算法是利用量子力学的特性巧妙地解决经典算法中的计算难题。它是将量子计算与量子信息理论融入到算法设计中。在这里&#xff0c;简单介绍一下量子计算基…

量子计算(一):量子计算是什么

文章目录 量子计算是什么 前言 一、什么是量子 二、什么是量子计算 量子计算是什么 前言 当传统计算模式趋近瓶颈时&#xff0c;下一代计算模式的重大变革也即将来临。在不久的将来&#xff0c;量子计算可以改变世界已经成为了共识。 一些大公司已经开始将量子计算研究视…

量子计算与量子信息之量子计算概述

量子计算与量子信息之量子计算概述 &#xff08;这个是连载的哦&#xff0c;期待大家的持续关注啦…&#xff09; 文章目录 量子计算与量子信息之量子计算概述一、引言二、初步感知三、引言与概述四、量子比特1、量子比特的概念2、Bloch球3、多量子比特 五、量子计算概述1、单…

OSM和PBF数据格式说明

从openstreetmap上下载的数据都是*.osm后缀的&#xff0c;虽然后缀是osm&#xff0c;但它的格式其实是xml的&#xff0c;而pbf则是一种xml的压缩格式。 一、osm格式 复制于&#xff1a;http://wiki.citydatum.com/index.php/OpenStreetMap&#xff0c;这个网页对openstreetmap…

osm 搭建离线地图_利用OpenStreetMap(OSM)数据搭建一个地图服务

图 利用OSM数据简单发布的北京地图服务 一、OSM是什么 开放街道图(OpenStreetMap&#xff0c;简称OSM)是一个网上地图协作计划&#xff0c;目标是创造一个内容自由且能让所有人编辑的世界地图(wiki&#xff1a;http://wiki.openstreetmap.org/wiki/Main_Page)。尤其值得称道的是…