Python3爬虫实战:利用Fiddler抓取手机APP数据
本文详细讲解如何使用Python3配合Fiddler工具抓取手机APP接口数据。内容涵盖Fiddler安装配置、手机代理设置、证书信任及抓包测试,并以王者荣耀盒子APP为例,演示如何解析英雄与装备接口数据,最终提供完整的Python爬取代码供参考。
以往的爬虫案例多集中于网页数据,本文将介绍一种通过Fiddler工具抓取手机APP接口数据的方法。
一、环境配置
1、Fidder的安装和配置
若未安装Fidder软件,可访问指定网址进行下载。安装过程采用默认设置即可,步骤简便。安装完成后启动软件,需进行如下配置:


此处保持默认的8888端口即可;若需修改端口,务必确保不与系统其他服务端口发生冲突。
2、手机的配置
首先打开命令行工具cmd,执行ipconfig命令以获取本机IP地址,并记录该地址:

为实现Fiddler对手机流量的抓取,需确保手机与PC处于同一局域网内,通常通过连接相同的无线网络实现。随后在手机端进入Wi-Fi设置,将代理模式改为手动,并填入前述IP地址及8888端口号:

接着在手机浏览器中访问http://127.0.0.1:8888,页面将显示如下界面,点击“FidderRoot certificate”以下载根证书:

下载证书后若遇到安装失败的情况,可尝试通过系统设置手动安装。以部分机型为例,路径为“设置->系统安全->从SD卡安装”。不同手机品牌的安装路径可能略有差异,但大体流程相似。
3、抓包测试
完成上述配置后,进行抓包验证。打开手机浏览器访问百度网页,此时Fiddler中应能捕获到相应的请求包,表明环境配置成功,可进行后续的数据抓取操作。

二、抓取步骤
本次测试选取的APP为“王者荣耀盒子”。启动APP后,点击“英雄”栏目,选中首位英雄“上官婉儿”并进入详情页。

此时在Fiddler中可以定位到如下请求包:

查看右侧详情面板,可见如下信息:

复制该请求数据并进行解码,即可获取包含英雄名称、头像图片及技能描述在内的结构化数据:

然而,在推荐的装备信息字段中,仅包含装备的ID值,缺失装备名称。为解决此问题,可采用相同策略:点击查看“所有装备”列表,重新抓包定位对应接口,进而爬取装备名称。在获取全部装备及其ID映射关系后,再爬取所有英雄名称,即可构建个性化的英雄攻略数据。
最终运行结果如下所示:

三、完整代码
"""
Version: Python3.5
Author: OniOn
Time: 2018/11/26 21:20
"""
import requests
# 装备信息
EQUIP_LIST = []
# 英雄信息
HERO_LIST = []
# 爬取英雄信息
def get_hero(hero_id):
url = "http://gamehelper.gm825.com/wzry/hero/detail?hero_id={}&channel_id=90009a&app_id=h9044j&game_id=7622&game_name=%E7%8E%8B%E8%80%85%E8%8D%A3%E8%80%80&vcode=13.0.4.0&version_code=13040&cuid=192384A3D29A295307CA7B96762D3911&ovr=6.0.1&device=Xiaomi_Redmi+4X&net_type=1&client_id=&info_ms=&info_ma=Z6OSFnQs6mXn4axI72A6yENV6NHXHBW%2FwZ6YjXKCGko%3D&mno=0&info_la=zdisjKfT0Zj1UXN2un%2BlyA%3D%3D&info_ci=zdisjKfT0Zj1UXN2un%2BlyA%3D%3D&mcc=0&clientversion=13.0.4.0&bssid=bFL4zw1N%2FGL43totbQy7Q9D8UfrPgiMUFRNSpM25pnY%3D&os_level=23&os_id=a2aa922677827ab1&resolution=720_1280&dpi=320&client_ip=10.12.88.95&pdunid=257ed0277cf4".format(
hero_id)
res = requests.post(url)
js = res.json()
img_url = js['info']['big_img']
skill_tips = js['info']['skill_tips'] # 使用技巧
skill_list = [] # 技能介绍
for i in js['info']['skill_list']:
desc = i['description'] if '<br>' not in i['description'] else i['description'].replace('<br>', '')
skill_list.append({
"name": i['name'] + "({})".format(i['intro']),
"type": i['tags'],
"desc": desc
})
print("英雄图片链接:{}".format(img_url))
print("英雄使用技巧:{}".format(skill_tips))
for i in skill_list:
print('{} 类型:{} \n技能介绍:{}'.format(i['name'], i['type'], i['desc']))
print("推荐装备:", end="")
equip_choice = [] # 推荐装备
all_money =
for i in js['info']['equip_choice'][]['list']:
equip_choice.append(EQUIP_LIST[int(i['equip_id'])]['name'])
all_money += int(EQUIP_LIST[int(i['equip_id'])]['price'])
print(' '.join(equip_choice), " (装备总金额:{})".format(all_money))
# 爬取所有装备的基本信息
def get_all_equip():
url = "http://gamehelper.gm825.com/wzry/equip/list?channel_id=90009a&app_id=h9044j&game_id=7622&game_name=%E7%8E%8B%E8%80%85%E8%8D%A3%E8%80%80&vcode=13.0.4.0&version_code=13040&cuid=192384A3D29A295307CA7B96762D3911&ovr=6.0.1&device=Xiaomi_Redmi+4X&net_type=1&client_id=&info_ms=&info_ma=Z6OSFnQs6mXn4axI72A6yENV6NHXHBW%2FwZ6YjXKCGko%3D&mno=0&info_la=zdisjKfT0Zj1UXN2un%2BlyA%3D%3D&info_ci=zdisjKfT0Zj1UXN2un%2BlyA%3D%3D&mcc=0&clientversion=13.0.4.0&bssid=bFL4zw1N%2FGL43totbQy7Q9D8UfrPgiMUFRNSpM25pnY%3D&os_level=23&os_id=a2aa922677827ab1&resolution=720_1280&dpi=320&client_ip=10.12.88.95&pdunid=257ed0277cf4"
res = requests.get(url)
for i in res.json()['list']:
EQUIP_LIST.append({
'price': i['price'],
'name': i['name'],
# 'equip_id': i['equip_id']
})
# 爬取所有英雄的基本信息
def get_all_hero():
# 英雄定位: type 1-战士 2-法师 3-坦克 4-刺客 5-射手 6-辅助
type_list = ['战士', '法师', '坦克', '刺客', '射手', '辅助']
url = "http://gamehelper.gm825.com/wzry/hero/list?channel_id=90009a&app_id=h9044j&game_id=7622&game_name=%E7%8E%8B%E8%80%85%E8%8D%A3%E8%80%80&vcode=13.0.4.0&version_code=13040&cuid=192384A3D29A295307CA7B96762D3911&ovr=6.0.1&device=Xiaomi_Redmi+4X&net_type=1&client_id=&info_ms=&info_ma=Z6OSFnQs6mXn4axI72A6yENV6NHXHBW%2FwZ6YjXKCGko%3D&mno=0&info_la=zdisjKfT0Zj1UXN2un%2BlyA%3D%3D&info_ci=zdisjKfT0Zj1UXN2un%2BlyA%3D%3D&mcc=0&clientversion=13.0.4.0&bssid=bFL4zw1N%2FGL43totbQy7Q9D8UfrPgiMUFRNSpM25pnY%3D&os_level=23&os_id=a2aa922677827ab1&resolution=720_1280&dpi=320&client_ip=10.12.88.95&pdunid=257ed0277cf4"
res = requests.get(url)
for i in res.json()['list']:
HERO_LIST.append({
"name": i['name'],
"id": i['hero_id'],
'type': '/'.join([type_list[int(j) - ] for j in i['type']])
})
if __name__ == '__main__':
get_all_hero()
length = len(HERO_LIST)
print("-" * 50)
for i in range(0, length // 5 * 5, 5):
print('{}(id:{}) '.format(HERO_LIST[i]['name'], HERO_LIST[i]['id']), end=' ')
print('{}(id:{}) '.format(HERO_LIST[i + 1]['name'], HERO_LIST[i + 1]['id']), end=' ')
print('{}(id:{}) '.format(HERO_LIST[i + 2]['name'], HERO_LIST[i + 2]['id']), end=' ')
print('{}(id:{}) '.format(HERO_LIST[i + 3]['name'], HERO_LIST[i + 3]['id']), end=' ')
print('{}(id:{}) '.format(HERO_LIST[i + 4]['name'], HERO_LIST[i + 4]['id']))
for i in range(length // 5 * 5, length):
print('{}(id:{}) '.format(HERO_LIST[i]['name'], HERO_LIST[i]['id']), end=' ')
print('\n', "-" * 50)
get_all_equip()
get_hero(input("\n请输入您想查看的英雄id:"))
以上为本文全部内容,希望能为读者的学习提供有益帮助,同时也欢迎对本站内容给予支持。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









