
12306网站推出图片验证码以后,对于抢票软件就强调了更高的规定,本篇并不涉及自动甄别验证码登录(主要是博主能力所限),提供一个途径-打码系统,这个几乎是可以破解所有验证码了,本篇主要是分享一下12306网站登录的流程的学习,勿吐槽,有问题请拍砖,博主也是刚开始接触爬虫,大家共勉共勉。
废话不多说了,直接干吧

首先打开12306登录页面
输入帐号密码直接登陆,会进入到后面的页面
红线划掉的就是用户名,那么我们最后就是要访问这个网站查找到我们的用户名,简单吧


好了,不闹了,看一下我们整个登录过程中的请求吧
这里缺少了开启登陆页面的请求,如果你没有发现,那我刚说了你就需要看到,这个注册页面是需要的,这里说一下我的理解,登录过程中我们是要发送验证码的,验证码作为独立的请求发送,那么服务器是要知道这个验证码是由张三发过来的而是由李四发回来的,所以当我们开启登陆页面的之后,服务器会记录session以及cookie,我们以后的请求都借助携带cookie让服务器知道是我张三发送的请求,而不是李四。大概就是这么回事,可能说的不太对,我也就理解了那么点,见谅见谅。
这里我们使用requests库,不要太方便
import requests
# 一个提供UserAgent的库,不用自己再去搞那么多了,方便
from fake_useragent import UserAgent
# 禁用安全请求警告
from urllib3 import disable_warnings
from urllib3.exceptions import InsecureRequestWarning
disable_warnings(InsecureRequestWarning)
session = requests.session()
# 设置不验证SSL,你应该看到了HTTPS
session.verify = False
ua = UserAgent(verify_ssl=False)
# 请求头,最最基础的反爬伪装
headers = {
"User-Agent": ua.random,
"Host":"kyfw.12306.cn",
"Referer":"https://kyfw.12306.cn/otn/passport?redirect=/otn/"
}
# 打开登录页面
url = "https://kyfw.12306.cn/otn/login/init"
session.get(url, headers=headers)
requests库的session会为我们保存cookie信息,只要我们再次使用session请求即可。
这里要先解释一下,我使用的是Chrome浏览器,但是这些请求上面确看不到response数据,真的很可笑,我写的之后每一个请求都用代码打印上去,很痛苦,

因为想写篇博客,要给你们照片,所有装了个虚拟机Windows xp,安装了Fiddler才发现一些信息,我而是习惯用Chrome,我尽量根据Chrome的方法去表明。
在所有的请求上面,我们主要关注Type等于document和xhr的请求,按照从上到下的方法就是整个步骤中请求的先后次序。我们可以发现init里面uamtk和captcha_js.js?_=1510993251087,
很明显这个是我们开启登陆页面时发送的请求,服务端告诉我们:你还没登录呢,废话我也是开启登陆界面,当然没注册了。不过我们一般了解了,发送这个请求,服务器会给我们反馈一些登录信息。后面那些请求很明显是js,我们暂时不用管。
下面是这个xhr请求:
这个是群发验证码的请求,12306的验证码属于坐标型验证码,所有我们发现发送的是一段坐标,在这个请求里面我们发现;module=login&rand=sjrand&0.9919795512111436
哦,这个是请求验证码的,要群发验证码请求,自然要先获取验证码喽,多请求几次发现表单里不仅最后一个随机数以外,其他的数据没有变化。接下来就是验证码的坐标了
首先是找原点坐标,这个跟正常登陆发送的坐标对比一下,大概能够确认,然后是断定坐标的拼接,x1,y1还是y1,x1,这个只是和正常登录发送的坐标大约对比一下就能确认了,我这儿只说一般原理,具体状况自己去尝试一下。下面上代码

验证码函数
def captcha():
# 请求数据是不变的,随机数可以使用random.random()
data = {
"login_site": "E",
"module": "login",
"rand": "sjrand",
"0.17231872703389062":""
}
# 获取验证码
param = parse.urlencode(data)
url = "https://kyfw.12306.cn/passport/captcha/captcha-image?{}".format(param)
response = session.get(url, headers=headers)
if response.status_code == 200:
# 获取验证码并打开,然后...手动找一下坐标吧,我开始就说了不涉及自动识别验证码的
file = BytesIO(response.content)
img = Image.open(file)
img.show()
positions = input("请输入验证码: ")
# 发送验证码
data = {
"answer": positions,
"login_site": "E",
"rand": "sjrand"
}
url = "https://kyfw.12306.cn/passport/captcha/captcha-check"
response = session.post(url, headers=headers, data=data)
if response.status_code == 200:
result = json.loads(response.text)
print(result.get("result_message"))
# 请求成功以后返回的code是4,这个看请求信息就知道了
return True if result.get("result_code") == "4" else False
return False
验证码通过之后,就要发送帐号登陆了,继续看上面的请求
账号密码登陆失败,看到没?好了

还没完呢,为啥捏?还没看见initMy12306这个请求呢 继续往前撸吧,,这个请求熟悉不?不熟悉的去翻上面
对比一下,前后不一样吧,验证通过,开心吧,哈哈! 咦!好像还多了点东西哦,newapptk什么鬼呢?不明白,继续看上面
敲黑板!!!是看下面的请求,你在看什么上面,睡着了吗?

验证通过,不过重点我都圈出来了,还看不见吗?tk,你再说说里面newapptk,明白了吗?上面的请求服务器返回了newapptk数据,我们借助以下的请求把这个值赋给tk,再群发给服务器手机12306怎么自动刷票,然后服务器告诉我们验证通过,
apptk和上面的tk一样,有什么用呢?不知道,那就往回看,哎呀,到站了
已经顺利了,有我们的账号名了,就是红点的地方,我似乎不会给你看我的账号名了,到这儿就真的完了,apptk没用到?没用就没用呗,终于结束了
我需要贴一下代码,差点忘了
完整的代码
# -*- coding: utf-8 -*-
import json
from urllib import parse
from io import BytesIO
from config import *
import requests
from PIL import Image
from fake_useragent import UserAgent
# 禁用安全请求警告
from urllib3 import disable_warnings
from urllib3.exceptions import InsecureRequestWarning
disable_warnings(InsecureRequestWarning)
session = requests.session()
session.verify = False
ua = UserAgent(verify_ssl=False)
headers = {
"User-Agent": ua.random,
"Host":"kyfw.12306.cn",
"Referer":"https://kyfw.12306.cn/otn/passport?redirect=/otn/"
}
def login():
# 打开登录页面
url = "https://kyfw.12306.cn/otn/login/init"
session.get(url, headers=headers)
# 发送验证码
if not captcha():
return False
# 发送登录信息
data = {
"username":USER_NAME,
"password":PASSWORD,
"appid":"otn"
}
url = "https://kyfw.12306.cn/passport/web/login"
response = session.post(url, headers=headers, data=data)
if response.status_code == 200:
result = json.loads(response.text)
print(result.get("result_message"), result.get("result_code"))
if result.get("result_code") != 0:
return False
data = {
"appid":"otn"
}
url = "https://kyfw.12306.cn/passport/web/auth/uamtk"
response = session.post(url, headers=headers, data=data)
if response.status_code == 200:
result = json.loads(response.text)
print(result.get("result_message"))
newapptk = result.get("newapptk")
data = {
"tk":newapptk
}
url = "https://kyfw.12306.cn/otn/uamauthclient"
response = session.post(url, headers=headers, data=data)
if response.status_code == 200:
print(response.text)
url = "https://kyfw.12306.cn/otn/index/initMy12306"
response = session.get(url, headers=headers)
if response.status_code == 200 and response.text.find("用户名") != -1:
return True
return False
def captcha():
data = {
"login_site": "E",
"module": "login",
"rand": "sjrand",
"0.17231872703389062":""
}
# 获取验证码
param = parse.urlencode(data)
url = "https://kyfw.12306.cn/passport/captcha/captcha-image?{}".format(param)
response = session.get(url, headers=headers)
if response.status_code == 200:
file = BytesIO(response.content)
img = Image.open(file)
img.show()
positions = input("请输入验证码: ")
# 发送验证码
data = {
"answer": positions,
"login_site": "E",
"rand": "sjrand"
}
url = "https://kyfw.12306.cn/passport/captcha/captcha-check"
response = session.post(url, headers=headers, data=data)
if response.status_code == 200:
result = json.loads(response.text)
print(result.get("result_message"))
return True if result.get("result_code") == "4" else False
return False
if __name__ == "__main__":
if login():
print("Success")
else:
print("Failed")
执行结果添一下,好累,我要去睡觉了
我讨厌写文章,真的,这是我的第一篇爬虫文章了,写代码过程用了两个小时,写文档用了整整一个下午手机12306怎么自动刷票,是的,一个下午。哎,我似乎还是不擅长写文章,之前想要写python微信公众号二次开发,结果写了好几次都是开头就删掉了,文才真的很烂,而且通篇逻辑混乱,我自己都看不下来。大家凑合看吧,希望多提意见,我一定虚心接受,慢慢纠正。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shouji/article-121138-1.html
台湾必须无条件接受统一
后有黄子韬
肯定不会让我们失望的
丑得我不要不要的作