参考文章:
python鬼才利用appium实现手机APP自动化!
下载源参考:
win10环境下,appium和python3的安装和配置
node.js下载:
官网
jdk下载:
华军软件园
android下载:http://tools.android-studio.org/index.php/sdk/
appium下载:
下载之家 Appium 官方版v1.8.0
app页面元素的有哪些属性,参考:
python+appium获取元素属性值
我安装的时候碰到一个坑:就是jdk、Android-sdk的环境变量配置与python的配置模式不一样。
生产使用了逍遥多开模拟器,该app使用默认Android5版本时,运行不成功,尝试了Android7和Android4.4维护版,最终只能在4.4版本上运行成功。
遇到的问题:
以下是写的一个简单操作类:
# -*- coding: UTF-8 -*-
import copy
from appium import webdriver
class AppDriver(object):
def __init__(self, platformName, deviceName, platformVersion, appPackage, appActivity, host, port):
self.driver = None
self.device_name = deviceName
self.platform = platformName
self.platform_version = platformVersion
self.app_package = appPackage
self.app_activity = appActivity
self.host = host
self.port = port
self.create_driver()
self.x = self.driver.get_window_size()["width"]
self.y = self.driver.get_window_size()["height"]
def create_driver(self):
options = {
'platformName': self.platform,
'deviceName': self.device_name,
'platformVersion': self.platform_version,
'appPackage': self.app_package,
'appActivity': self.app_activity
}
self.driver = webdriver.Remote(f'http://{self.host}:{self.port}/wd/hub', options)
def get_page_elements_id(self, need_print=False):
elements = self.driver.find_elements_by_xpath('//*')
id_dict = {}
all_text = []
for element in elements:
if need_print:
print('======')
print(element.get_attribute('className'))
print(element.text)
print(element.get_attribute('name'))
print(element.get_attribute('resourceId'))
print('=======')
if element.text:
all_text.append(element.text)
resource_id = element.get_attribute('resourceId')
if resource_id and element.text:
id_dict[resource_id] = element.text
return id_dict, all_text
def swipe_down(self, start_y=0.6, stop_y=0.9, duration=200):
# 按下手机屏幕,向下滑动
# 注意,向下滑时,x轴不变,要不然就变成了斜向下滑动了
# @duration:持续时间
x1 = int(self.x * 0.5)
y1 = int(self.y * start_y)
x2 = int(self.x * 0.5)
y2 = int(self.y * stop_y)
# print x1,y1,x2,y2
self.driver.swipe(x1, y1, x2, y2, duration)
def swipe_left(self, star_x=0.75, stop_x=0.25, duration=300):
# 按下手机屏幕,向左边滑动
# 注意,向左边滑时,y轴不变
# @duration:持续时间
x1 = int(self.x * star_x)
y1 = int(self.y * 0.5)
x2 = int(self.x * stop_x)
y2 = int(self.y * 0.5)
# print x1,y1,x2,y2
self.driver.swipe(x1, y1, x2, y2, duration)
def swipe_right(self, star_x=0.25, stop_x=0.75, duration=300):
# 按下手机屏幕,向右边滑动
# 注意,向左边滑时,y轴不变
# @duration:持续时间
x1 = int(self.x * star_x)
y1 = int(self.y * 0.5)
x2 = int(self.x * stop_x)
y2 = int(self.y * 0.5)
# print x1,y1,x2,y2
self.driver.swipe(x1, y1, x2, y2, duration)
def swipe_up(self, start_y=0.9, stop_y=0.6, duration=300):
# 按下手机屏幕,向上滑动
# 注意,向上滑时,x轴不变,要不然就变成了斜向下滑动了
# @duration:持续时间
x1 = int(self.x * 0.5)
y1 = int(self.y * start_y)
x2 = int(self.x * 0.5)
y2 = int(self.y * stop_y)
# print x1,y1,x2,y2
self.driver.swipe(x1, y1, x2, y2, duration)
def find_element_by_text(self, text):
return self.driver.find_element_by_android_uiautomator(f'text(\"{text}\")')
def click_text(self, text):
try:
node = self.find_element_by_text(text)
except:
node = self.find_element_by_text_startswith(text)
node.click()
return 1
def find_id(self, resource_id):
return self.driver.find_element_by_id(resource_id)
def click_id(self, resource_id):
self.find_id(resource_id).click()
def get_text_of_id(self, resource_id):
return self.find_id(resource_id).text
def find_element_by_text_startswith(self, text):
loc = f'new UiSelector().textStartsWith("{text}")'
return self.driver.find_element_by_android_uiautomator(loc)
def send_key_to_element_by_id(self, resource_id: str, text: str):
node = self.driver.find_element_by_id(resource_id)
node.send_keys(text)
def wait(self, sec):
self.driver.implicitly_wait(sec)
def close(self):
self.driver.close_app()
# adb命令
# adb shell pm list packages -f # 获取app名称列表
# adb shell
# dumpsys activity | grep mFocusedActivity 获取 appPackage和 appActivity
# :/data/app/com.xmeng.ued-1.apk=com.xmeng.ued
desired_caps = {
'platformName': 'Android',
'deviceName': 'emulator-5554',
'platformVersion': '4.4',
'appPackage': 'com.xmeng.ued',
'appActivity': 'XMMainActivity',
'host': '127.0.0.1',
'port': 4723, # appium端口
}
driver = AppDriver(**desired_caps)
driver.click_text('北京')
# 打印页面元素
driver.get_page_elements_id(need_print=True)
driver.click_id('com.xmeng.ued:id/function4')
def find_destination_text(resource_id):
# 获取目标文本,未成功就向上滑动直到成功
res = ''
while not res:
try:
res = driver.get_text_of_id(resource_id)
return res
except:
driver.swipe_up()
# 职业介绍数据
def find_zyjs_data(data):
# 获取某个页面的指定数据
driver.click_text('职业介绍')
tasks = {
'job_define': 'com.xmeng.ued:id/jabDefinitionTV',
'job_intro': 'com.xmeng.ued:id/job_introduce',
'job_task': 'com.xmeng.ued:id/jobTask',
'job_learn_skill': 'com.xmeng.ued:id/joblearnskill',
'job_skill': 'com.xmeng.ued:id/jobskill',
}
for k, task in tasks.items():
if k == 'job_task':
res = find_destination_text(task)
if '工作考核要求' in res:
data['job_responsibility'] = res.split('工作考核要求:')[0]
data['job_require'] = '工作考核要求:' + res.split('工作考核要求:')[1]
else:
data['job_responsibility']=''
data['job_require']=''
else:
data[k] = find_destination_text(task)
driver.click_text('返回')
return data
def click_text_util_success(text):
res = ''
times = 0
while not res:
try:
res = driver.click_text(text)
except:
if times < 10:
driver.swipe_up()
# 怎么判断是否滑动到底部 ,通过两次页面的元素一样,但比较耗时
else:
driver.swipe_down()
times += 1
if times > 22:
print('==========', text)
break
def find_one_cate(cate):
function4 = 0
while not function4:
try:
driver.click_id('com.xmeng.ued:id/function4')
function4 = 1
except:
driver.click_text('返回')
driver.click_text(cate)
data = {
'big_profession': '',
'profession': '',
'job_define': '',
'job_intro': '',
'job_responsibility': '',
'job_require': '',
'job_learn_skill': '',
'job_skill': '',
}
for kind_name in ALL_KINDS[cate]:
# 去重
hash_txt = redis_cli.hash_md5(kind_name)
if redis_cli.exist(hash_txt):
continue
click_text_util_success(kind_name)
driver.wait(2)
kind_data = find_zyjs_data(data=copy.deepcopy(data))
kind_data['big_profession'] = cate
kind_data['profession'] = kind_name
# 保存数据
mysql_cnn.save_many(save_sql, save_data=[list(kind_data.values())])
redis_cli.add(hash_txt)
print(f'完成职业类:{cate} 数据采集')
def main():
for cate in cate_list:
try:
find_one_cate(cate)
except:
pass
driver.close()
if __name__ == '__main__':
main()