无不良目的,学习使用。
一、工具介绍
fiddler:用于查看抖音个人信息接口,Tool-Connections-port配置监听端口
uiautomator2:操控夜神模拟器,模拟操作抖音,打开抖音,去掉提示信息,点击个人中心,返回,滑动,重复操作。
mitmdump:抓取模拟器请求数据,对请求url进行过滤,过滤出通过fiddler查到的接口,并对数据解析入库。启动命令:mitmdump -p 8888 -s decode_douyin.py
weditor:用于查看app的元素,确定元素位置。启动:python -m weditor,connect连接,dump hierachy刷新。
夜神模拟器:需要配置桥接,配置网络ip和端口和fiddler和mitmdump一样
二、数据展示
三、代码展示
uiautomator操控夜神模拟器部分
import time
import uiautomator2 as u2
class Douyin:
def __init__(self):
# self.d = u2.connect_usb(serial=serial)
self.d = u2.connect()
self.stop_app()
self.handle_watcher()
self.size = self.get_windowsize()
# 是用来获取一个初始时间
self.t0 = time.perf_counter()
def start_app(self):
"""启动app"""
self.d.app_start(package_name="com.ss.android.ugc.aweme")
def stop_app(self):
"""app退出逻辑"""
# 先关闭监视器
self.d.watcher.stop()
self.d.app_stop("com.ss.android.ugc.aweme")
self.d.app_clear("com.ss.android.ugc.aweme")
def get_windowsize(self):
return self.d.window_size()
def handle_watcher(self):
"""监视器"""
# 个人信息保护指引
print('====滑动个人信息保护指引')
self.d.watcher.when('//*[@resource-id="com.ss.android.ugc.aweme:id/azt"]').click()
self.d.watcher.when('//*[@resource-id="com.ss.android.ugc.aweme:id/azp"]').click()
# 添加一个监控器
# self.d.watcher.when('//*[@text="快速进入TA的个人中心"]').click()
# 监控器写好之后,一定要记得启动
self.d.watcher.start(interval=1)
def swipe_up(self):
x1 = int(self.size[0] * 0.5)
y1 = int(self.size[1] * 0.9)
y2 = int(self.size[1] * 0.15)
self.d.swipe(x1, y1, x1, y2)
def run(self):
print('====1开启app')
self.start_app()
print('====2等待上滑查看更多视频')
if self.d(resourceId='com.ss.android.ugc.aweme:id/ir3', text='上滑查看更多视频').exists(timeout=25):
print('====3点击上滑查看更多视频')
self.swipe_up()
time.sleep(1)
i = 1
while True:
if self.d(resourceId='com.ss.android.ugc.aweme:id/cgd').exists():
# print('====进入广告,继续滑动')
self.swipe_up()
continue
if self.d(resourceId='com.ss.android.ugc.aweme:id/bi0').exists():
# print('====进入广告,继续滑动')
self.swipe_up()
continue
try:
if self.d.xpath('//*[@resource-id="com.ss.android.ugc.aweme:id/j0k"]/android.widget.TextView[1]').exists:
# print('====进入广告,继续滑动')
self.swipe_up()
continue
except Exception as e:
pass
print('====第{}次滑动'.format(i))
# if self.d(resourceId='com.ss.android.ugc.aweme:id/emd').exists(timeout=10):
# 点击头像
try:
self.d(resourceId='com.ss.android.ugc.aweme:id/em1').click(timeout=5)
except:
try:
self.d(resourceId='com.ss.android.ugc.aweme:id/j0k').click(timeout=5)
except:
print('===error:77')
return
# 判断获赞数是否出来
# if self.d(resourceId='com.ss.android.ugc.aweme:id/egh').exists(timeout=15):
# print('获赞数出来了')
# else:
# print('获赞数没出来')
time.sleep(4)
# 点击返回
self.d.xpath('//*[@resource-id="com.ss.android.ugc.aweme:id/l6"]').click(timeout=10)
# 判断是否是广告
if self.d(resourceId='com.ss.android.ugc.aweme:id/a3h').exists(timeout=10):
self.swipe_up()
i += 1
if i > 100:
self.stop_app()
break
if __name__ == '__main__':
Douyin().run()
mitmdump监听请求部分,获取响应数据,解析入库
import json
import pymysql
def saveDB(data):
conn = pymysql.connect(
host='xx,xx,xx,xx',
user='xx', password='xxx',
database='spider',
charset='utf8')
cursor = conn.cursor()
sql = "INSERT INTO tiktok SET nickname='{}',uid='{}',total_favorited='{}',following_count='{}',follower_count='{}';"
sql = sql.format(data.get('nickname'), data.get('uid'), data.get('total_favorited'), data.get('following_count'),
data.get('follower_count'))
print(sql)
cursor.execute(sql)
conn.commit()
cursor.close()
conn.close()
def response(flow):
if 'https://aweme.snssdk.com/aweme/v1/user/profile/other/?sec_user_id=' in flow.request.url:
print(flow.request.url)
person_response = json.loads(flow.response.text)
person_info = person_response.get("user", "")
if person_info:
info = {
'nickname': person_info.get("nickname", ""),
'total_favorited': person_info.get("total_favorited", 0),
'following_count': person_info.get("following_count", 0),
'uid': person_info.get("uid", ""),
'follower_count': person_info.get("follower_count", 0)
}
saveDB(info)