前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >12306自动刷票下单-登录篇

12306自动刷票下单-登录篇

作者头像
星星在线
发布2018-08-21 10:38:39
1.1K0
发布2018-08-21 10:38:39
举报
文章被收录于专栏:python爬虫实战之路

12306网站推出图片验证码以后,对于抢票软件就提出了更高的要求,本篇并不涉及自动识别验证码登录(主要是博主能力所限),提供一个途径-打码平台,这个几乎是可以破解所有验证码了,本篇主要是分享一下12306网站登录的流程的学习,勿吐槽,有问题请指正,博主也是刚开始接触爬虫,大家共勉共勉。

废话不多说了,直接干吧

这里写图片描述

首先打开12306登录页面https://kyfw.12306.cn/otn/login/init

这里写图片描述

输入账号密码直接登录,会转入到下面的页面https://kyfw.12306.cn/otn/index/initMy12306

这里写图片描述

红线划掉的就是用户名,那么我们最终就是要访问这个网页查找到我们的用户名,简单吧

这里写图片描述

好了,不闹了,看一下我们整个登录过程中的请求吧

这里写图片描述

这里缺少了打开登录页面的请求,如果你没有发现,那我刚说了你就应该发现,这个登录页面是必须的,这里说一下我的理解,登录过程中我们是要发送验证码的,验证码作为独立的请求发送,那么服务器是要知道这个验证码是由张三发过来的还是由李四发过来的,所以当我们打开登录页面的时候,服务器会记录session或者cookie,我们之后的请求都通过携带cookie让服务器知道是我张三发送的请求,而不是李四。大概就是这么回事,可能说的不太对,我也就理解了这么点,见谅见谅。

这里我们使用requests库,不要太方便

代码语言:javascript
复制
import requests# 一个提供UserAgent的库,不用自己再去搞那么多了,方便from fake_useragent import UserAgent# 禁用安全请求警告from urllib3 import disable_warningsfrom urllib3.exceptions import InsecureRequestWarning
disable_warnings(InsecureRequestWarning)

session = requests.session()# 设置不验证SSL,你应该看到了HTTPSsession.verify = Falseua = 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,

这里写图片描述

很明显这个是我们打开登录页面时发送的请求,服务端告诉我们:你还没登录呢,废话我只是打开登录界面,当然没登录了。不过我们大概知道了,发送https://kyfw.12306.cn/passport/web/auth/uamtk这个请求,服务器会给我们反馈一些登录信息。后面那个请求很明显是js,我们暂时不用管。

下面是这个xhr请求:https://kyfw.12306.cn/passport/captcha/captcha-check

这里写图片描述

这个是发送验证码的请求,12306的验证码属于坐标型验证码,所有我们看到发送的是一段坐标,在这个请求上面我们看到https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.9919795512111436

这里写图片描述

哦,这个是请求验证码的,要发送验证码请求,自然要先获取验证码喽,多请求几次发现表单里除了最后一个随机数以外,其他的数据没有变化。接下来就是验证码的坐标了

这里写图片描述

首先是找原点坐标,这个跟正常登录发送的坐标对比一下,大概就能确定,然后是确定坐标的拼接,x1,y1还是y1,x1,这个也是和正常登录发送的坐标大概对比一下就能确定了,我这里只说大概原理,具体情况自己去尝试一下。下面上代码

验证码函数

代码语言:javascript
复制
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

验证码通过以后,就要发送账号登录了,继续看下面的请求 https://kyfw.12306.cn/passport/web/login

这里写图片描述

账号密码登录成功,看到没?好了

这里写图片描述

还没完呢,为啥捏?还没看到initMy12306这个请求呢 继续往下撸吧,https://kyfw.12306.cn/passport/web/auth/uamtk,这个请求熟悉不?不熟悉的去翻前面

这里写图片描述

对比一下,前后不一样吧,验证通过,开心吧,哈哈! 咦!好像还多了点东西哦,newapptk什么鬼呢?不明白,继续看下面 敲黑板!!!是看后面的请求,你在看哪个下面,睡着了吗? https://kyfw.12306.cn/otn/uamauthclient

这里写图片描述

验证通过,不过重点我都圈起来了,还看不见吗?tk,你再看看上面newapptk,明白了吗?上面的请求服务器返回了newapptk数据,我们通过下面的请求把这个值赋给tk,再发送给服务器,然后服务器告诉我们验证通过,apptk和前面的tk一样,有什么用呢?不知道,那就往下看,哎呀,到站了 https://kyfw.12306.cn/otn/index/initMy12306

这里写图片描述

已经成功了,有我们的账号名了,就是红点的地方,我当然不会给你看我的账号名了,到这里就真的完了,apptk没用到?没用就没用呗,终于结束了

这里写图片描述

我还要贴一下代码,差点忘了

完整的代码

代码语言:javascript
复制
# -*- coding: utf-8 -*-import jsonfrom urllib import parsefrom io import BytesIOfrom config import *import requestsfrom PIL import Imagefrom fake_useragent import UserAgent# 禁用安全请求警告from urllib3 import disable_warningsfrom urllib3.exceptions import InsecureRequestWarning
disable_warnings(InsecureRequestWarning)

session = requests.session()
session.verify = Falseua = 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 Falsedef 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 Falseif __name__ == "__main__":    if login():
        print("Success")    else:
        print("Failed")

执行结果添一下,好累,我要去吃饭了

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python爬虫实战之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档