難度: ★☆☆☆☆ 1星
這個網站的註冊頁面上有一個看上去很複雜的驗證碼,但是實際上是假的,讓我們打開這個頁面:
輸入完信息之後還需要搞一個滑動驗證,得把滑塊向右滑動,不過看上去也不是那麼麻煩啊:
打開控制檯,清空掉無關請求,然後再把上面的滑塊向右滑動直到驗證成功,觀察到控制檯上沒有新的請求,這就有點詭異了:
這說明滑塊驗證碼向右滑動這個只是前端的一個事件,不是真正的驗證,然後滑到頭之後出來一個看上去很嚇人的驗證碼:
我們嘗試選中驗證碼圖片,觀察一下這張圖片是怎樣的:
源碼面板:
等等,好像有哪裏不太對,選中的圖片中的那個“早”字,它好像在源碼面板直接顯示出來了...這說明這個字一定是從哪裏傳輸回頁面的上的,我們只需要找到那個請求就好了。
仍然是把無關請求清空掉(上次清完之後好像還沒有新的請求...),然後點擊驗證碼上的刷新,從控制檯的Network觀察一下它的流程:
Network面板出現了幾個新的請求:
先看第一個:
看上去像是一個請求驗證碼的操作,還帶上了我剛剛註冊時輸入的手機號,然後再看看它的響應是什麼,怎麼是一坨文字,難道是我們想找的東西:
然後和頁面上做對比,會發現好像randomChar好像就是那兩行文本,而randomCode1和randomCode2就是讓點選的字:
然後再看另外幾個請求,這個請求貌似就是去根據之前註冊的手機號生成驗證碼的,畢竟在頁面上還要顯示成圖片的樣子嚇人:
這個是生成要點選的文字的,同理嚇人:
然後再在頁面上點選這兩個文字,看下提交成功會是什麼樣子:
看下點選成功的網絡請求是什麼樣子的:
然後在頁面上點擊“註冊”按鈕提交註冊表單,結果彈出一個發短信驗證碼的彈窗:
先不管彈窗,先看下提交註冊表單的網絡請求:
然後回到網頁,單擊彈窗裏的“獲取短信校驗碼”按鈕:
看下對應的網絡請求:
和這個請求的響應:
至此整個過程就比較清晰了,我們只需要按下面的流程發送請求即可:
實現代碼:
#!/usr/bin/env python3 # encoding: utf-8 """ @author: CC11001100 """ import logging import requests LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" logging.basicConfig(level=logging.INFO, format=LOG_FORMAT) session = requests.session() def register(phone_number, passwd): # 獲取驗證碼 response = very_code(phone_number) # 提交驗證碼 response = check_very_code(response, phone_number) # 彈窗也要發請求啊 h5_callback(phone_number, passwd) # 獲取手機驗證碼 order_meal(phone_number, passwd) def order_meal(phone_number, passwd): url = "https://mail.wo.cn/orderMeal" # 注意同一個字段的參數名字與之前的幾個接口不同,怪我自己瞎... # 難道是不同的人寫的,如果是一個人寫的哥們也太分裂了吧... data = { "phone": phone_number, "password": passwd, "productId": "8888888888" } response = session.post(url, data=data) logging.info(f"獲取短信驗證碼結果: {response.text}") return response def h5_callback(phone_number, passwd): url = "https://mail.wo.cn/h5Callback" data = { "userPhone": phone_number, "password": passwd, "productID": "8888888888" } headers = { # refer是必須帶的 "Referer": "https://mail.wo.cn/register", } response = session.post(url, headers=headers, data=data) logging.info(f"打開彈窗結果: {response.text}") return response def very_code(phone_number): """ 請求驗證碼 :param phone_number: :return: {'randomCode1': '此', 'randomCode2': '找', 'randomChar': '準背世風字此話離找沒'} """ url = "https://mail.wo.cn/veryCode" data = { "actionType": "veryCode", "user": phone_number, "domain": "wo.cn" } response = session.post(url, data=data) logging.info(f"請求到驗證碼: {response.text}") return response.json() def check_very_code(very_code_response, phone_number): url = "https://mail.wo.cn/checkVeryCode" data = { "actionType": "checkVeryCode", "user": phone_number, "userCode": very_code_response["randomCode1"] + very_code_response["randomCode2"] } response = session.post(url, data=data) logging.info(f"提交驗證碼的結果: {response.text}") return response if __name__ == "__main__": register("13791488888", "cC11001100")
運行結果:
倉庫:
https://github.com/CC11001100/misc-crawler-public/tree/master/003-captcha/01-003-mail.wo.cn
請注意爬蟲文章具有時效性,本文寫於2020-11-6日。