最近,有一個朋友告訴我,她在某平臺上購買了一部手機,收到貨之後發現商品品質挺好的,價格也不貴。
臨了隨手給了個好評,商家最後還給她發一個 小紅包,她把這個商品分享給了我。
本篇文章的目的是利用 Python 自動化完成商品購買的操作。
ps:本文僅限用於技術交流,請勿用於其他用途。
2
準 備 工 作
在編寫程式碼之前,需要做如下準備工作:
1、配置好 Android ADB 開發環境
2、Python 虛擬環境內安裝 pocoui 依賴庫
3、操作剪下板的應用 APK,下載連結見文末
3
編 寫 代 碼
我們分 7 個步驟來實現這個功能,分別是:開啟目標應用客戶端、搜尋關鍵字到商品列表介面、裁剪原圖拿到商品主圖、商品匹配、商品收藏和瀏覽、購買商品、獲取訂單號和截圖。
第 1 步,使用 Airtest 自動化開啟目標應用。
# 目標應用package_name = '應用包名'activity = 'Home Activity'def __pre(self): """ 準備工作 :return: """ # 刪除快取檔案 remove_cache('./part.jpg', './screenshot.png', './uidump.xml') home() stop_app(package_name) start_my_app(package_name, activity)
開啟應用之後,就可以進行第 2 步操作了。
def __search_good_by_key(self): """ 通過關鍵字搜尋商品 :return: """ self.poco(id_page_main_button_search).wait(5).click() 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()
通過 遍歷 x 軸、y 軸,拿到每一個畫素的顏色值,如果是連續的白色就做一個標識,進而拿到主圖的上、下、左、右座標值,最後利用 cv2 庫進行裁剪,得到商品主圖。
def crop_main_img(img_path): """ 獲取商品主圖 :return: """ img = cv2.imread(img_path) # 圖片大小(高、寬、the pixels value is made up of three primary colors) size = img.shape height = size[0] width = size[1] channels = size[2] # 1080*458 print(f'圖片寬度:{img_width},高度:{img_height}' # 標識陣列,針對x軸和y軸 arr_x = [] arr_y = [] # 遍歷寬,得到主圖的x軸座標 for x in range(img_width): is_black = True # 遍歷高 for y in range(img_height): # 獲取顏色值 color_position = img[y, x] if (color_position == color_white).all(): pass else: is_black = False arr_x.append(is_black) # 遍歷高,得到主圖的y軸座標 for y in range(img_height): is_black = True # 遍歷高 for x in range(img_width): # 獲取顏色值 color_position = img[y, x] if (color_position == color_white).all(): pass else: is_black = False arr_y.append(is_black) position_x = get_space_index(arr_x) position_y = get_space_index(arr_y) main_img_path = "./head_img.jpeg" # 剪下 # 裁剪座標為[y0:y1, x0:x1] cropped = img[position_y[0]:position_y[1], position_x[0]: position_x[1]] cv2.imwrite(main_img_path, cropped) return main_img_path
第 4 步,商品匹配。
拿到商品主圖之後,利用 Airtest 在當前頁面進行元素查詢,如果沒有找到,就滑到下一個元素;否則,就拿到匹配商品的座標。
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.__swipe(True) else: print('找到了') # 螢幕寬度和高度 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
第 5 步,商品收藏和瀏覽。
在預先設定的瀏覽時間內,執行休眠、滑動操作。
def __browser_good_detail(self): """ 瀏覽商品 :return: """ # 切換到詳情Tab self.poco('com.**: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('詳情頁面檢視完畢')
第 6 步,購買商品。
def __buy_good(self): """ 購買商品 :return: """ # 立即購買 self.poco('**/detail_main_sys_button', text='立即購買').click() # 選擇商品屬性 sleep(10) # 確定購買 self.poco('**/confirm_text', text='確定').parent().click() # 提交訂單 self.poco(text='提交訂單').click() # 手動輸入密碼或者指紋 sleep(10)
第 7 步,獲取訂單 ID 及商品截圖。
通過 Monitor 觀察發現,訂單號文字元素很難通過屬性或者子、父關係拿到。
可以通過點選複製按鈕,將訂單號貼上到系統的剪下板,然後利用 adb + clipper 這款 App拿到剪下板中的內容。
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接著利用 adb 命令擷取當前螢幕,然後儲存到 PC 端,即完成了全部操作。
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_result4
結 果 結 論
通過以上的步驟,即可以完成自動化挑選商品、瀏覽、購買等一系列操作。
需要補充的是,由於手機解析度的不一致,導致商品主圖匹配會存在一定的誤差;但由於主圖寬、高比是一致的,可以通過縮放圖片達到 適配 的目的。