刚刚刷完慕课,写完线代作业,现在是时候来一波验证码的突破测试了。在开始之前,我相信有很多朋友会问我:为什么要选择突破12306的验证码? 大家应该都知道,12306每天的火车票的数量都是有限的,如果有很多人都能够通过爬虫来进行抢票,那么,让那些不懂爬虫的人应该怎么办呢? 所有12306的反爬措施肯定是很到位的,既然反爬很强,那么也就是我们应该试着突破的对象。不因为别的,只是为了提高自己的技术,仅此而已。话不多说,下面进入正题。
大致思路是这样的:
1.找到12306的登录页面,post请求一次,找到请求的真正url,以及提交给服务器的数据data;
2.分析数据包data,找出需要提交的信息,然后再从上面的post请求中抓包分析,找到验证码的url;
3.找到提交data包的url,进行post请求,提交数据;
4.再次寻找所需要的验证信息,(12306的验证防护有3层,这篇文章,我们只讲前面的部分)
首先,我们打开12306的登录界面,F12,打开network选项,随便输入一个用户名,密码,和验证码,我们来看看会发出哪一些请求。
抓包分析可知,当点击登录的时候,浏览器发送了两个http请求。点击其中的一个,我们可以看见浏览器发出了一个post请求,而请求的真正的url是我红线画的url。
往下面看,可以发现,我们提交了一个data数据包,其中的login_site和rand都是定值,而answer则是验证码的分辨率。这里正是我们的突破口。
那么,接下来的一步就是要找到验证码的分辨率了,应该怎么做呢?
首先,我们要找到请求验证码图片的真实url,这里需要注意的是:图片的http请求和网页主题的请求并不是同步的,所有的图片信息都需要自己的url来进行请求。
显然,刚刚抓包得到的第二个请求就是,验证码图片的url。这是一个get请求,并不需要提交数据。
那么。我们现在需要做的就是将这个图片下载下来,然后通过画图工具,找到他的正确答案所对应的像素即可。 下面,我们开始写代码:(这里只写了主要的代码,没写的大家自己添加,请看注释)
check_res=my_session.get(ver_url)#得到验证码,并保存到本地
#将验证码保存到本地
with open('1.jpg','wb') as f:
f.write(check_res.content)
img=Image.open('1.jpg')
img.show()#将图片表示出来,用画图工具打开,然后就能看见像素
ver=input("请输入验证码>>>")#从验证码中得知的像素
#构造表单,字典类型
datas={"answer":ver,
"login_site":"E",
"rand":"sjrand"}
check_res=my_session.post(check_url,data=datas)
print(check_res.text)
我们可以看一下输出的内容是:
可以看见,现在已经模拟验证码输入已经成功了。大家可以看下图,当我们在网页上将验证码输入成功的时候,response的其实也就是这样一串数字。
验证码这一部分已经ok了,下面就是要找到账号和密码提交的真实url
我们在浏览器中将,账号,密码,以及验证码全部输入正确,点击登录时进行抓包分析:
可以看见,这次抓取的包就有很多了。在红区的包中,进行查找,我们发现有一个post请求,提交了我们的账号和密码:(这里时我随便输入的账号和密码,但是只要把验证码输入正确之后,就会进行进行账号和密码的验证,和上面说的把账号和密码,验证码全部输入正确并不矛盾)
而很容易发现,这个post请求发送给给的是下图url:
所以,下面我们就可以进行下一步了:对账号和密码进行一个验证,代码如下:
#抓包分析,得到提交账号和密码的url
login_url="https://kyfw.12306.cn/passport/web/login"
username=input("请输入账号:")
password=input("请输入密码:")
data={"username":username,
"password":password,
"appid":"otn"}
login_res=my_session.post(login_url,data=data)
print(login_res.text)
运行上面所有的代码,结果如下:
现在,我们就yij将验证码的校验给提交成功了,但是,这并不代表我们已经真正地登录成功了,大家可以看见,在账号密码的验证之后返回的response中,有一串名为uamtk的字符。、
实际上,这是我们下一步要使用的验证信息。这是一个思路,大家可以接着自己去做,今天我就讲这么多。
源码放在了我的的GitHub上,需要的朋友自取:
5月20日更新。
今天给大家更新一波。
在昨天的验证码和账号密码珀斯特之后,我们可以继续分析url,很容易找到:还有两个post请求。
这就是12306的第二层防护。我们看看其中一个post的数据包
可以看见他需要提供一个tk数据包,其实这就是我跟大家所说的上面登录成功之后,utamk参数的作用,按照之前的分析,可以分析处需要提交的url,这里直接上代码:
login_res=my_session.post(login_url,data=data)
print(login_res.text)
data2={"appid":"otn"}
Uamtk_res=my_session.post(Uamtk_url,data=data2)
json=json.loads(Uamtk_res.text)
umtk_id=json["newapptk"]
print(umtk_id)
data1={"tk": umtk_id}
uamtk_res=my_session.post(uamtk_url,data=data1)
print(uamtk_res.text)
data3={"_json_att":""}
use_res=my_session.post(user_url,data=data3)
print(use_res.text)
需要源码的朋友,可以去我的GitHub上下载
全文结束,欢迎在评论区讨论~