微信羣總是有人發廣告?看我用Python寫一個自動化機器人消滅他!

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"寫在前面"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"微信羣牛皮癬"},{"type":"text","text":",指的是在微信羣裏面惡心羣發小廣告的用戶,是微信羣主最痛恨的一波人。如果熟悉早起的讀者可以知道我有一個技術交流羣,但是自從建羣以來就飽受小廣告的困擾。他們僞裝成正常人的樣子混進羣然後不停的發送廣告轟炸,嚴重的打亂了羣內的技術交流氣氛👇"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/45/451cdaac19c0e7b9f330d7842848a1c1.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"或者是一聲不吭的去騷擾每一個羣成員👇"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d0/d01cb56f958a0708c67e67c7ceff8079.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然不清楚是什麼能夠驅使他們這樣不折不扣的努力成爲最強微信羣牛皮癬(可能是鈔能力),但是在太多次的騷擾之後,我決定拿起Python消滅這些小廣告。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"第一回合"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實實現思路很簡單,總共分兩步"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.識別廣告用戶"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.寫代碼移除之"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是這兩步,每一步都不簡單,先來說說第一步如何準確的識別這些用戶,網上沒有數據也沒有一個好的鑑別標準,只能用我的大腦完成特徵識別。經過這幾個月,近百份發廣告用戶的樣本訓練,基本可以判斷一個非正常用戶"},{"type":"text","marks":[{"type":"strong"}],"text":"至少滿足下面幾條中的三條以上"},{"type":"text","text":":"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"沒有設置微信號"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"頭像爲網紅女生"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"微信名爲特殊符號或者表情"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"沒發過朋友圈"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"沒有朋友圈背景圖"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過後不會有除進羣申請外的其他回覆"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"並且根據歷史數據,"},{"type":"text","marks":[{"type":"strong"}],"text":"符合1、3條的用戶有極大概率爲小廣告愛好者"},{"type":"text","text":",那麼接下來要做的就是"},{"type":"text","marks":[{"type":"strong"}],"text":"用Python寫代碼找出微信裏面的這些人"},{"type":"text","text":"。在總結出這一規律後很樂觀的認爲實現這一需求並不困難,因爲我在幾年前就曾拿過Python研究微信好友,不論是"},{"type":"codeinline","content":[{"type":"text","text":"wxpy"}]},{"type":"text","text":"還是"},{"type":"codeinline","content":[{"type":"text","text":"itchat"}]},{"type":"text","text":"操作起來應該都不復雜,但是事實確證明我還是太年輕了"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不知從何時起,雖然這些庫還能使用但是微信基本已經禁止了大部分人的網頁版微信登陸權限,因此當我使用多個微信號分別掃完登陸微信的二維碼之後,無一例外的提示我"}]},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"1203\n爲了你的帳號安全,此微信號已不允許登錄網頁微信。\n\n你可以使用Windows微信或Mac微信在電腦端登錄。\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這就讓人頭疼了,總不能手動的去一個一個check我的幾千個微信好友吧,於是我開始思考是否有其他的解決辦法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"第二回合"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你經常寫Python爬蟲,那麼你會知道在有些情況下,與其使用"},{"type":"codeinline","content":[{"type":"text","text":"Requests"}]},{"type":"text","text":"對付一些噁心的反爬措施,不如"},{"type":"codeinline","content":[{"type":"text","text":"Selenium"}]},{"type":"text","text":"操作起來方便。所以在發現想使用基於微信API的思路失效後,我將目光轉向了相對笨一點的方法————"},{"type":"codeinline","content":[{"type":"text","text":"pynput"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"pynput"},{"type":"text","text":"是一款使用Python來控制和監控電腦鼠標、鍵盤的第三方庫,說到這裏你大概明白我想怎麼做了,直接用API取數據搞不定,那麼我就像Selenium一樣,"},{"type":"text","marks":[{"type":"strong"}],"text":"模擬點擊"},{"type":"text","text":"一個一個好友來實現我想要的操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面簡單說一下這個庫,因爲沒有太多依賴庫所以安裝起來很簡單,直接"},{"type":"codeinline","content":[{"type":"text","text":"pip install pynput"}]},{"type":"text","text":"即可,使用起來也很簡單,對於鼠標操作只依賴座標,看個demo👇"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/eb/ebc8c802de4c5bfca1bb4d7cba8d6bf6.gif","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就像上面GIF演示的一樣,先導入"},{"type":"codeinline","content":[{"type":"text","text":"pynput"}]},{"type":"text","text":"並實例一個鼠標控制器,接着將微信在狀態欄的位置提交給"},{"type":"codeinline","content":[{"type":"text","text":"mouse.position"}]},{"type":"text","text":",這樣鼠標就會移動到該位置,再使用"},{"type":"codeinline","content":[{"type":"text","text":"mouse.press"}]},{"type":"text","text":"來模擬鼠標點擊即可自動打開微信。那麼問題來了,如何獲得我想要的位置的座標?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"pynput除了使可以使用"},{"type":"codeinline","content":[{"type":"text","text":"Controller"}]},{"type":"text","text":"來控制鼠標,也可以監控鼠標,比如使用下面的代碼就可以記錄下程序啓動後鼠標的每一個點擊操作所在的位置👇"}]},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"from pynput import mouse\n\ndef on_move(x, y ):\n print('鼠標移動至 {0}'.format(\n (x,y)))\n\ndef on_click(x, y , button, pressed):\n print('{0} 在座標 {1}'.format('鼠標點擊' if pressed else '鼠標釋放', (x, y)))\n if not pressed:\n return False\n\nwhile True:\n with mouse.Listener(on_move = on_move,on_click = on_click) as listener:\n listener.join()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a9/a97e624447d7451efc3078794cedb856.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那麼接下來的任務就簡單了,我們只需要保持微信窗口不移動,在記錄下每一個關鍵位置的座標("},{"type":"text","marks":[{"type":"strong"}],"text":"微信圖標位置,羣聊窗口位置,單個羣成員頭像位置"},{"type":"text","text":")之後,比如我們想對上面說的第一條規則進行判斷即獲取每一個羣成員微信號是否設置,就可以按照模擬以下操作實現:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"點擊微信app"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"點擊需要的羣聊"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"依次點擊每一個羣成員頭像"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"移動到微信號的位置"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"雙擊"},{"type":"text","text":"該微信號"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"複製該微信號判斷是否爲初始微信號"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在上面的過程中,值得說的是最後一步,複製我們可以使用pynput中的鍵盤控制器,在雙擊選中對應微信號之後通過下面的代碼實現模擬鍵盤輸入"},{"type":"codeinline","content":[{"type":"text","text":"Command + C"}]},{"type":"text","text":"完成複製操作"}]},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"from pynput.keyboard import Key\nfrom pynput.keyboard import Controller as Controller1\nkeyboard = Controller1()\n\nwith keyboard.pressed(Key.cmd):\n keyboard.press('c')\n keyboard.release('c')"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是粘貼則不需要使用pynput通過模擬"},{"type":"codeinline","content":[{"type":"text","text":"command+c"}]},{"type":"text","text":"來粘貼到另一個編輯中複雜過程,我們可以使用第三方庫"},{"type":"codeinline","content":[{"type":"text","text":"pyperclip"}]},{"type":"text","text":",直接通過下面兩行代碼即可將複製好的文字轉爲"},{"type":"text","marks":[{"type":"strong"}],"text":"字符串"}]},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"import pyperclip\npyperclip.paste()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在將羣成員的微信號轉換爲字符串後,不論我們是通過判斷字符串的長度還是用正則表達式或者是其他的方法都可以輕鬆的判斷該成員的微信號是否爲初始微信號,實現規則1的判斷,下面的代碼與動態圖就是一次**完整的過程"}]},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"from pynput.mouse import Button, Controller\nimport time\nfrom pynput.keyboard import Key\nfrom pynput.keyboard import Controller as Controller1\nimport pyperclip\n\nmouse = Controller()\n\n# 點擊微信\nmouse.position = (1046.14453125, 4.546875)\ntime.sleep(2)\nmouse.press(Button.left)\nmouse.release(Button.left)\n\n#點擊頭像\nmouse.position = (1194.140625, 441.05859375)\ntime.sleep(1)\nmouse.press(Button.left)\nmouse.release(Button.left)\n\n# 點擊選中文本\nmouse.position = (965.60546875, 284.0390625)\ntime.sleep(1)\nmouse.click(Button.left, 2)\n\nkeyboard = Controller1()\n\nwith keyboard.pressed(Key.cmd):\n keyboard.press('c')\n keyboard.release('c')\n time.sleep(1)\n\nwechatid = pyperclip.paste()\nprint(f\"微信號{wechatid}疑似廣告號\" if len(wechatid) > 20 else f\"微信號{wechatid}不是廣告號\")"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到成功將早小起的微信從廣告號中排除"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/05/058836df6083db3d029d5f16232df7fb.gif","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/0a/0a11cad1c9504cffca2395cd63efc2ad.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那麼接下來只需要記錄下每兩個羣成員之間間隔的座標距離,之後循環去"},{"type":"text","marks":[{"type":"strong"}],"text":"模擬滾動"},{"type":"text","text":"或者*"},{"type":"text","marks":[{"type":"italic"}],"text":"下拉"},{"type":"text","text":"*來實現上述過程,就可以將羣裏所有成員的微信號根據規則1進行判斷,找到異常的那些成員"},{"type":"text","marks":[{"type":"strong"}],"text":"單獨進行判斷"},{"type":"text","text":"。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/61/619f7570bfe98b28ee6ad3f43334beb6.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到最終是找到了6個疑似廣告號的微信,接下來通過其他規則的手動判斷最終將兩個用戶判定爲廣告高風險用戶並移除。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"寫在最後"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過上面的操作,雖然成功的踢出了兩個疑似廣告號,但是依舊很難去判斷是否真的踢對了人,如果踢錯了,那麼則粉絲-1,同時也可以發現想用Python準確找到羣裏的牛皮癬還是非常困難的,使用pynput最多可以完成微信號及頭像(使用識圖API)的判斷,但是更多的信息卻很難提取挖掘。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同時"},{"type":"codeinline","content":[{"type":"text","text":"pynput"}]},{"type":"text","text":"有着和"},{"type":"codeinline","content":[{"type":"text","text":"selenium"}]},{"type":"text","text":"同樣的缺點,那就是由於"},{"type":"text","marks":[{"type":"strong"}],"text":"模擬真人操作而導致的速度慢"},{"type":"text","text":",並且它的定位方式僅支持座標,所以還需要保證在操作的過程中微信窗口不可以被移動,否則之前記錄的元素將全部失效(建議開發者可以支持更多的定位方式)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你有好的思路可以在留言區和我交流,如果你想看更詳細的pynput講解,不要忘記給個三連。如果你對本文的代碼感興趣,可以在公衆號早起Python中找到。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"今天的文章就到這裏,爲了維護良好的羣內交流環境,對抗小廣告的路還在繼續,拜拜~"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章