tnblog
首页
视频
资源
登录
有个性,不需要签名
排名
17
文章
40
粉丝
16
评论
21
Linq or Sql 取树末级节点
剑轩 : 这个方法是真的帅!
Python实例 2-12306抢票(二) 下单
18335584353 : 哥。我也是总返回url":"/leftTicket/init",&quot...
Visual Studio小技巧
剑轩 : [斜眼笑][斜眼笑]开会完了认真看了一遍
C#网络流读取(图片)
风清月 : 把一个图片放到字节数组里边[发呆](`・ω・´)
C#与Java二进制编码转换,补码
风清月 : 我勒个擦.....有时间这种问题很坑很难发现哇o(╥﹏╥)o
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

Python实例 2-12306抢票(一) 登陆

18469人阅读 2019/1/8 19:31 总访问:286083 评论:12 收藏:0 手机
分类: Python

开坑

年关将近,终于对12306下手了,,

平安夜撸代码,攻克了12306的登陆  2018-12-24 22:16:00


没错 这篇博客就写从零开始的异世界..(误)    一从零开始的抢票 

可能为期比较长  毕竟下班了才有时间写..  也才接触python半年不到 所以也是一边学习一边写的比较慢...



一、登陆

   采用扫码二维码的方式登陆,就是得下个app。。  验证码太烦了,不想搞

1.获取二维码:

    先分析二维码一般是一张图片,我们把他下载到本地 来方便扫码

    

    图片还是base64的数据形式


    但是我们用传统的方式爬下来 并不能取到图片的信息,只有一个图片占位标签

    

     拿到的东西没有src内容 但是页面上却有,说明图片的url是动态获取填充的

    (用到了 SoupStrainer 库安装pip install beautifulSoup4,介绍:开坑中 )


    继续分析,发现有这样一个请求,可以拿到图片的src内容

    

    图片是base64形式存储的 可以直接把他保存为图片 (base64:二进制编码数据形式,图片存数据库一般就这样放,取出来解析就是一张图,但是一般会比较长。。 )

    需要用到一个库操作图片pip install pillow

    由于图片是base64 还需要引入base64的库解码

模拟请求,下载图片:

地址:https://kyfw.12306.cn/passport/web/create-qr64

参数:{appid:otn} //固定的

返回:

  1. {"result_message":"生成二维码成功","result_code":"0","image":"iVBORw0KGgoAAAANSUhEUgAAAMcAAA......","uuid":"4B-aKlPZTyR4xlPGh7wmTz553-0ep8w-Lufw8sVxCir-mcQuzTf9iZPX-M4OZYBWjRiASiGJaiv0we1"}


代码:

  1. import base64
  2. import json
  3. import os
  4. import re
  5. import requests  # 用requests库,方便保存会话 功能和urllib差不多
  6. from bs4 import BeautifulSoup, SoupStrainer  # 网页解析库 可以替代正则来获取你想要的内容
  7. from PIL import Image  # 操作图片
  8. session = requests.Session() # session会话对象,请求和返回的信息保存在session中
  9. def get(url):
  10.     header = {
  11.         "User-Agent""Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
  12.     }
  13.     reqs = session.get(url, headers=header)
  14.     return reqs.text
  15. def post(url, data):
  16.     header = {
  17.         "User-Agent""Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
  18.     }
  19.     reqs = session.post(url, headers=header, data=data)
  20.     return reqs.text
  21. #获取二维码图片
  22. def getQR():
  23.     data = post(
  24.         'https://kyfw.12306.cn/passport/web/create-qr64', {"appid""otn"})
  25.     json_result = json.loads(data) # 是json格式 直接转成json方便操作
  26.     print(json_result)
  27.     if(json_result['result_code'] == "0"):
  28.         login_pic =getImage(base64.b64decode(json_result['image']))
  29.         Image.open(login_pic).show() #依赖PIL库,打开图片(会创建一个零食文件打开图片,图片未被占用时销毁)
  30. def getImage(img):
  31.     filepath = './login.png'
  32.     with open(filepath, 'wb'as fd: #w写入 b二进制形式
  33.         fd.write(img)
  34.     return filepath
  35. if __name__ == "__main__":
  36.     getQR()

结果

 

搞定 图片拿回来了。



2.登陆扫码

    图片是拿回来了也可以扫了,然而扫完之后并没有什么反应啊。。  

    继续分析! 12306是如何知道我们已经扫码了?

    在上一步我们分析拿二维码的时候 应该有注意到,请求中不止一个二维码的,还有一个大概每秒一个的请求

    

    就是这个checkqr根据字面意思,检查二维码!!


   

    我们扫一扫二维码 再看返回内容  注意result_code0变成了1 !!

    点击确定登陆再看(勾上preserve log 不然跳转了日志就没了)

    ??

  chrome的弊端。。 看不了了 可以用火狐看

   

 搞定! result_code2,说明扫码成功,token  get√!!



用程序来模拟这个请求:

地址:https://kyfw.12306.cn/passport/web/checkqr

参数:{

             uuid:"", //这个参数在前面取二维码时,有同时返回回来的

             appid:otn 固定的

           }

返回:

  1. {'result_message''扫码登录成功''result_code''2''uamtk''1bzmt2A2uZNXk96zw1kwAypjB4m3DzjQease2oBSTCYjnq2q0'}


代码:

  1. import base64
  2. import json
  3. import os
  4. import re
  5. import time
  6. import requests  # 用requests库,方便保存会话 功能和urllib差不多
  7. from bs4 import BeautifulSoup, SoupStrainer  # 网页解析库 可以替代正则来获取你想要的内容
  8. from PIL import Image  # 操作图片
  9. import threading
  10. session = requests.Session()  # session会话对象,请求和返回的信息保存在session中
  11. def get(url):
  12.     header = {
  13.         "User-Agent""Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
  14.     }
  15.     reqs = session.get(url, headers=header)
  16.     return reqs.text
  17. def post(url, data):
  18.     header = {
  19.         "User-Agent""Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
  20.     }
  21.     reqs = session.post(url, headers=header, data=data)
  22.     return reqs.text
  23. # 获取二维码图片
  24. def getQR():
  25.     data = post(
  26.         'https://kyfw.12306.cn/passport/web/create-qr64', {"appid""otn"})
  27.     json_result = json.loads(data)  # 是json格式 直接转成json方便操作
  28.     if(json_result['result_code'] == "0"):
  29.         uuid = json_result['uuid']
  30.         threading._start_new_thread(checkqr,(uuid,)) # 开一个线程去执行监听
  31.         login_pic = getImage(base64.b64decode(json_result['image']))
  32.         Image.open(login_pic).show()  # 依赖PIL库,打开图片(会创建一个零食文件打开图片,图片未被占用时销毁)
  33. def getImage(img):
  34.     filepath = './login.png'
  35.     with open(filepath, 'wb'as fd:  # w写入 b二进制形式
  36.         fd.write(img)
  37.     return filepath
  38.     
  39. def checkqr(uuid):
  40.     while(True):
  41.         checkqr_url = 'https://kyfw.12306.cn/passport/web/checkqr'
  42.         data = post(checkqr_url, {"uuid": uuid, "appid""otn"})
  43.         json_result = json.loads(data)
  44.         print(json_result)
  45.         status_code = json_result['result_code']
  46.         if(status_code == "1"):
  47.             print('已扫描请确定')
  48.         elif(status_code == "2"):
  49.             print(json_result['result_message'])
  50.             return
  51.         elif(status_code == '3'):  # 二维码过期
  52.             getQR()
  53.             return
  54.         time.sleep(2)
  55. if __name__ == "__main__":
  56.     getQR()

结果

虽然提示扫码登陆成功,现在调用检查是否登陆 可以看到结果flag是false 代表未登录   ↓

(不贴完整代码了 太长,后面给源码)


扫码登陆成功主要是取回token,然后带着token去请求验证,可以看到上一个不是扫码成功的请求里并没有token

这里有个重要的点!!!,怎么保存会话 

我们的请求全是通过seeesion来发起的,所有如果请求后返回的信息如token,cookie之类,会自动记录到session中,你再用session来发起时 会自动带上请求的cookie之类的信息!

强大


验证:

    地址:https://kyfw.12306.cn/passport/web/auth/uamtk

    参数:{appid:otn} //固定的

    返回:

  1. {"result_message":"验证通过","result_code":0,"apptk":null,"newapptk":"oIxLeXFNNYv1526TDD6Avm-oX3OAmexpa3T6bKVEefg36q2q0"}


    地址:https://kyfw.12306.cn/otn/uamauthclient

    参数:{tk:""} //验证1里返回的newapptk 

    返回:

  1. {"apptk":"oIxLeXFNNYv1526TDD6Avm-oX3OAmexpa3T6bKVEefg36q2q0","result_code":0,"result_message":"验证通过","username":"XX"}

模拟请求:

可以看到验证成功之后 返回了你的邮箱或者姓名之类的信息! 再检查是否登陆 flag:Ture!

到此为止 登陆搞定! 算是剥去衣服

代码 https://github.com/YuChenDayCode/Ticket/blob/login/ticket.py

整理下流程:

  1. https://kyfw.12306.cn/passport/web/create-qr64 //获取二维码
  2. https://kyfw.12306.cn/passport/web/checkqr //检查二维码是否过期或是否被扫码
  3. https://kyfw.12306.cn/passport/web/auth/uamtk //验证
  4. https://kyfw.12306.cn/otn/uamauthclient //二次验证


下一步刷票 http://www.tnblog.net/cz/article/details/241



欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

评价

剑轩

2019/1/10 23:50:25

整站第一次评论!

雨雨雨雨辰

2019/1/10 23:52:03

第二次!!!

剑轩:@雨雨雨雨辰好久出第二篇哇

2019/1/11 9:44:20 回复

雨雨雨雨辰:@剑轩整理一大半了,1,2天就能发!

2019/1/11 9:50:14 回复

2019/1/11 11:19:08 回复

剑轩:@雨雨雨雨辰第一篇突破200的文章[狂赞]

2019/1/13 17:55:12 回复

噢大菁

2019/1/11 0:21:21

我是老幺!!!

剑轩:@噢大菁[斜眼笑][斜眼笑]你是老大

2019/1/11 9:45:01 回复

噢大菁:@剑轩哈哈哈 老幺免礼

2019/1/11 11:35:03 回复

剑轩:@噢大菁给大佬递茶

2019/1/11 11:36:48 回复

噢大菁:@剑轩【喝茶】.gif

2019/1/11 11:38:58 回复

瑾语

2019/7/17 11:46:24

第三次评论

Python学习 1-安装

Ptyhon非常简单易用的面向对象的脚本语言,跨平台 入门简单python分2个版本 Python2、Python3。Python 2.7 将于 2020 年结...

Python学习 2-基本语法

基础:python脚本语言,不需要编译(像C#、Java、PHP、C++需要编译成机器可识别的语言), 而直接由解释器解释,很多地方类似...

Python学习 3-爬虫基本介绍 及简单实例

爬虫爬虫就是一只猪,蜘蛛。。 网络蜘蛛。互联网是一个网由各个网站组成。无数的蜘蛛就在网上到处爬,根据网址从一个网站爬...

Python实例 1-日志抓取处理 补错(附日志小技巧)

有时候数据出了问题,可以从日志中恢复数据(如果你没记日志..没备份..→_→..)一、日志展示介绍个平常自己用的小方法,如...

Python安装pip以及使用pip安装requests等模块

pip很简单的介绍pip 是一个现代的,通用的 Python 包管理工具。提供了对 Python 包的查找、下载、安装、卸载的功能。如果想...

Python数据集合区别

列表(list):可读写,值可以重复,有序排列,初始化语法:['tom',‘jerry’]元组(tuple):只读,值可以重复,...

Python实例 2-12306抢票(二) 下单

第二篇 刷票与下单1.记住登陆上一篇写了登陆:http://www.tnblog.net/cz/article/details/162 为了方便调试 不让每次登陆都...

使用VS Code开发Python

Vs Code开发Python可以很好的支持代码调试、智能提示、代码对齐等1:下载VS Codehttps://code.visualstudio.com/Downloadvs ...

Python变量与命名

Python使用等号 ( = ) 作为赋值运算符,例如a = 66 就是一条赋值语句,作用就是将66赋值给变量a。Python是弱类型语言,弱类...

Python关键字和内置函数

Python中包含了如下所示的关键字:上面这些关键字都不能作为变量名。另外,Python 3还提供了如下表所示的内置函数:也不能...

Python基础输入和输出

Python使用print()函数向打印程序输出,采用input()函数接收程序输入。print()函数的语法格式如下:print(value,...,sep=&#...

Python基本数据类型

Python包含两大类基本数据类型:数值类型、字符串类型,三大类组合数据类型:集合类型、序列类型和字典类型.数值类型:整型...

Python中通过fake_useragent生成随机UserAgent

fake_useragent第三方库,来实现随机请求头的设置;GitHub ---> https://github.com/hellysmile/fake-useragent安...

Python 升级pip

一条命令即可: python -m pip install --upgrade pip 安装成功后,一般是在python目录下面的Scripts里边的

Python html编码解码

使用方法:html.escape(s)与html.unescape即可 import html s="<div>jsdlfjsl</div>" #html编...