热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

airtest连接设备黑屏或者运行报错minicap超时问题

前提是各种usb模式都搞完了,连接时黑屏或者一闪而断开连接,或者运行代码提示mincaptimeout之类的东西解决方法,在airtestide连接按

前提是各种usb模式都搞完了,连接时黑屏或者一闪而断开连接,或者运行代码提示 mincap time out之类的东西

解决方法,在airtestide连接按钮时,把其中的javacap勾上

纯代码的话在连接时加上连接参数

cap_method=javacap&touch_method=adb

一个完整的python项目例程,里面用到了大部分poco操作以及连接初始,看一遍自然全都会了

 

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File : 电商爬虫.py
# Author: DaShenHan&道长-----先苦后甜,任凭晚风拂柳颜------
# Date : 2021-01-10from airtest.core.api import *
from airtest.aircv import *
from airtest.core.android.adb import *
from airtest.core.android.android import *import os
import requests
import base64
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
from html.parser import HTMLParser
from db_connect.sqlite_driver import *
from pprint import pprint
html_parser = HTMLParser()
import datetime
sql3 = init_db('result_datas/美菜网商品.db')
PACKAGE = "com.meicai.mall" # 美菜网包名
INSTALL_PATH = "app/美菜商城.apk"def re_text(text):text = text.replace('\xa5','¥')return html_parser.unescape(text) # html转义字符还原def ocr_login(api_key='KbfUHNoabG8Slos64ugqnff4',sdk_key='28GQ5PNNnwKAXy0BxoBvEHF5xtZs1Alf'):host = f'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={api_key}&client_secret={sdk_key}'respOnse= requests.get(host)if response:rep_json = response.json()access_token = rep_json.get('access_token')print('登录成功,获得token:',access_token)return access_tokenreturn Nonedef setup_function():# 连接当前设备# HUAWEI honor 10 分辨率:2280*1080# OPPO R15 分辨率:2280*1080# Vivo x21 分辨率:2280*1080# onePlus 5T 分辨率:2160×1080 poco sevices启动不稳定# xiaomi mix2 元素无法识别# onePlus pocoserver无法启动# device = init_device("Android") # 获取设备号adb = ADB()device = Android() # 获取设备号devicesList = adb.devices() # 获取所有设备列表print('所有设备列表:',devicesList)# connect_device("android:///" + devicesList[1][0]) # 切换手机currentDevice = device.get_default_device()print("现在连接的测试设备:", currentDevice)auto_setup(__file__, logdir=True, devices=[# "android://127.0.0.1:5037/{currentDevice}?cap_method=MINICAP_STREAM&&ori_method=MINICAPORI&&touch_method=MINITOUCH".format(currentDevice=currentDevice),"android://127.0.0.1:5037/{currentDevice}?cap_method=javacap&touch_method=adb".format(currentDevice=currentDevice),])try:device.check_app(PACKAGE) # 检测是否安装了指定的apkprint('apk已存在,正在尝试打开...')except AirtestError: # 安装应用,是否同意覆盖安装,默认否print('检测到未安装指定的apk,正在为你安装,请耐心等待...')device.install_app(INSTALL_PATH, False) # 不覆盖安装print('apk安装完毕')# clear_app(PACKAGE) # 清除数据# uninstall(PACKAGE) # 卸载App# install(INSTALL_PATH) # 安装应用# stop_app(PACKAGE) # 停止应用setup_function() # 连接设备
# api_url = "http://127.0.0.1:8000"
api_url = "http://qianyuan.iask.in:9090"
headers = {'content-type': 'application/x-www-form-urlencoded'}
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)
height = G.DEVICE.display_info['height']
width = G.DEVICE.display_info['width']
pixes = [height, width] # 分辨率access_token = ocr_login()if not access_token:raise UserWarning('登录失败,程序退出')def get_nowtime_hs():dt_ms = datetime.datetime.now().strftime('%Y-%m-%d_%H_%M_%S_%f') # 含微秒的日期时间,来源 比特量化return dt_msdef ocr_price(base_jpg, access_token,is_high):if is_high:request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic"else:request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic"# with open('2815.png.png', 'rb') as f:# img = f.read()# base_jpg = base64.encodebytes(img)params = {"image": base_jpg}access_token = access_tokenrequest_url = request_url + "?access_token=" + access_tokenheaders = {'content-type': 'application/x-www-form-urlencoded'}respOnse= requests.post(request_url, data=params, headers=headers)if response:ret = response.json()if ret.get('error_msg'):print('百度api接口已达上限,统一返回0')price = 0else:result = ret.get('words_result') or []if len(result) > 0:price = ret.get('words_result')[0]['words']else:price = '价格获取失败'return pricereturn 0def get_price(price_ui,save_name):if "/" in save_name:path = save_name.split('/')save_path = '/'.join(path[:-1])os.makedirs(save_path,exist_ok=True)pos = price_ui.get_position() # 取位置size = price_ui.get_size() # 取尺寸pic_loc = price_ui.get_bounds() # 取边缘pic_loc = [pic_loc[3]*width,pic_loc[0]*height,pic_loc[1]*width,pic_loc[2]*height]pos_value = [pos[0]*width,pos[1]*height]size_value = [size[0]*width,size[1]*width]pic_pos = (pos_value[0] - size_value[0] * 0.5, pos_value[1] - size_value[1] * 0.5, pos_value[0] + size_value[0] * 0.5, pos_value[1] + size_value[1] * 0.5)screen = G.DEVICE.snapshot()local_screen = aircv.crop_image(screen, pic_loc)# local_screen = aircv.crop_image(screen, pic_pos)pil_image = cv2_2_pil(local_screen)pil_image.save(f"{save_name}", quality=99, optimize=True) # 读取截图并识别截图中的文字with open(f'{save_name}', 'rb') as f:file = f.read()base_jpg = base64.b64encode(file)encode_jpg = base_jpg.decode()print('开始识别价格图片:', encode_jpg[-20:-12])price_unit = ocr_price(base_jpg,access_token,False) # 调百度云接口识别文字return encode_jpg,price_unitdef get_category(first=0,secOnd=0,wait_time=3):first_cate = poco(name='com.meicai.mall:id/ll_container').child('com.meicai.mall:id/horizontalScrollView').child() # 获取所有大类别。用的时候取第一个first_cate[first].click()first_cate_text = first_cate[first].get_text()first_cate.wait_for_appearance(wait_time)second_cate = poco(name='com.meicai.mall:id/lv_second_category').offspring('com.meicai.mall:id/cate_tv')second_cate_text = second_cate[second].get_text()second_cate[second].click()second_cate.wait_for_appearance(wait_time)return first_cate_text,second_cate_textdef swip_ui(ui_ret):ui_pos = ui_ret.get_position()ui_size = ui_ret.get_size()print(ui_pos, ui_size)# pos_detla = ui_pos[1] - 0.27395833333333336 + ui_size[1]*0.5pos_detla = ui_size[1]print('需要移动:', pos_detla)# ret.swipe('up')ui_ret.swipe([0, -pos_detla])ui_ret.wait(3)global indexprint(f"下次从{index}开始爬.本节点爬取失败:{ui_ret.get_name()}")def swip_up_one(ui_ret):ui_pos = ui_ret.get_position()ui_size = ui_ret.get_size()ui_ret.swipe([0, -ui_size[1]])time.sleep(1)def swip_up2(ui_ret):ui_size = ui_ret.get_size()ui_ret.swipe([0, -2*ui_size[1]])time.sleep(1)def swip_down_one(ui_ret):ui_size = ui_ret.get_size()ui_ret.swipe([0, ui_size[1]])time.sleep(2) # 下拉刷新def get_now_page(cate_name):global index,count,size_hret_list = poco(name='com.meicai.mall:id/lv_goods_list').offspring('android:id/list').offspring(name='com.meicai.mall:id/ll_container')is_goods = ret_list[0].offspring('com.meicai.mall:id/tv_goods_name').exists()if len(ret_list) > 2: # 必须三个以上if not is_goods:ret_list = [ret_list[1], ret_list[2]]else:ret_list = [ret_list[0], ret_list[1]]for ret in ret_list:try:is_goods = ret.offspring('com.meicai.mall:id/tv_goods_name').exists()if not is_goods:print(f"跳过非商品的节点:{ret}")continuenot_Onsale= ret.offspring('com.meicai.mall:id/tv_goods_ssu_price').exists()name = ret.offspring('com.meicai.mall:id/tv_goods_name') # 名称ggs = ret.offspring("com.meicai.mall:id/specLabels").children() # 规格复数ggs_texts = [gg.child().get_text() for gg in ggs] # 规格文本guage = ret.offspring("com.meicai.mall:id/tv_goods_multi_gauge") # 瓜葛guage = guage if guage.exists() else ret.offspring('com.meicai.mall:id/tv_goods_ssu_unitprice')guage_text = guage.get_text() if guage.exists() else "" # 瓜葛文本guage_text = re_text(guage_text)price = ret.offspring('com.meicai.mall:id/tv_goods_price') if not not_onsale else ret.offspring('com.meicai.mall:id/tv_goods_ssu_price') # 价格图片price_text = get_price(price, f'images/{get_nowtime_hs()}.png') # 价格文字 图片编码,文字discount = ret.offspring('com.meicai.mall:id/tvDiscountsPrices') # 折扣discount_text = re_text(discount.get_text()) if discount.exists() else "" # 折扣文本# 销售信息 自营 券满减if not_onsale:sale_info = ret.offspring('com.meicai.mall:id/rl_price_container').child('com.meicai.mall:id/ll_goods_promote_tag').child('android.widget.LinearLayout')else:sale_info = ret.offspring('com.meicai.mall:id/ll_price_container').child('com.meicai.mall:id/ll_goods_promote_tag').child('android.widget.LinearLayout')sale_texts = [sale.child().get_text() for sale in sale_info] # 销售信息文本goods_info = {"seq": f'{index}','cate_name':cate_name,"name": name.get_text(),"gg": '&'.join(ggs_texts),'guage': guage_text,'discount': discount_text,"price": price_text[1],'sale_info': '&'.join(sale_texts),}sql3.save(goods_info=goods_info) # 保存到数据库index += 1print("-----------一条完整商品信息为--------------")print(goods_info) # 打印构造的信息# req = requests.post(api_url, data={"mc": goods_info['name'], "gg": goods_info['gg'], "tp": goods_info['price'][1]},headers=headers)# print(req.text)except Exception as e:name = ret.offspring('com.meicai.mall:id/tv_goods_name')if name.exists():print(name.get_text(),f"爬取失败,开始向上滑动\n{e}")else:print(ret, f"爬取失败,开始向上滑动\n{e}")swip_up_one(ret)swip_up2(ret_list[-1]) # 按列表中最后一个节点向上滑动两格def main(number=300):global index,countindex = count = 1# first, secOnd= get_category()# cate_name = f'{first}/{second}'cate_name = f'未定义'print(f'正在爬取 {cate_name} 下所有商品...')ui_root = poco(name='com.meicai.mall:id/lv_goods_list').offspring('android:id/list').offspring(name='com.meicai.mall:id/ll_container')global size_h # 全局变量每个菜看板高度size_h = ui_root.get_size()[1]# swip_down_one(ui_root) # 下拉刷新num = 0while num

 


推荐阅读
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • MySQL锁--(深入浅出读书笔记)
    MySQL锁的概述1.针对不同的引擎,采用不同的锁机制;(表锁,页面锁,行锁)myisam和memory存储引擎:表级锁;BOB存储引擎:页面锁,表级 ... [详细]
  • 微服务应用性能分析实战15 数据磐石:APM 收集端的存储模型
    分布式监控的重要设计就是数据存储模型,而SkyWalking的分布式追踪数据模型就是一个经典代表,这也是它会在APM领域脱颖而出的原因。所以今天我就以 ... [详细]
author-avatar
U曹宸prideX_J
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有