最近项目在搞抖音app,记录一下过程和遇到的坑
1,appium
2,fiddle
3,夜神模拟器
4,Android SDK
详情可以借鉴这篇文章
https://www.cnblogs.com/qieyu/p/10450739.html
其中如果出现 adb devices 连接不到的情况就将上述文章中的替换adb.exe步骤更改为sdk的adb.exe复制到模拟器下bin目录下的adb.exe,然后将nox_adb.exe复制到桌面然后重命名为nox_adb.exe.bak,再将重命名后的文件放到模拟器bin目录下
再执行adb connect connect 127.0.0.1:62001
整个操作过程可以参考https://www.cnblogs.com/CYHISTW/p/11626990.html
这个tap.py脚本是点击搜索框输入罗志祥然后点击用户进入用户主页
from appium import webdriver
# WebDriverWait用来加入时间判断,有时候控件元素需要过一段时间才会出现
from selenium.webdriver.support.ui import WebDriverWait
import time
'''
此版本适用于抖音6.0.0版本
'''
# 配置信息
option = {
"platformName": "Android",
"platformVersion": "5.1.1",
"deviceName": "127.0.0.1:62001",
# 自动化测试包名
"appPackage": "com.ss.android.ugc.aweme",
# 自动化测试Activity
"appActivity": "com.ss.android.ugc.aweme.main.MainActivity",
'automationName': 'uiautomator2',
# 再次启动不需要再次安装
"noReset": True,
# unicode键盘 我们可以输入中文
"unicodekeyboard": True,
# 操作之后还原回原先的输入法
"resetkeyboard": True
}
# 其中的4723就是appium服务启动时的端口号
driver = webdriver.Remote("http://localhost:4723/wd/hub", option)
# 得到窗口大小
def get_size():
x = driver.get_window_size()['width']
y = driver.get_window_size()['height']
return (x, y)
# 放大镜按钮
try:
# 使用resource-id查找按钮
if WebDriverWait(driver, 5).until(lambda x: x.find_element_by_id('com.ss.android.ugc.aweme:id/aqz')):
# 点击按钮
driver.find_element_by_id('com.ss.android.ugc.aweme:id/aqz').click()
except:
pass
WebDriverWait(driver, 5)
# 定位搜索框
if WebDriverWait(driver, 5).until(lambda x: x.find_element_by_id('com.ss.android.ugc.aweme:id/agq')):
driver.find_element_by_id('com.ss.android.ugc.aweme:id/agq').click()
# time.sleep(1)
driver.find_element_by_id('com.ss.android.ugc.aweme:id/agq').send_keys('罗志祥')
# 点击搜索
driver.find_element_by_id('com.ss.android.ugc.aweme:id/agt').click()
WebDriverWait(driver, 5)
# 点击用户
try:
driver.find_element_by_id('android:id/text1').click()
except:
driver.tap([(299, 173), (359, 214)], 500)
time.sleep(4)
try:
driver.find_element_by_id('com.ss.android.ugc.aweme:id/ab8').click()
except:
driver.tap([(32, 279), (144, 391)], 500)
time.sleep(5)
上述脚本中用模拟器搜索用户的时候可能会返回找不到用户,可能是因为安装的Xposed Installer 没有激活
这个swipe.py脚本是自动上滑左滑进入用户主页
from appium import webdriver
# WebDriverWait用来加入时间判断,有时候控件元素需要过一段时间才会出现
from selenium.webdriver.support.ui import WebDriverWait
import time
# 配置信息
option = {
"platformName": "Android",
"platformVersion": "5.1.1",
"deviceName": "127.0.0.1:62001",
# 自动化测试包名
"appPackage": "com.ss.android.ugc.aweme",
# 自动化测试Activity
"appActivity": "com.ss.android.ugc.aweme.main.MainActivity",
# 再次启动不需要再次安装
"noReset": True,
# unicode键盘 我们可以输入中文
"unicodekeyboard": True,
# 操作之后还原回原先的输入法
"resetkeyboard": True
}
# 其中的4723就是appium服务启动时的端口号
driver = webdriver.Remote("http://localhost:4723/wd/hub", option)
# # 得到窗口大小
def get_size():
x = driver.get_window_size()['width']
y = driver.get_window_size()['height']
return (x, y)
def swipe_left():
size = get_size()
driver.swipe(int(size[0] * 0.85), int(size[1] * 0.5), int(size[0] * 0.15), int(size[1] * 0.5), 1000)
print('向左滑动')
def swipe_up():
size = get_size()
driver.swipe(int(size[0] * 0.5), int(size[1] * 0.85), int(size[0] * 0.5), int(size[1] * 0.15), 1000)
print('向上滑动')
def swipe_right():
size = get_size()
driver.swipe(int(size[0] * 0.15), int(size[1] * 0.5), int(size[0] * 0.85), int(size[1] * 0.5), 1000)
print('向右滑动')
while True:
WebDriverWait(driver, 100)
# 测出等待四秒刚好是抖音加载时间
time.sleep(4)
# 模拟滑动
swipe_left()
swipe_left()
time.sleep(0.2)
swipe_right()
time.sleep(0.2)
swipe_up()
time.sleep(0.2)
swipe_left()
time.sleep(0.2)
swipe_right()
time.sleep(0.2)
swipe_up()
其中获取appPackage和appActivity获取方法参考下面这位大兄弟的文章
https://blog.csdn.net/qq_34374753/article/details/81605374
下面mitmdump_get_user_id.py 是mitmdump运行文件,获取到接口数据
import json
import re
from get_shop_detail import get_shop_detail
# from get_user_detail import handle_douyin_info
# 获取的数字都是详细数字,返回抖音展示数据
def show_num(st):
if 100000000 > st > 10000:
st = str(st)[:-4] + '.' + str(st)[-4] + 'w'
return st
elif st > 100000000:
if int(str(st)[-8]) > 8:
st = str(int(str(st)[:-8]) + 1) + '.' + '0' + '亿'
else:
st = str(st)[:-8] + '.' + str(st)[-8] + '亿'
return st
else:
return st
# 'aweme.snssdk.com/aweme/v1/discover/search'这是搜索框内的接口
# aweme-hl.snssdk.com/aweme/v1/user/follower/list
# 函数名必须这样写 这是mitmdump规则
def response(flow):
uid_list = []
if 'https://aweme-hl.snssdk.com/aweme/v1/story/?' in flow.request.url:
# print('输出连接story', flow.response.text)
story_data = json.loads(flow.response.text)
for u in story_data['story_feed']:
s_uid = u['user_info']['uid']
uid_list.append(s_uid)
elif 'aweme-hl.snssdk.com/aweme/v1/aweme/post/?' in flow.request.url:
# print('输出连接post', flow.response.text)
post_data = json.loads(flow.response.text)
p_uid = post_data['aweme_list'][0]['author']['uid']
uid_list.append(p_uid)
elif 'aweme-eagle-hl.snssdk.com/aweme/v1/user/?user_id' in flow.request.url:
# print('输出连接user_id', flow.response.text)
'''用户详情页,如果mitmdump没有获取到该链接则获取uid去请求网页版
'''
user_data = json.loads(flow.response.text)
nickname = user_data['user']['nickname']
# 粉丝数
mplatform_followers_count = user_data['user']['mplatform_followers_count']
# 认证
custom_verify = user_data['user']['custom_verify']
# 自我备注
signature = user_data['user']['signature']
# 关注
following_count = user_data['user']['following_count']
# 获赞数
total_favorited = user_data['user']['total_favorited']
s_uid = user_data['user']['uid']
print(nickname, s_uid, mplatform_followers_count, signature, following_count, total_favorited, custom_verify)
uid_list.append(s_uid)
elif 'aweme-eagle-hl.snssdk.com/aweme/v1/feed/' in flow.request.url:
# print('输出连接feed', flow.response.text)
feed_data = json.loads(flow.response.text)
for u in feed_data['aweme_list']:
f_uid = u['author']['uid']
uid_list.append(f_uid)
elif 'aweme/v1/discover/search' in flow.request.url:
user_data = json.loads(flow.response.text)
for u_mes in user_data['user_list']:
# 简称
nickname = u_mes['user_info']['nickname']
# 自我备注
signature = u_mes['user_info']['signature']
# 关注
following_count = u_mes['user_info']['following_count']
# 粉丝数
follower_count = u_mes['user_info']['follower_count']
# 获赞数
total_favorited = u_mes['user_info']['total_favorited']
# 抖音号
unique_id = u_mes['user_info']['unique_id']
# 认证
custom_verify = u_mes['user_info']['custom_verify']
# 头像图片
cover = u_mes['user_info']['avatar_168x168']['url_list'][0]
print(nickname,signature,follower_count,following_count,total_favorited,unique_id,custom_verify,cover)
if len(set(uid_list)):
for uuid in set(uid_list):
for shop_info in get_shop_detail(uuid):
if '该用户没有种草视频' in shop_info:
pass
else:
# user_info = handle_douyin_info(uuid)
# print(user_info)
print(shop_info)
下面get_shop_detail.py是根据用户id判断是否有种草视频接口
import json
import requests
def get_num(num):
if num[-2:] == '00':
num = num[:-2]
else:
num = num[:-2] + '.' + num[-2]
return num
def get_shop_detail(uid):
url = f'https://aweme-hl.snssdk.com/aweme/v1/promotion/user/promotions/?count=2000&cursor=0&user_id={uid}&version=2&from=2&ts=1572857141&js_sdk_version=1.14.5.20&app_type=normal&os_api=22&device_type=google%20Pixel%202&device_platform=android&ssmix=a&iid=90888264944&manifest_version_code=600&dpi=320&uuid=865166010002072&version_code=600&app_name=aweme&version_name=6.0.0&openudid=00cfe04d074c9806&device_id=69289123246&resolution=900*1600&os_version=5.1.1&language=zh&device_brand=google&ac=wifi&update_version_code=6002&aid=1128&channel=wandoujia_aweme1&_rticket=1572857161583&mcc_mnc=46007&as=a1750e6b45437d154f4855&cp=ec37dd5c5af2b85ae1KcSg&mas=0144f35c4083bebfe452339d1c8b179f38acac1c2c662cac8c26ec'
headers = {'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'cache-control': 'max-age=0',
'cookie': 'odin_tt=15551ee734234ab8d70bd407a37fa44abb65f07804072751c61070fc46b0245df24e6ba1ab998e458b5850f6b1de4e7c5de439b885f2d14c7add4adc1141144c',
'sec-fetch-mode': 'navigate', 'sec-fetch-site': 'none', 'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}
res = requests.get(url, headers=headers, verify=False)
if res.status_code == 200:
try:
if len(res.json()['promotions']) != 0:
for mes in res.json()['promotions']:
# 商品标题
shop_title = mes['title']
# 商品链接
shop_url = mes['url']
# 商品id
gid = mes['gid']
# 商品封面
elastic_img = mes['elastic_img'][0]['url_list'][0]
prices = str(mes['price'])
# 商品现价
price = get_num(prices)
market_prices = str(mes['market_price'])
# 商品原价
market_price = get_num(market_prices)
# 销售量
sales = mes['sales']
# 视频id
# last_aweme_id = mes['last_aweme_id']
# 优惠券值
if 'coupon' in json.loads(mes['extra']):
coupon_amount = json.loads(mes['extra'])['coupon']['coupon_amount']
else:
coupon_amount = '无'
# print(shop_title, gid, coupon_amount, elastic_img, price, shop_url, market_price, sales)
yield shop_title, gid, coupon_amount, elastic_img, price, shop_url, market_price, sales
else:
yield '该用户没有种草视频', '该用户没有种草视频', '该用户没有种草视频', '该用户没有种草视频', '该用户没有种草视频', '该用户没有种草视频', '该用户没有种草视频', '该用户没有种草视频'
except Exception as e:
print('出错了', e)
运行步骤最好按照下面步骤来:
1,打开模拟器和appium-desktop
2,在命令窗口输入mitmdump -s mitmdump_get_user_id.py -p 8080
3,运行appium server
4,运行操作py脚本