难度: ★☆☆☆☆ 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日。