# -*- encoding=utf8 -*- __author__ = "xingdao_1" from airtest.core.api import * from poco.drivers.android.uiautomation import AndroidUiautomationPoco poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False) auto_setup(__file__) xy = poco.get_screen_size() x = xy[0] y = xy[1] # swipe((x*0.9,y*0.5),(x*0.1,y*0.5),duration=1) poco(desc="小蓝本企业查询").click() print("*************************************") # sleep(4) # poco(name="com.itjuzi.app:id/iv_logo").click() # poco(text="默认排序").click() # poco(text="更新时间").click() # poco("android.widget.LinearLayout").click() # num = 0 # while 1: # num += 1 # info_list = poco(name = "com.itjuzi.app:id/company_new_name_txt") # title_list = [title.get_text() for title in info_list] # for title in title_list: # print(title) # poco(text=title).click() # sleep(1)
def main(DeviceNum): # 多设备连接时,可指定设备编号 # python -m airtest run main.py --device Android://127.0.0.1:5037/0123456789ABCDEF # device = Android('GWY0216C16002906') # 设备类型 1 手机[720,1280][1080,1920] 2平板[1200,1920] # DeviceNum = 'c5bac654' NeedSwipe = ['CLB0218414001154', 'DLQ0216824000142', 'E4J4C17405011422', 'APU0216530000778', 'APU0216408028484', 'APU0216111008105'] try: DbContext = DbHelper() DeviceType = 0 device = Android(DeviceNum) # device.adb.start_shell("su") # device.adb.start_shell("wipe data") # device.adb.start_shell("wipe cache") # device.adb.start_cmd("adb reboot") if '0123456789ABCDEF' not in DeviceNum: device.wake() # 唤醒页面 poco = AndroidUiautomationPoco(device) # if DeviceNum in NeedSwipe: poco.swipe([0.4, 0.9], [0.4, 0.55], duration=0.1) time.sleep(2) # 复位一下,防止之前没有睡眠也滑动 poco.swipe([0.4, 0.45], [0.4, 0.9], duration=0.1) else: poco = AndroidUiautomationPoco( use_airtest_input=True, screenshot_each_action=False) # ClearMemory(device,poco,'') # return device_screen = poco.get_screen_size() device_x = device_screen[0] device_y = device_screen[1] print(str(device_y), str(device_x)) if device_y > 1600 and device_x > 1080: DeviceType = 2 else: DeviceType = 1 if DeviceType == 0: print( '\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~o(╥﹏╥)o 设备型号无法确定 o(╥﹏╥)o~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') DbContext.AddLog(DeviceNum, 3, '设备[' + DeviceNum + ']型号无法确定') return elif DeviceType == 1: print( '\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~O(∩_∩)O 设备型号为手机 O(∩_∩)O~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n') else: print( '\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~O(∩_∩)O 设备型号为平板 O(∩_∩)O~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n') except Exception as e: print('\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~o(╥﹏╥)o 设备连接异常 o(╥﹏╥)o~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') DbContext.AddLog( DeviceNum, 3, "设备[" + DeviceNum + "]连接异常:" + repr(e).replace("'", "")) else: BackHomeStatus = BackHomePage( poco, DbContext, DeviceNum, device) # 返回首页 if BackHomeStatus: mode = DbContext.GetDeviceRunningMode(DeviceNum) taskList = [] # 获取当前设备要抓取的城市 IsRunning = True if mode == 1: taskList = DbContext.GetDeviceTask(DeviceNum) elif mode == 2: taskList = DbContext.GetDeviceTaskByMode2() elif mode == 3: taskList = DbContext.GetDeviceTaskByMode3() elif mode == 5: IsRunning = False elif mode == 6: # 根据店名爬取 while True: data = get_shopName() id_name_addr_city = data[0] shopid = id_name_addr_city[0] storeName = id_name_addr_city[1] addr = id_name_addr_city[2] city = (id_name_addr_city[3])[:-1] print(storeName, addr, city) if data[1] == 3: crawl_status_code(storeName, 3) else: crawl_status_code(storeName, 1) search_store(storeName, poco, device, addr, city, shopid) BackHomePage(poco, DbContext, DeviceNum, device) crawl_status_code(storeName, 2) if(len(taskList) == 1): # 更新任务为运行中 DbContext.UpdateTaskStatus( int(taskList[0]['TaskId']), 1, 0, mode) while IsRunning: BackHomeStatus = BackHomePage( poco, DbContext, DeviceNum, device) # 返回首页 if BackHomeStatus: for task in taskList: # AddressList(task['TargetCity']) #获取未抓取的坐标点 AllPosition = [ {'RepresentativeAdress': task['RepresentativeAdress'], 'Genhash':task['Genhash']}] taskId = task['TaskId'] cityCode = task['CityCode'] # 更新任务为运行中 DbContext.UpdateTaskStatus(int(taskId), 1, 0, mode) # 计时 StartTime = datetime.datetime.now() # 返回值需要写进队列 currentTaskResult, IsEmergencyStop = StartCapture( poco, AllPosition, DeviceType, task['TargetCity'], DeviceNum, cityCode, device) # 抓取数据 # 没有紧急置停的情况下才完成后续的更新 if not IsEmergencyStop: EndTime = datetime.datetime.now() DbContext = DbHelper() DbContext.AddLog(DeviceNum, 2, '设备[' + DeviceNum + ']本次抓取[' + AllPosition[0]['RepresentativeAdress'] + '] [' + str( len(currentTaskResult)) + '] 家店,耗时:' + str(((EndTime - StartTime).seconds)/60)) # 更新任务为完成 DbContext.UpdateTaskStatus( int(taskId), 2, len(currentTaskResult), mode) # 将任务的执行结果回写到队列 if mode != 3: Produce = SendMessage() result = Produce.sendMessage( taskId, currentTaskResult) if result: # 将任务状态改为已回写队列 DbContext.UpdateTaskStatus( int(taskId), 3, len(currentTaskResult), mode) else: break mode = DbContext.GetDeviceRunningMode(DeviceNum) if len(taskList) > 0: taskList.clear() if mode == 1: taskList = DbContext.GetDeviceTask(DeviceNum) elif mode == 2: taskList = DbContext.GetDeviceTaskByMode2() elif mode == 3: taskList = DbContext.GetDeviceTaskByMode3() elif mode == 5: print( '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~O(∩_∩)O 紧急置停 O(∩_∩)O~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') break if len(taskList) > 0: print( '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~O(∩_∩)O 抽取一条任务 O(∩_∩)O~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') else: print( '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~O(∩_∩)O 任务执行完毕 O(∩_∩)O~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') break else: DbContext.AddLog( DeviceNum, 3, '设备[' + DeviceNum + ']返回首页异常') break else: DbContext.AddLog(DeviceNum, 3, '设备[' + DeviceNum + ']返回首页异常')
class Aloha(object): def __init__(self): connect_device( "android://127.0.0.1:5037/4f74b1cc?cap_method=MINICAP_STREAM&&ori_method=MINICAPORI&&touch_method=MINITOUCH") self.poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False) self.screenWidth, self.screenHeight = self.poco.get_screen_size() self.total = 0 self.loop_users() def like_people(self): poco_like = self.poco("com.cupidapp.live:id/followImageView") if poco_like.exists(): self.watcher() poco_like.click() self.total += 1 print("喜欢了 %s 人" % self.total) back = self.poco("com.cupidapp.live:id/leftImageView") if back.exists(): self.watcher() back.click() def like_post(self): post_list = self.poco("com.cupidapp.live:id/profilePostCoverImageView") if len(post_list) > 0: self.watcher() if post_list[0].exists(): post_list[0].click() sleep(1) # swipe((self.screenWidth * 0.5, self.screenHeight * 0.5), vector=[0, -0.5], duration=1) detail_list = self.poco("com.cupidapp.live:id/feedRecyclerView").children() if detail_list.exists(): detail_item = detail_list[0] if detail_item.exists(): like = detail_item.offspring("com.cupidapp.live:id/feedPraiseButton") if like.exists(): self.watcher() like.click() print("点赞一条动态") back = self.poco("com.cupidapp.live:id/leftImageView") if back.exists(): self.watcher() back.click() def loop_users(self): date = time.strftime("%Y年%m月%d日", time.localtime()) self.total = collection.count_documents({"record_date":date}) start_app("com.cupidapp.live") self.watcher() while True: sleep(1) # self.some_one_like_you() blur_list = self.poco("com.cupidapp.live:id/userAgeAndInfoTextView") if blur_list.exists(): if blur_list[0].exists(): self.watcher() blur_list[0].click() self.watcher() swipe((self.screenWidth * 0.5, self.screenHeight * 0.7), vector=[0, -0.5], duration=1) count = self.poco("com.cupidapp.live:id/postCountTitleTextView") post_count = "" if count.exists(): post_count = count.get_text() dest = self.poco("com.cupidapp.live:id/profileDescriptionTextView") post_dest = "" if dest.exists(): post_dest = dest.get_text() print("pos_count:%s,pos_des is :%s" % (post_count, post_dest)) desc_list = self.poco("com.cupidapp.live:id/specContentTextView") if len(desc_list) > 0: for item in desc_list: print(item.get_text()) if post_count != "暂无动态": self.like_post() # 点击喜欢 self.like_people() else: self.watcher() back = self.poco("com.cupidapp.live:id/leftImageView") if back.exists(): self.watcher() back.click() else: self.watcher() if self.total > 800: break def watcher(self): print("-----------------------弹窗检测启动") # 目标元素 com.cupidapp.live:id/messageSend find_element = self.poco("com.cupidapp.live:id/closeImageView") if find_element.exists(): find_element.click() print("发现元素") else: print("-----------------------等待0.5秒,当前时间:",time.strftime("%H:%M:%S", time.localtime())) time.sleep(0.5) # 定义子线程: 循环查找目标元素 # p = Process(target=self.loop_watcher, args=(find_element,)) # p.start() def skip_old(self): pass
class TaoBao(object): def __init__(self, key, *args): self.poco = AndroidUiautomationPoco(screenshot_each_action=False) auto_setup(__file__) # 搜索关键字 self.key = key # 浏览商品详情的时间,默认时长为20s if len(args) == 1 or len(args) == 2: self.browser_detail_time = args[0] else: self.browser_detail_time = 20 # 浏览评论的时长,默认时长为5s self.browser_evalute_time = args[1] if len(args) == 2 else 5 # 待匹配的商品主图 self.main_img_path = '' def run(self): # 1、准备工作,打开淘宝客户端 self.__pre() # 2、根据关键字,搜索商品 self.__search_good_by_key() # 3、剪切图片,拿到商品主图 self.main_img_path = crop_main_img('./333.jpeg') # 4、滑动,从列表中匹配商品 self.__search_good_from_list() # 5、收藏商品 self.__collect_good() # 6、浏览商品 self.__browser_good_detail() # 7、查看评论 self.__browser_good_evalute() # 8、购买 self.__buy_good() # 9、获取订单编号 order_no = self.__get_order_no() # 10、截取订单截图页面 screenshot_pic_result = self.get_order_pic() print(f'购买完成!\n订单号为:{order_no}\n订单截图路径:{screenshot_pic_result}') def __collect_good(self): """ 收藏商品 :return: """ # 滑动一次,使顶部Tab显示出来 self.__swipe(True) self.__swipe(True) # 判断商品是否收藏 fav_element = self.poco('com.taobao.taobao:id/fav_title') if fav_element.get_text() == '收藏': print('开始收藏...') fav_element.parent().children()[0].click() back_keyevent() else: print('商品已经收藏') def __pre(self): """ 准备工作 :return: """ # 删除缓存文件 remove_cache('./part.jpg', './screenshot.png', './uidump.xml') home() stop_app(package_name) start_my_app(package_name, activity) def __search_good_by_key(self): """ 通过关键字搜索商品 :return: """ self.poco(id_page_main_button_search).wait(5).click() # perform_view_id_click(poco, id_page_main_button_search) perform_view_input(self.poco, id_page_search_edittext_search, self.key) # 点击搜索 self.poco(id_page_search_button_search).wait_for_appearance() while self.poco(id_page_search_button_search).exists(): print('点击一次搜索') perform_view_id_click(self.poco, id_page_search_button_search) # 等待列表加载出来 self.poco(id_page_goods_rv).wait_for_appearance() def __search_good_from_list(self): """ 从列表中匹配商品 :return: """ # 循环的图片查找 while True: try: pos = loop_find(Template(self.main_img_path), timeout=10, threshold=0.95) except TargetNotFoundError: print('滑动一页') # self.poco.swipe([0.5, 0.8], [0.5, 0.4], duration=0.2) self.__swipe(True) else: print('找到了') # poco.click([100.0 / 1920, 100.0 / 1080]) print(pos) # 屏幕宽度和高度 screen_size = self.poco.get_screen_size() print(screen_size) # 点击的坐标点(宽、高) # (0.22407407407407406, 0.8550925925925926) position_click = (pos[0] / screen_size[0], pos[1] / screen_size[1]) print(position_click) self.poco.click(position_click) break def __swipe(self, up_or_down): """ 滑动单条新闻 :param up_or_down: true:往上滑动;false:往下滑动【慢慢滑动】 :return: """ if up_or_down: self.poco.swipe([0.5, 0.8], [0.5, 0.4], duration=0.2) else: self.poco.swipe([0.5, 0.4], [0.5, 0.8], duration=0.2) def __browser_good_detail(self): """ 浏览商品 :return: """ # 切换到详情Tab self.poco('com.taobao.taobao:id/taodetail_nav_bar_tab_text', text='详情').click() # 滑动时长为: self.browser_detail_time browser_start = datetime.datetime.now() browser_end = browser_start while (browser_end - browser_start).seconds < self.browser_detail_time: # 休眠一会 time.sleep(random.randint(2, 5)) # 滑动一次 self.__swipe(True) # 结束时间 browser_end = datetime.datetime.now() print('详情页面查看完毕') def __browser_good_evalute(self): """ 查看评论 :return: """ print('查看评论') # 切换到详情Tab self.poco('com.taobao.taobao:id/taodetail_nav_bar_tab_text', text='评价').click() # 查看全部评论 self.poco('com.taobao.taobao:id/mainpage').offspring( text='查看全部').click() browser_start = datetime.datetime.now() browser_end = browser_start while (browser_end - browser_start).seconds < self.browser_evalute_time: # 休眠一会 time.sleep(random.randint(2, 5)) # 滑动一次 self.__swipe(True) # 结束时间 browser_end = datetime.datetime.now() print('评价页面查看完毕') def __buy_good(self): """ 购买商品 :return: """ # 立即购买 self.poco('com.taobao.taobao:id/detail_main_sys_button', text='立即购买').click() # 选择商品属性 sleep(10) # 确定购买 self.poco('com.taobao.taobao:id/confirm_text', text='确定').parent().click() # 提交订单 self.poco(text='提交订单').click() # 手动输入密码或者指纹 sleep(10) def __get_order_no(self): """ 获取订单编号 :return: """ global copy_element while True: # 由于手机屏幕的限制,【复制】按钮第一页不一定能显示出来 try: copy_element = self.poco(text='复制') except Exception as e: print('没有找到元素,往下滑动一页') self.__swipe(True) break copy_element.click() # 从剪切板拿到数据 result = exec_cmd('adb shell am broadcast -a clipper.get')[1] # 匹配出订单号 result = re.findall(r'data="(.*)"', result) order_no = '' if result and len(result) > 0: order_no = result[0] print(order_no) return order_no def get_order_pic(self): """ 拿到订单截图界面 :return: """ screenshot_pic_result = './order_screenshot.png' # 截取手机当前屏幕 exec_cmd('adb shell /system/bin/screencap -p /sdcard/screenshot.png') # 保存到PC端 exec_cmd('adb pull /sdcard/screenshot.png %s' % screenshot_pic_result) return screenshot_pic_result
Author:henly Date:2021/4/13 """ from airtest.core.api import * from poco.drivers.android.uiautomation import AndroidUiautomationPoco from multiprocessing import Process import pymongo import logging logger = logging.getLogger("airtest") logger.setLevel(logging.ERROR) connect_device( "android://127.0.0.1:5037/4f74b1cc?cap_method=MINICAP_STREAM&&ori_method=MINICAPORI&&touch_method=MINITOUCH") poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False) s_width,s_height = poco.get_screen_size() def start(): start_app("com.cupidapp.live") while True: sleep(2) froz_poco = poco.freeze() chat_list = poco("com.cupidapp.live:id/sessionUserAvatarImageView") sleep(1) if chat_list.exists(): for chat in chat_list: if chat.exists(): watcher() chat.click()
# 要抓取的 app 名称 PACKAGE_NAME = 'com.goldze.mvvmhabit' # 声明了 AndroidUiautomationPoco 对象,赋值为 poco,即获得了 App 的操作句柄 poco = AndroidUiautomationPoco() # 设备唤醒,手机可能处于息屏状态 poco.device.wake() # 调用了 stop_app 和 start_app 并传入 app 包名实现了 App 的重启,确保是从头开始抓取的。 stop_app(PACKAGE_NAME) start_app(PACKAGE_NAME) auto_setup(__file__) # 获取屏幕宽度高度 screenWidth, screenHeight = poco.get_screen_size() # 定义一个列表,用于保存电影名称 viewed = [] current_count, last_count = len(viewed), len(viewed) # 定义了一个无限循环,提取的是 android.support.v7.widget.RecyclerView # 里面的 android.widget.LinearLayout 子节点,会一次性命中多个 while True: last_count = len(viewed) result = poco('android.support.v7.widget.RecyclerView').child( 'android.widget.LinearLayout') result.wait(timeout=10) # for 循环遍历了每个节点,获取到了其中的 android.widget.TextView 节点, # 并用 get_text 提取了文本值,保存到 viewed 变量里面并去重,电影名称 for item in result:
class Mock_GPS(object): def __init__(self): self.poco = AndroidUiautomationPoco(screenshot_each_action=False) auto_setup(__file__) self.location = '故宫' self.msg = "这是一条心情" # 图片数目 self.image_num = 1 def run(self, location, msg): # 1、打开FackLocation,模拟位置 self.location = location self.msg = msg self.__mock_location() # 2、开启模拟 # 判断模拟位置是否打开,如果没有打开,需要进行打开操作 self.__start_mock() # 3、回到桌面 home() # 4、导入图片到手机相册内 self.__import_image_to_dcim() # 5、打开微信 stop_app(package_name_weixin) start_my_app(package_name_weixin, activity_weixin) # 6、打开朋友圈 self.__open_friend_circle() # 7、选择照片 self.__choose_photos() # 8、编辑内容,选择地理位置 self.__put_content_and_gps() # 9、执行发送操作 self.poco('com.tencent.mm:id/lm', text='发表').click() def __mock_location(self): """ 模拟定位 :return: """ home() stop_app(package_name_location) start_my_app(package_name_location, activity_location) # 点击添加位置 self.poco('com.lerist.fakelocation:id/fab').click() # 点击搜索 self.poco('com.lerist.fakelocation:id/m_item_search').click() # 输入框输入目的地 self.poco( 'com.lerist.fakelocation:id/l_search_panel_et_input').set_text( self.location) # 等待搜索列表出现 # self.poco('').wait_for_appearance() sleep(2) # 宽、高 size = self.poco.get_screen_size() # 由于选择结果UI树查找不到,这里使用坐标来执行点击操作 adb_click(500, 283) # 确定位置 while self.poco('com.lerist.fakelocation:id/a_map_btn_done').exists(): self.poco('com.lerist.fakelocation:id/a_map_btn_done').click() def __start_mock(self): """ 开启模拟位置 :return: """ mock_element = self.poco( 'com.lerist.fakelocation:id/f_fakeloc_tv_service_switch') if mock_element.get_text() == '启动模拟': mock_element.click() # 等待启动模拟完成 self.poco('com.lerist.fakelocation:id/f_fakeloc_tv_service_switch', text='停止模拟').wait_for_appearance() else: pass print('模拟已经开启') def __open_friend_circle(self): """ 打开朋友圈 :return: """ # 等待完全打开微信App self.poco(text='微信').wait_for_appearance() self.poco(text='通讯录').wait_for_appearance() self.poco(text='发现').wait_for_appearance() self.poco(text='我').wait_for_appearance() print('微信完全打开') # 点击【发现】Tab self.poco('com.tencent.mm:id/djv', text='发现').parent().click() # 打开朋友圈 self.poco('android:id/title', text='朋友圈').click() # 等待朋友圈动态加载完全 self.poco('com.tencent.mm:id/eyx').wait_for_appearance() def __import_image_to_dcim(self): """ 导入图片到手机相册内 :return: """ # 本地的图片 files = get_all_files('./image/') # 一共待发送的图片数目 self.image_num = 9 if len(files) > 9 else len(files) # 手机相册目录 phone_image_path = 'sdcard/DCIM/Camera/' # 一张一张图片导入到手机相册内 for file in files[:self.image_num]: exec_cmd('adb push %s %s' % (file, phone_image_path)) # 注意:需要发送广告,通知更新相册 exec_cmd( 'adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///%s' % phone_image_path) print('图片导入到相册成功!') def __choose_photos(self): """ 选择图片 :return: """ # 点击右上角的相机图标 self.poco('com.tencent.mm:id/ln').click() # 选择相册 self.poco(text='从相册选择').click() # 选择指定数目的照片 cbs = self.poco('com.tencent.mm:id/ek8').offspring( 'com.tencent.mm:id/bwn') index = 0 # 选中固定数目的照片 for cb in cbs: if index < self.image_num: cb.click() else: break index += 1 # 确认选择图片 self.poco('com.tencent.mm:id/lm').click() def __put_content_and_gps(self): """ 输入内容和定位 :return: """ # 输入朋友圈内容 self.poco('com.tencent.mm:id/d3k').set_text(self.msg) # 定位的次数,一般需要两次 location_count = 0 # 点击定位图标 while True: self.poco('com.tencent.mm:id/d0a', text='所在位置').click() # 等待搜索列表中有结果出现 self.poco('com.tencent.mm:id/du7').wait_for_appearance() if location_count == 0: # 返回 keyevent('BACK') location_count += 1 else: # 排除ListView的前两项(不显示、市区),直接点击第三项(具体位置) self.poco('com.tencent.mm:id/dul').children()[2].click() break
class XHSFollow(object): def __init__(self): connect_device( "android://127.0.0.1:5037/DRGGAM0850527807?cap_method=MINICAP_STREAM&&ori_method=MINICAPORI&&touch_method=MINITOUCH") self.poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False) self.screenWidth, self.screenHeight = self.poco.get_screen_size() self.follow() def follow(self): start_app("com.xingin.xhs") temp_name_list = [] while True: sleep(1) state = self.poco.freeze() fans_list = state(type="androidx.recyclerview.widget.RecyclerView") sleep(1) user_name_list = [] for item in fans_list.children(): sleep(1) item.click() sleep(1) post_frame = self.poco(type="androidx.recyclerview.widget.RecyclerView") sleep(1) if post_frame.exists(): if post_frame[-1].children().exists(): post = post_frame[-1].children()[0] if post.exists(): post_name = post.get_name() if re.match(r"^com.xingin.xhs:id.*", post_name): sleep(1) like = post.offspring("com.xingin.xhs:id/afi") if like.exists(): like.click() print("已经点赞") else: print("用户没有发过帖子") message_btn = self.poco("com.xingin.xhs:id/cav") username = "" user_name_btn = self.poco("com.xingin.xhs:id/bhz") if user_name_btn.exists(): username = user_name_btn.get_text() user_name_list.append(username) if message_btn.exists(): if message_btn.get_text()=="关注": message_btn.click() print("已经关注 ", username) else: print("已经关注过 %s 了,跳过" % username) sleep(1) if self.poco("com.xingin.xhs:id/bha").exists(): self.poco("com.xingin.xhs:id/bha").click() print("下一个") date = time.strftime("%Y%m%d", time.localtime()) total = collection.count_documents({"record_date":date}) if user_name_list == temp_name_list: print("-----------------\n到头了\n-----------------") break elif total > 500: print("今天任务完成了") break else: temp_name_list = user_name_list swipe((self.screenWidth * 0.5, self.screenHeight * 0.8), vector=[0, -1], duration=1) sleep(3)
class XHSUnfollow(object): def __init__(self): connect_device( "android://127.0.0.1:5037/DRGGAM0850527807?cap_method=MINICAP_STREAM&&ori_method=MINICAPORI&&touch_method=MINITOUCH") self.poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False) self.screenWidth, self.screenHeight = self.poco.get_screen_size() self.follow() def sleep_radom(self): sleep(random.randint(1,3)) def follow(self): start_app("com.xingin.xhs") total = 500 while total > 1: self.sleep_radom() state = self.poco.freeze() fans_list = state("com.xingin.xhs:id/cx1") self.sleep_radom() for item in fans_list.children(): self.sleep_radom() follow_state = item.offspring("com.xingin.xhs:id/ex1") if follow_state.exists(): state_str = follow_state.get_text() if state_str == "互相关注": continue item.click() self.sleep_radom() post_frame = self.poco(type="androidx.recyclerview.widget.RecyclerView") self.sleep_radom() if post_frame.exists(): if post_frame[-1].children().exists(): post = post_frame[-1].children()[-1] if post.exists(): post_name = post.get_name() if not re.match(r"^com.xingin.xhs:id.*", post_name): message_btn = self.poco("com.xingin.xhs:id/f21") username = "" user_name_btn = self.poco("com.xingin.xhs:id/de8") if user_name_btn.exists(): username = user_name_btn.get_text() if message_btn.exists(): if message_btn.get_text() == "发消息": unfollow_btn = self.poco("com.xingin.xhs:id/f22") if unfollow_btn.exists(): self.sleep_radom() unfollow_btn.click() self.sleep_radom() self.poco("android:id/button1").click() self.sleep_radom() print("已经取关 ", username) total = total - 1 else: print("没有操作 %s 了,跳过" % username) else: print("用户发过帖子") if self.poco("com.xingin.xhs:id/ddi").exists(): self.poco("com.xingin.xhs:id/ddi").click() print("下一个") swipe((self.screenWidth * 0.5, self.screenHeight * 0.2), vector=[0, 1], duration=random.randint(1,3)) self.sleep_radom()
class DouYin(): ''' 操作模拟器,操控软件 ''' def __init__(self): # 通过系统时间自动计算时间间隔 a = str(datetime.now()) hour = a.split(' ')[-1].split(':')[0] num = int(hour) / 3 num = int(num) * 3 if num == 0: # 对于凌晨 0 点的判断 # 时间判断部分 date = datetime.now() - timedelta(days=1) news_start_time = str(date).split(' ')[0] yesterday = datetime.now() - timedelta(days=1) # 昨天时间 yesterday = str(yesterday).split(' ')[0] else: # 时间判断部分 date = datetime.now() - timedelta(days=0) news_start_time = str(date).split(' ')[0] yesterday = datetime.now() - timedelta(days=0) # 昨天时间 yesterday = str(yesterday).split(' ')[0] print('爬取时间段:{}到{}'.format(news_start_time, yesterday)) self.start_time = news_start_time # self.start_time = '2019-09-09' # 定义结束时间 y-m-d 离现在时间近 self.end_time = yesterday # end_time = '2019-03-22' self.phone_name = device_name_list[0]['device_id'] self.device_num = device_name_list[0]['device_num'] print(self.device_num) self.device_1 = Android(self.device_num) self.poco = AndroidUiautomationPoco(self.device_1, deuse_airtest_input=True, screenshot_each_action=False) self.keyword_list = ['奔驰 C级', '奔驰 GLA', '奔驰 S级'] # '宝马 X1', '宝马 X2','宝马 3系','宝马 7系', '宝马 X5', '宝马 X7',, '奔驰 GLE' self.size = self.poco.get_screen_size() self.is_break = False self.same_num = 0 # 表示评论数相同的计数,用来判断视频翻页是否到底 self.up_title = '' pool = redis.ConnectionPool(host='127.0.0.1') # 实现一个Redis连接池 self.redis_example = redis.Redis(connection_pool=pool) self.zhu_num = 0 # 视频的翻页数,主要用来断点续爬,多少个视频之后开始采集评论 self.is_first = True # 是否是第一次启动的第一个关键词,主要用来断点续爬 self.keyword = '' def hua(self): ''' 评论滑动 :return: ''' # print(size) x = self.size[0] # 获取屏幕宽 y = self.size[1] self.poco.swipe([(1 / 2) * x / x, (4 / 5) * y / y], [(1 / 2) * x / x, (1 / 4) * y / y], duration=0.2) def first_hua(self): ''' 防止评论输入模式滑动 :return: ''' x = self.size[0] # 获取屏幕宽 y = self.size[1] # # 向上滑 self.poco.swipe([(1 / 2) * x / x, (3 / 4) * y / y], [(1 / 2) * x / x, (1 / 6) * y / y], duration=0.1) def hua_zhuping(self): ''' 视频列表页滑动 :return: ''' # 获取屏幕的高 x = self.size[0] # 获取屏幕宽 y = self.size[1] # 向上滑动 # self.poco.swipe([(1 / 2) * x / x, (4 / 7) * y / y], [(1 / 2) * x / x, (3 / 7) * y / y], duration=0.1) self.poco.swipe([(1 / 2) * x / x, (5 / 6) * y / y], [(1 / 2) * x / x, (1 / 6) * y / y], duration=0.35) time.sleep(0.1) def hua_up(self): ''' 视频列表页滑动 :return: ''' # # 获取屏幕的高 # x = self.size[0] # # 获取屏幕宽 # y = self.size[1] # # 向上滑动 # self.poco.swipe([(1 / 2) * x / x, (4 / 7) * y / y], [(1 / 2) * x / x, (3 / 7) * y / y], duration=0.1) self.poco.swipe([0.5, 0.6], [0.5, 0.8], duration=0.2) time.sleep(0.1) def is_chinese(self, uchar): """判断一串字符中是否有汉字""" for child in uchar: if child >= u'\u4e00' and child <= u'\u9fa5': return True else: continue def main_work(self): """ 这里进行滑动的逻辑操作 :return: """ for i in range(300): print(i) souye = self.poco(text='首页') if souye: return print('进行一次主页滑动') self.hua_zhuping() time.sleep(0.5) if self.poco(text='暂时没有更多了'): break # time.sleep(5) # self.device_1.keyevent('KEYCODE_BACK') # time.sleep(5) # self.device_1.keyevent('KEYCODE_BACK') # time.sleep(5) # self.device_1.keyevent('KEYCODE_BACK') # time.sleep(5) # self.device_1.keyevent('KEYCODE_BACK') # time.sleep(5) # self.device_1.keyevent('KEYCODE_BACK') print('目前返回到抖音首页.....') time.sleep(5) def input_keyword(self, keyword, num): """ 这里进行点击输入框,输入文本操作,并搜索 """ # try: # print('点击输入文本框-1') # search_btn = self.poco(name='com.ss.android.ugc.aweme:id/aex')[0] # search_btn.click() # time.sleep(1) # except: # print('点击输入文本框-2') # self.poco(name='com.ss.android.ugc.aweme:id/aex').click() # time.sleep(1) if num > 0: self.poco(name='com.ss.android.ugc.aweme:id/a5j').click() else: self.poco(type='android.widget.EditText').click() print('输入搜索关键词') self.poco(type='android.widget.EditText').set_text(keyword) time.sleep(1) print('点击搜索按钮') self.poco(text='搜索').click() time.sleep(2) # self.poco(text='视频').click() # time.sleep(1) # self.poco.swipe([0.3, 0.3], [0.3, 0.3], duration=0.2) time.sleep(15) def time_change(self, str_time): """ 时间可是转换, 将‘分钟前’,‘小时前’,‘昨天’,‘前天’, '天前',转换成标准时间格式Y-m-d h:m:s :param str_time: :return: """ if '秒' in str_time: get_time = str(datetime.now()).split('.')[0] return get_time elif '分钟' in str_time: get_time_num = re.search('\d{1,2}', str_time).group(0) get_time_num = int(get_time_num) * 60 print(get_time_num) int_time = int(str(time.time()).split('.')[0]) - get_time_num # #转换成localtime time_local = time.localtime(float(int_time)) # 转换成新的时间格式(2016-05-05 20:28:54) dt = time.strftime("%Y-%m-%d", time_local) # "%Y-%m-%d %H:%M:%S" return dt elif '小时' in str_time: get_time_num = re.search('\d{1,2}', str_time).group(0) get_time_num = int(get_time_num) * 60 * 60 print(get_time_num) int_time = int(str(time.time()).split('.')[0]) - get_time_num # #转换成localtime time_local = time.localtime(float(int_time)) # 转换成新的时间格式(2016-05-05 20:28:54) dt = time.strftime("%Y-%m-%d", time_local) # "%Y-%m-%d %H:%M:%S" return dt elif '昨天' in str_time: try: part_time = str_time.split(' ')[1] yesterday = datetime.now() - timedelta(days=1) # 昨天时间 yesterday = str(yesterday).split(' ')[0] except: yesterday = datetime.now() - timedelta(days=1) # 昨天时间 yesterday = str(yesterday).split(' ')[0] return yesterday elif '前天' in str_time: part_time = str_time.split(' ')[1] two_days_ago = datetime.now() - timedelta(days=2) # 昨天时间 two_days_ago = str(two_days_ago).split( ' ')[0] + ' ' + part_time.replace('点', ':').replace('分', '') return two_days_ago elif '天前' in str_time: part_time = str_time.split('天前')[0] two_days_ago = datetime.now() - timedelta( days=int(part_time)) # 昨天时间 two_days_ago = str(two_days_ago).split(' ')[0] return two_days_ago elif '年' in str_time: str_time = str_time.replace('年', '-').replace('月', '-').replace('日', '') return str_time else: # str_time = '2019-' + str_time.replace('月', '-').replace('日', '') return str_time def run(self): self.homing() # if not self.poco(text='首页'): # self.device_1.shell('input keyevent 26') # time.sleep(1) # self.poco.swipe([0.5, 0.9], [0.5, 0.4], duration=0.3) # time.sleep(5) # try: # self.poco(name='com.ss.android.ugc.aweme:id/ap1').click() # print('点击搜索按钮-1') # time.sleep(1) # except: # print(traceback.format_exc()) # print('点击搜索按钮-2') # self.poco(name='com.ss.android.ugc.aweme:id/agt').click() # time.sleep(1) keyword_list = eval(self.redis_example.get('keyword_list')) print(type(keyword_list)) # for keyword in self.keyword_list: for i in range(1000): # 通过将关键词存入rides中,然后各个爬虫实例来取 # self.homing() time.sleep(5) keyword_index = int(self.redis_example.get('keyword_index')) if keyword_index > len(keyword_list): # 判断关键词是否爬取完毕 print('关键词爬取完毕......,最后一个爬取关键词为:', self.keyword) break self.keyword = keyword_list[keyword_index] print('获得关键词:', self.keyword) keyword_index += 1 self.redis_example.set('keyword_index', keyword_index) self.redis_example.set(self.phone_name, self.keyword) # time.sleep(30) print(111111, self.redis_example.get(self.phone_name).decode('utf8')) # try: if i == 0: self.poco(desc='搜索').click() # except: # time.sleep(10) # self.device_1.keyevent('KEYCODE_BACK') # time.sleep(10) # self.poco(desc='搜索').click() time.sleep(10) self.input_keyword(self.keyword, i) # 输入关键词 self.main_work() # 活动操作 else: self.input_keyword(self.keyword, i) # 输入关键词 self.main_work() # 活动操作 def homing(self): for i in range(6): souye = self.poco(text='关注') if not souye: self.device_1.keyevent('KEYCODE_BACK') time.sleep(5) else: print('返回到首页.....') time.sleep(20) break
class Follow(object): def __init__(self): connect_device( "android://127.0.0.1:5037/4f74b1cc?cap_method=MINICAP_STREAM&&ori_method=MINICAPORI&&touch_method=MINITOUCH" ) self.poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False) self.s_width, self.s_height = self.poco.get_screen_size() self.fans_json = "" self.validate_config() def judge_lite(self): sleep(3) return # sleep(3) # if exists(Template(r"tpl1616916148778.png", threshold=0.9000000000000001, rgb=True, record_pos=(-0.193, -0.033), resolution=(1080, 2340))): # touch(Template(r"tpl1616916171046.png", threshold=0.9000000000000001, rgb=True, record_pos=(0.153, 0.212), resolution=(1080, 2340))) # sleep(1) def fetch_fans(self): frzz = self.poco.freeze() frzz("android.widget.LinearLayout").offspring( "com.android.chrome:id/compositor_view_holder").offspring( "app")[0].child("android.view.View")[0].child( "android.view.View")[7].click() self.only_scrol() keyevent("BACK") sleep(3) def fetch_follows(self): frzz = self.poco.freeze() button = frzz("android.widget.LinearLayout").offspring( "com.android.chrome:id/compositor_view_holder").offspring("app")[ 0].child("android.view.View")[0].child("android.view.View")[6] if button: button.click() else: swipe((self.s_width * 0.5, self.s_height * 0.5), vector=[0, -0.4]) sleep(5) frzz = self.poco.freeze() button = frzz("android.widget.LinearLayout").offspring( "com.android.chrome:id/compositor_view_holder").offspring( "app")[0].child("android.view.View")[0].child( "android.view.View")[6] self.only_scrol() keyevent("BACK") sleep(3) self.fetch_fans() def only_scrol(self): path = Path("./end_user.png") if path.exists(): path.unlink() while True: sleep(2) scr = self.scrol_crop() is_same = self.compaire_image(scr) if is_same: # 二次滚动防止提前退出 second_pic = self.scrol_crop() second = self.compaire_image(second_pic) if second: print("确实已经到达底部,下一轮开始了") break else: self.save_caputure(second_pic) else: self.save_caputure(scr) def save_caputure(self, pic): end_user = cv2_2_pil(pic) end_user.save(r"./end_user.png") print("继续往下滑") def scrol_crop(self): # self.judge_lite() swipe((self.s_width * 0.5, self.s_height * 0.9), vector=[0, -1]) sleep(5) scr = crop_image(G.DEVICE.snapshot(), (0, self.s_height / 2, 450, self.s_height / 2 + 250)) sleep(1) return scr def compaire_image(self, scr): path = Path("./end_user.png") if path.exists(): tempalte = Template(r"./end_user.png", threshold=0.90) pos = tempalte.match_in(scr) if pos: print("貌似到达底部了", pos) return True else: return False else: return False def start(self): owner = list(source.find({}, {"user.id": 1, "user.screen_name": 1})) current = [ item for item in owner if item["user"]["id"] == self.fans_json["userid"] ] index = owner.index(current[0]) user_list = [item["user"] for item in owner][index:] for user in user_list: start_app("com.android.chrome") sleep(5) swipe((self.s_width * 0.5, self.s_height * 0.5), vector=[0, -0.2]) userid = user["id"] username = user["screen_name"] url = "https://m.weibo.cn/profile/" + str(userid) swipe((self.s_width * 0.5, self.s_height * 0.5), vector=[0, 0.2]) sleep(5) self.poco("com.android.chrome:id/url_bar").click() self.poco("com.android.chrome:id/url_bar").set_text("") sleep(1) text(url, search=True) sleep(5) # self.judge_lite() print("当前是 %s 的粉丝,id是 %s \n" % (username, userid)) self.write_data(userid) self.fetch_fans() stop_app("com.android.chrome") def validate_config(self): path = Path("fans.json") if not path.is_file(): sys.exit(u'当前路径:%s 不存在fans.json' % path.resolve()) with open("fans.json") as file: try: self.fans_json = json.loads(file.read()) print(self.fans_json) except ValueError: sys.exit(u'fans.json 格式不正确') def write_data(self, id): self.fans_json["userid"] = id with open("fans.json", "w") as f: json.dump(self.fans_json, f)