为了追到小姐姐,我用 Python 制作了一个机器人
閱讀文本大概需要 15 分鐘。
1
目 標 場 景
最近發現有一個微信好友,我的每一條朋友圈動態,無論什么時候發布,發布的什么內容,點贊列表總有它的身影。
這不禁讓我陷入一種沉思,是否我也能做一個機器人,第一個時間給暗戀的小姐姐朋友圈點贊,是不是也能拉動我們之間的距離。
作為技術人,肯定首先想的是如何實現的,實現這個功能的主流方案就下面 3 種,分別是:自動化、無障礙服務、Xposed 插件。
本篇文章帶大家利用 Python 自動化實現這一騷操作。
2
編 寫 代 碼
在開始編寫代碼之前,需要做下面的準備工作
?Android 開發環境
本機安裝?Node.js
npm 命令安裝?Appium Server
安裝 Python 依賴包
百度情感分析 API
開啟 Appium 服務
下面通過 7 步完成這個功能,分別是:打開微信、進入朋友圈入口、
首次滑動處理、獲取每條動態的內容、操作點贊、可變數據參數化、異常處理。
第 1 步,打開微信
我們利用 adb 命令獲取微信應用的包名及入口 Activity,通過數據線連接電腦,獲取到設備 id,編寫 Appium 配置文件。
#?配置文件 caps?=?{"platformName":?"Android","deviceName":?"ca2b3455",?????#?設備id"appPackage":?'com.tencent.mm',???#?微信包名"appActivity":?'com.tencent.mm.ui.LauncherUI',??#?微信入口Activity"autoGrantPermissions":?True,????"noReset":?True???#?不重置應用 }然后,WebDriver 就能通過上面的配置文件打開微信 App 了。
#?根據配置文件,驅動應用打開 self.driver?=?webdriver.Remote("http://127.0.0.1:4723/wd/hub",?caps)#?隱式等待微信主頁完全加載 self.driver.implicitly_wait(10)第 2 步,進入朋友圈入口
只需要找到首頁的「發現」Tab,執行點擊操作,接著點擊「朋友圈」文本控件,即能進入到朋友圈主界面。
由于從點擊到朋友圈頁面完全加載需要一個不確定的時間,這里使用一個顯式等待,直到朋友圈「動態列表元素」加載可見。
def?__open_friend_circle(self):"""打開朋友圈:return:"""#?點擊發現Tabfind_element_by_id_and_text(self.driver,?self.tag_id["id_page_main_discover"],self.tag_text["discover"]).click()#?進入朋友圈find_element_by_text(self.driver,?self.tag_text["friend_circle"]).click()def?__wait_for_appear(self,?id):"""等待某個元素出現:param?id::return:"""#?顯式等待?30s,直到元素出現WebDriverWait(self.driver,?30).until(EC.visibility_of_element_located((By.ID,?id)))self.__wait_for_appear(self.tag_id['id_page_friend_circle_listview'])第 3 步,首次滑動處理
由于屏幕分辨率的差異,部分小屏手機可能第一條動態在界面上可能展示不全,直接處理會產生異常,為了保證處理的完整性,需要做一次滑動預處理。
比如:下圖的第一條動態只有發布者和發布內容可見,發布時間不可見。
我們只需要拿到「第一條動態元素」的 y 軸坐標,向上對應的距離,這樣第一條動態就完全展示出來了。
def?swipe_first(self,?id_listview):"""首次滑動:param?param::return:"""element_listview?=?self.driver.find_element_by_id(id_listview)#?由于動態Item從ListView的第二子元素開始,獲取到第一個子元素的高度element_content?=?element_listview.find_element_by_class_name("android.widget.LinearLayout")#?獲取元素的屬性size?=?element_content.size#?滑動一次#?由于滑動因為滑動速度存在誤差,這里滑動距離需要做一下處理swipe_up_with_distance(self.driver,?size.get("height")?-?50,?1000)time.sleep(2)需要注意的是,由于滑動過快時,滑動距離會存在誤差,這里對滑動距離稍微做了一下處理。
第 4?步,獲取每條動態的內容
動態的內容分為純文本、其他(圖片、視頻、鏈接、音樂等)、文本+其他三種形式。
我們獲取到:動態的發布者、發布時間、發布文本內容。
def?__get_dynamic_content(self,?element):"""獲取動態的類型:param?element::return:"""#?文字的id:#?注意:不確定是否存在的元素,要使用find_elements_**,否則會拋出異常element_titles?=?element.find_elements_by_id(self.tag_id['id_page_friend_circle_item_title'])#?好友名element_author?=?element.find_element_by_id(self.tag_id['id_page_friend_circle_item_friend_name'])#?發布時間#?注意:可能沒法找到,導致異常element_publish_time?=?element.find_element_by_id(self.tag_id['id_page_friend_circle_item_publish_time'])author_name?=?element_author.get_attribute("text")publish_time?=?element_publish_time.get_attribute("text")content?=?Noneif?len(element_titles)?>?0:content?=?element_titles[0].get_attribute('text')#?返回發布者、發布時間、發布內容return?author_name,?publish_time,?content第 5?步,操作點贊
根據上面獲取的內容,去判斷這條動態是否值得我們去點贊。
如果本條動態的發布內容不為空,我們就采用百度的情感分析 API 去分析內容的積極性。
from?aip?import?AipNlpdef?get_word_nlp(word):"""判斷內容是否為消極的:param?word::return:""""""?你的?APPID?AK?SK?"""APP_ID?=?'xx'API_KEY?=?'xxx'SECRET_KEY?=?'xxxx'client?=?AipNlp(APP_ID,?API_KEY,?SECRET_KEY)"""?調用情感傾向分析?"""result?=?client.sentimentClassify(word)#?該情感搭配的極性(0表示消極,1表示中性,2表示積極)sentiment?=?result.get("items")[0].get("sentiment")return?sentiment?==?0過濾掉消極內容和已經點過贊的動態,其他每一條動態都執行點贊操作。
#?如果文本存在,并且是消極的,就不處理 if?dynamic_contents[2]?and?get_word_nlp(dynamic_contents[2]):print('消極的內容,不點贊!')continue#?點擊,彈出點贊按鈕element_perform_click(element,?self.tag_id['id_page_friend_circle_approve_button_pre'])#?不點贊的情況:已經點過贊、有文字內容并且為消極#?未點贊:贊;已贊:取消if?approve_text?==?'取消':#?關閉點贊彈框print('已經點贊過,不點贊')element_perform_click(element,?self.tag_id['id_page_friend_circle_approve_button_pre'])continue#?注意,點贊按鈕沒法執行點擊操作,需要往上找父類元素執行點擊操作element_perform_click(self.driver,?self.tag_id['id_page_friend_circle_approve_button'])處理完一頁動態之后,接著可以循環滑動頁面去查找動態列表,繼續上面的操作。
while?True:elements?=?self.driver.find_elements_by_id(id_item)#?....?循環操作#?滑動一次swipe_up(self.driver,?500)time.sleep(2)第 6?步,可變數據參數化
為了保證后期的可維護性,對文中查詢的 id、文本等元素寫入到 yaml 配置文件中。
tag:id:id_page_main_discover:?'com.tencent.mm:id/cw2'???#?主頁:發現按鈕id_page_friend_circle_listview:?'com.tencent.mm:id/e2p'???#?朋友圈頁面:動態列表id_page_friend_circle_item:?'com.tencent.mm:id/e6t'???#?朋友圈頁面:每一項動態id_page_friend_circle_item_title:?'com.tencent.mm:id/e6x'??#?朋友圈頁面:動態標題文本id_page_friend_circle_item_friend_name:?'com.tencent.mm:id/azl'??#?朋友圈頁面:動態的發布者id_page_friend_circle_item_publish_time:?'com.tencent.mm:id/e25'???#?朋友圈頁面:動態發布時間id_page_friend_circle_approve_button_pre:?'com.tencent.mm:id/e2c'??#?朋友圈頁面:動態點贊入口按鈕id_page_friend_circle_approve_status:?'com.tencent.mm:id/e1l'??#?朋友圈頁面:動態點贊狀態文本(贊或者取消)id_page_friend_circle_approve_button:?'com.tencent.mm:id/e1k'??#?朋友圈頁面:每一個動態的點贊按鈕text:discover:?'發現'friend_circle:?'朋友圈'后期一旦微信版本升級迭代,只需要更改此處代碼即可。
第 7?步,異常處理
上面的代碼如果不做異常處理,直接運行很有可能會出現各類異常,下面逐一進行說明。
首尾動態處理:當前界面第一條動態和最后一條動態中的部分元素不可見。
針對這個問題,需要考慮是在頂部還是尾部。如果在頂部,繼續處理下一條動態;如果在尾部,直接跳出本次循環。
for?index,?element?in?enumerate(elements):try:dynamic_contents?=?self.__get_dynamic_content(element)except?Exception?as?e:err_tag?=?"頭部元素"?if?index?==?0?else?"尾部元素"err?=?"**********%s產生一個異常**********"?%?err_tagprint(err)logging.error(err)logging.error(traceback.format_exc())#?判斷是頁面的第一個元素還是最后一個元素if?index?==?0:continueelse:break元素不可點擊:可以往上查找父級元素,直到找到一個可以點擊的元素,直接點擊操作。
元素不可見:有些元素在執行點擊操作的時候,不可見。
這個問題只需要捕獲異常,滑動小距離之后,再次執行點擊操作即可。
def?fb_id(driver:?WebDriver,?parentElement,?element_id):"""通過id查找元素:param?driver::param?parentElement?父元素中查找:param?element_id::return:"""while?True:try:#?注意:查找單個元素經常容許產生異常,這里進行捕獲后,然后滑動一次,繼續查找element?=?parentElement.find_element_by_id(element_id)return?elementexcept:print('查找元素:【%s】產生異常,滑動一次,再進行查找!'?%?element_id)swipe_up_small(driver,?500)3
結 果 結 論
通過上面的 7 步操作,就能完成了一個有感情的朋友圈點贊機器人。
我已經將全部源碼上傳到后臺,關注公眾號后回復「 點贊?」即可獲得全部源碼。
如果你覺得文章還不錯,請大家點贊分享下。你的肯定是我最大的鼓勵和支持。
來和小伙伴們一起向上生長呀!
掃描下方二維碼,添加小詹微信,可領取千元大禮包并申請加入 Python 學習交流群,群內僅供學術交流,日常互動,如果是想發推文、廣告、砍價小程序的敬請繞道!一定記得備注「交流學習」,我會盡快通過好友申請哦!
????長按識別,添加微信
(添加人數較多,請耐心等待)
????長按識別,關注小詹
(掃碼回復 1024 領取程序員大禮包)
總結
以上是生活随笔為你收集整理的为了追到小姐姐,我用 Python 制作了一个机器人的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小白级OpenCV入门
- 下一篇: 关于Python异常处理,你需要了解的知