薅羊毛 | Python 自動化帶你輕鬆賺錢(完結版)
- 2019 年 11 月 1 日
- 筆記
1
目 標 場 景
最近,有一個朋友告訴我,她在某平台上購買了一部手機,收到貨之後發現商品品質挺好的,價格也不貴。
臨了隨手給了個好評,商家最後還給她發一個 小紅包,她把這個商品分享給了我。

本篇文章的目的是利用 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()
第 3 步,剪切原圖,需要對原圖中多餘的白色區域進行刪除,只保留左側的商品主圖。

通過 遍歷 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 img_height = size[0] img_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_result
4
結 果 結 論
通過以上的步驟,即可以完成自動化挑選商品、瀏覽、購買等一系列操作。
需要補充的是,由於手機解析度的不一致,導致商品主圖匹配會存在一定的誤差;但由於主圖寬、高比是一致的,可以通過縮放圖片達到 適配 的目的。