學以緻用~使用 Appium 模拟人類操控手機行為
V2.0在手機上運作,目前實作以下功能:
1.小黑屋模式,一分鐘内給好友發100條消息然後進了好友的小黑屋
2.定時發消息提醒對象多喝熱水~
3.對指定好友QQ空間說說自動進行點贊、評論、留言、轉發
4.所有贊過自己QQ名片背景牆的好友進行點贊
理論上可以模拟一切人類手指操控手機的行為
技術棧:
Appium + Python + ADB 安卓測試橋
核心部分源碼如下:
(純自己寫的,如有您有更好的實作方式請留言)
`
from appium import webdriver
from time import sleep
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.support.wait import WebDriverWait
import datetime
desired_caps = dict()
desired_caps['unicodeKeyboard'] = True #設定編碼格式為unicode
desired_caps['resetKeyboard'] = True #隐藏手機鍵盤
手機參數
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '9'
desired_caps['deviceName'] = 'anyone'
url = 'http://localhost:4723/wd/hub'
應用參數
desired_caps['appPackage'] = 'com.tencent.mobileqq'
desired_caps['appActivity'] = 'com.tencent.mobileqq.activity.SplashActivity' #QQ登入界面
driver = webdriver.Remote(url,desired_caps) #擷取driver
driver.implicitly_wait(15) #隐式等待
登入賬号密碼
datas={}
datas['login_usr'] = "登入的QQ号"
datas['passwd'] = "登入的密碼"
datas['searched_qq_number'] = {
'first':'在此輸入想要查找的QQ号',
'second':'在此輸入想要查找的QQ号',
'third':'在此輸入想要查找的QQ号',
'forth':'在此輸入想要查找的QQ号',
'fifth':'在此輸入想要查找的QQ号'
''
}
chat_mesage = {}
chat_mesage["問候語"]="你好!"
chat_mesage["段子"]= {
"段子0":"有的女孩真的很講道理的,隻要你道歉态度誠懇,哪怕你根本就沒錯,她們也會原諒你的。",
"段子1":"所有人都關心你飛的高不高 累不累 隻有我不一樣 我不關心你。"
}
def login():
"""
1.登入
:return:
"""
# 登入界面同意協定
driver.find_element_by_xpath("//*[@text='同意']").click()
# 點選登入按鈕
driver.find_element_by_xpath("//*[@text='登入']").click()
# 點選賬号框并輸入賬号(todo:參數化,由外部檔案讀取)
ele = driver.find_element_by_xpath("//*[@text='QQ号/手機号/郵箱']")
ele.click()
ele.send_keys(datas['login_usr'])
sleep(2)
# 點選密碼框輸入密碼(todo:參數化,由外部檔案讀取)
ele = driver.find_element_by_xpath("//*[@text='輸入密碼']")
ele.click()
ele.send_keys(datas['passwd'])
# 點選登入按鈕
driver.find_element_by_id("com.tencent.mobileqq:id/login").click()
# 權限申請點選【去授權】按鈕
driver.find_element_by_id("com.tencent.mobileqq:id/dialogRightBtn").click()
# 權限請求點選允許(适用于VIVO)
# driver.find_element_by_xpath("//*[@text='允許']").click()
# #點選權限授權确定按鈕(适用于華為pad)
driver.find_element_by_id("android:id/button1").click()
return
login()
class EnterIntoChatPage():
"""
1.進入聊天界面
2.發送消息
3.定時發送消息
"""
def __init__(self, searched_qq_number, message, start_time='', end_time='', ontime_message=''):
"""
:param searched_qq_number: 被查找的QQ号碼
:param message: 要發送的消息
:param start_time: 定時發送消息模式開始時間,預設為空
:param end_time: 定時發送消息模式截止時間,預設為空
:param ontime_message: 定時發送消息内容,預設為空
"""
self.searched_qq_number = searched_qq_number
self.message = message
self.start_time = start_time
self.end_time = end_time
self.ontime_message = ontime_message
def enter_chat_page(self):
"""
1.進入聊天界面
:return:
"""
# 1.找到搜尋框并進行點選
driver.find_element_by_xpath("//*[@content-desc='搜尋']").click()
# 2.向搜尋框中輸入要查找的QQ号(todo:datas['searched_qq_number']['first']first需要修改)
# driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/et_search_keyword']").send_keys(self.searched_qq_number)
driver.find_element_by_id("com.tencent.mobileqq:id/et_search_keyword").send_keys(self.searched_qq_number)
sleep(2)
# 3.點選搜尋出聯系人進入聊天界面
driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/image']").click()
def send_message(self):
"""
1.發送資訊
"""
# 1.點選聊天界面消息輸入框并将消息輸入輸入框
ele = driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/input']")
ele.click()
# TODO:互動實作實時對話
for i in range(1): #range(1)預設為1,小黑屋模式可指定對應數字
ele.send_keys(message)
# 2.點選發送消息按鈕
driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/fun_btn']").click()
def send_message_on_time(self):
"""
用于定時發送消息
"""
while True:
# 擷取目前系統時間,如果時間是2021-01-23 13:00:00,發送指定消息
curr_time = datetime.datetime.now()
time_str = datetime.datetime.strftime(curr_time, '%Y-%m-%d %H:%M:%S')
if self.start_time <= time_str <= self.end_time:
# 向輸入框輸入消息
ele = driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/input']")
ele.click()
ele.send_keys("定時發送消息測試,目前時間是 "+ time_str + "要發送的消息是:" + self.ontime_message)
# 點選發送按鈕
driver.find_element_by_xpath("//*[@text='發送']").click()
break
elif time_str <= self.start_time:
pass
else:
pass
---------------以下是對EnterIntoChatPage()類的測試---------------
searched_qq_number = datas['searched_qq_number']['second']
message = chat_mesage["段子"]["段子0"]
start_time='2021-01-23 13:33:00'
end_time='2021-01-23 13:33:59'
ontime_message='你好'
action = EnterIntoChatPage(searched_qq_number, message,start_time,end_time,ontime_message)
action.enter_chat_page()
action.send_message()
action.send_message_on_time()
action.enter_personal_data_page()
---------------------------------------------------------------
class EnetrQzone():
"""
用于進入個人資訊展示頁面進行點贊和進入QQ空間
1.首先進入個人資訊展示頁面
2.點贊
3.進入QQ空間
"""
def int(self):
""""""
def enter_personal_data_page(self):
"""
1.在聊天界面點選右上角【聊天設定】按鈕
2.點選個人頭像和昵稱一欄進入個人資訊展示界面
3.進入個人資訊展示頁面
"""
#1.調用EnterIntoChatPage()類的enter_chat_page()方法進入聊天界面
EnterIntoChatPage(searched_qq_number, message,start_time,end_time,ontime_message).enter_chat_page()
#2.點選在聊天界面點選右上角【聊天設定】按鈕
driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/ivTitleBtnRightImage']").click()
#3.點選個人頭像和昵稱一欄進入個人資訊展示界面
driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/clv']").click()
sleep(5)
def give_like(self):
"""
點贊
TODO:贊顯示為花樣贊時,無法進行點贊
"""
pass
def qzone_like(self):
"""
1.對個人QQ空間進行點贊
2.通過對話框界面進入,調用send_message函數
:return:
"""
# 1.點選進入空間的按鈕(進行判斷,若已經開通了小世界,則第二個入口為QQ空間,否則為第一個)
elements = driver.find_elements_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/dkv']")
elements[0].click()
#2.判斷空間是否是禁止通路的狀态
'''
if driver.find_element_by_xpath("//*[@text='主人設定了權限']"):
print("主人設定了權限")
# 發送傳回鍵模拟手機傳回按鈕
driver.press_keycode(4)
else:
pass
'''
# 首次進入空間需要滑動一段距離,以防點贊按鈕加贊不處理來
# sleep(3)
origin_ele = driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/c53']")
destination_ele = driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/hto']")
driver.drag_and_drop(origin_ele, destination_ele)
# 先找昵稱和說說發表時間所在的方框,進行周遊
while True:
elements = driver.find_elements_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/c7p']")
print("Current page click_like_button number is:" + str(len(elements)))
# if current page click_lkie_button number is one,click it one times
if len(elements) == 1:
elements[0].click()
# pass
# if current page click_like_button number >=2,the button is iterated over
elif len(elements) >= 2:
elements[1].click()
# pass
print("------------點贊一輪結束---------------")
origin_eles = driver.find_elements_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/c7y']")
destination_eles = driver.find_elements_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/c4r']")
print("Current page origin_eles numbers:" + str(len(origin_eles)))
print("Current page destination_eles numbers:" + str(len(destination_eles)))
# if current page only have one origin_eles and one destination_eles,direct use of
if len(origin_eles) == 1 and len(destination_eles) == 1:
driver.drag_and_drop(origin_eles[0],destination_eles[0])
# if current page have two desttination_eles and one origin_eles,than Slide from the destination_eles[1] to the destination_eles[1]
elif len(destination_eles) == 2 and len(origin_eles) == 1:
driver.drag_and_drop(destination_eles[1],destination_eles[0])
# if current page have two desttination_eles and one origin_eles,than Slide from the origin_eles[1] to the origin_eles[0]
elif len(origin_eles) == 2 and len(destination_eles) == 1:
driver.drag_and_drop(origin_eles[1],origin_eles[0])
# 如果目前頁面有2個滑動起點和2個滑動終點,那麼從第2個滑動終點滑動到第1個滑動終點
elif len(origin_eles) == 2 and len(destination_eles) == 2:
driver.drag_and_drop(destination_eles[1],destination_eles[0])
# 如果目前界面有1個滑動起點和0個滑動終點
elif len(origin_eles) == 1 and len(destination_eles) == 0:
origin_ele = driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/c4r']")
destination_ele = driver.find_element_by_xpath("//*[@resource-id='com.tencent.mobileqq:id/c7y']")
driver.drag_and_drop(origin_ele, destination_ele)
# 如果目前界面有1個滑動終點和0個滑動起點
elif len(destination_eles) == 1 and len(origin_eles) == 0:
pass
---------------以下是對EnetrQzone(EnterIntoChatPage)類的測試---------------
action = EnetrQzone()
action.enter_personal_data_page()
action.qzone_like()
---------------------------------------------------------------
`