自动抢票软件
一、说明
12306目前反爬虫手段做的越来越牛逼了,一旦检测到,直接就封号了或者很容易导致登录失败,必须更换代理服务器才能登录,所以做测试的时候一定要小心,要先把代理IP池搞好,再做测试。
二、代理IP池
1、获取代理IP途径,获取代理IP链接,记得将ip、端口、协议类型都获取下来,存放到一个文本中
2、获取的代理IP可能不存活,如果想验证IP的存活性的话,可以使用nmap进行验证,具体验证方式不做详细讲解,可以百度
三、code
实现此code目前遇到的问题难点
- 识别12306登录验证码,这个验证码是随机出现的图片,肉眼都很难识别,更别说程序了;目前知道的有三种方式可以识别
- 第一种:专业打码平台,调用API就可以验证,但是这个要花钱购买
- 第二种:深度学习图片识别,采集大量的12306登录验证码图片,进行训练模型,将模型训练的精确度比较高的时候,可以用来识别登录图片
- 第三种:12306其实利用的是根据图片所在的坐标来识别输入的验证码是否准确的,图片的坐标在verify_code函数中有注释,1:(45,45)代表第一张图片的识别坐标范围:横坐标为0-45,纵坐标为0-45,只要输入在这个范围,则登录就会验证通过;本程序目前采用的就是先把登录验证的图片下载下来,根据肉眼匹配图片,输入坐标就可登录成功,如果有大神可以利用第二种方式来实现
import http.cookiejar as cookielib
from json import loads
import re
import os
import time
import random
import requests
requests.packages.urllib3.disable_warnings()
def get_random():
return str(random.random()) # 生产一个18位的随机数
def get_13_time(): # 一个十三位的时间戳
return str(int(time.time() * 1000))
def load_file(file_name):
datas = []
if file_name is not None and os.path.isfile(file_name):
with open(file_name, 'r') as f:
for line in f:
line = line.encode('utf-8').decode('utf-8-sig').strip().lower()
if line:
datas.APPend(line)
return datas
class CN12306:
def __init__(self):
# 代理IP获取网站
self.start_time = '2018-07-15'
self.headers = {
'User-Agent': 'Mozilla/5.0 (windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36'
}
self.s = requests.session()
self.ips = load_file('ips.lt')
self.proxies = {'http': random.choice(self.ips)}
self.s.cookies = cookielib.LWPCookieJar(filename='cookie')
def get_init(self): # 请求了一个首页
url = 'https://kyfw.12306.cn/otn/login/init'
r = self.s.get(url, proxies=self.proxies, headers=self.headers, verify=False)
print('首页获取成功,状态码:', r)
def get_image_code(self):
url = "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{}".format(
random.random())
response = self.s.get(url=url, proxies=self.proxies, headers=self.headers, verify=False)
with open(r'H:\pictures\12306自动抢票\code.png', 'wb') as f:
f.write(response.content)
def generate_code_list(self, code_str):
code_str = code_str.strip()
groups = code_str.split(',')
codes = []
check_list = ['35,35', '105,35', '175,35', '245,35', '35,105', '105,105', '175,105', '245,105']
for group in groups:
codes.append(check_list[int(group) - 1])
return ','.join(codes)
def verify_code(self):
# {1:(45,45)}{2:(120,45)}{3:(180,45)}{4:(255,45)}{5:(45,120)}{6:(120,120)}{7:(180,120)}{8:(255,120)}
self.get_image_code()
code = input('输入验证码:')
code = self.generate_code_list(code)
data = {
'answer': code,
'login_site': 'E',
'rand': 'sjrand'
}
url = 'https://kyfw.12306.cn/passport/captcha/captcha-check'
resp = self.s.post(url, data=data, proxies=self.proxies, headers=self.headers, verify=False)
result = loads(resp.text)
if result['result_code'] == '4':
return True
else:
return false
def login(self):
url = 'https://kyfw.12306.cn/passport/web/login'
data = {
'username': '', # 个人12306用户名
'password': '', # 个人12306用户密码
'appid': 'otn',
}
resp = self.s.post(url=url, proxies=self.proxies, data=data, headers=self.headers, verify=False)
result = loads(resp.text)
print(result)
if result['result_code'] == 0:
self.uamtk = result['uamtk']
return True
else:
return False
def userLogin(self):
url = 'https://kyfw.12306.cn/otn/login/userLogin'
r = self.s.post(url=url, proxies=self.proxies, headers=self.headers, verify=False)
# print(r.text)
def getjs(self):
url = 'https://kyfw.12306.cn/otn/HttpZF/GetJS'
r = self.s.get(url, proxies=self.proxies, headers=self.headers, verify=False)
def post_uamtk(self):
url = 'https://kyfw.12306.cn/passport/web/auth/uamtk'
data = {'appid': 'otn'}
r = self.s.post(url=url, data=data, proxies=self.proxies, allow_redirects=False, headers=self.headers, verify=False)
self.newapptk = r.json()["newapptk"]
r.encoding = 'utf-8'
print(r.text)
def post_uamauthclient(self):
url = 'https://kyfw.12306.cn/otn/uamauthclient'
data = {
'tk': self.newapptk
}
r = self.s.post(url=url, data=data, proxies=self.proxies, headers=self.headers, verify=False)
self.apptk = r.json()["apptk"]
r.encoding = 'utf-8'
print(r.text)
def get_userLogin(self):
url = 'https://kyfw.12306.cn/otn/login/userLogin'
r = self.s.get(url, proxies=self.proxies, headers=self.headers, verify=False)
r.encoding = 'utf-8'
# print(r.text)
def get_leftticket(self):
url = 'https://kyfw.12306.cn/otn/leftTicket/init'
r = self.s.get(url, proxies=self.proxies, headers=self.headers, verify=False)
r.encoding = 'utf-8'
# print(r.text)
def get_GetJS(self):
url = 'https://kyfw.12306.cn/otn/HttpZF/GetJS'
self.s.get(url, proxies=self.proxies, headers=self.headers, verify=False)
def get_qufzjql(self):
url = 'https://kyfw.12306.cn/otn/dynamicJs/qufzjql'
self.s.get(url, proxies=self.proxies, headers=self.headers, verify=False)
def get_queryZ(self):
url = 'https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes={}'.format(
self.start_time, 'XAY', 'WNY', 'ADULT')
r = self.s.get(url, headers=self.headers, proxies=self.proxies, verify=False)
r.encoding = 'utf-8'
print(loads(r.text))
cheliang = r.json()["data"]["result"]
for i in cheliang:
dandulist = str(i).split('|')
if len(str(dandulist[0])) >= 100:
self.secretStr = dandulist[0]
# secretStr = str(x[0])
车次 = str(dandulist[3])
出发时间 = str(dandulist[8])
到达时间 = str(dandulist[9])
历时 = str(dandulist[10])
软卧 = str(dandulist[23])
硬卧 = str(dandulist[28])
硬座 = str(dandulist[29])
无座 = str(dandulist[26])
if "G" in 车次 or "D" in 车次:
print(i)
print('可预订车次列表,', '车次:', 车次, '出发时间:', 出发时间, '到达时间:',
到达时间, '历时:', 历时, '软卧: ', 软卧, ' 硬卧: ', 硬卧, ' 硬座: ', 硬座, ' 无座: ', 无座)
print('*****************************************************')
# return True
# 点击预定下单
def post_submitorderRequest(self):
url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
data = {
'secretStr': self.secretStr,
'train_date': self.start_time, # 出发时间
'back_train_date': self.start_time, # 返回时间
'tour_flag': 'dc',
'purpose_codes': 'ADULT',
'query_from_station_name': '西安',
'query_to_station_name': '渭南',
'undefined': ''
}
r = self.s.post(url=url, proxies=self.proxies, data=data, headers=self.headers, verify=False)
print(r.text)
def post_initDc(self):
url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
r = self.s.post(url)
# r.text
self.REPEAT_SUBMIT_TOKEN = re.findall("globalRepeatSubmitToken = '(.*?)';", r.text)[0]
def post_getPassengerDTOs(self): # 获取乘客信息
url = 'https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs'
data = {
'REPEAT_SUBMIT_TOKEN': self.REPEAT_SUBMIT_TOKEN,
'_json_att': ''
}
r = self.s.post(url=url, proxies=self.proxies, data=data, headers=self.headers, verify=False)
r.encoding = 'utf-8'
print(r.text)
if __name__ == '__main__':
# main_()
cn = CN12306()
if cn.verify_code():
print("验证码校验成功")
else:
print("验证码校验失败")
exit(1)
if cn.login():
print("账户登录成功")
else:
print("账户登录失败")
exit(1)
# cn.userLogin()
cn.getjs()
cn.post_uamtk()
cn.post_uamauthclient()
# cn.get_userLogin()
cn.get_leftTicket()
cn.get_GetJS()
cn.get_qufzjql()
cn.get_queryZ()
# while cn.get_queryZ():
# time.sleep(60)
分享即快乐
以上代码仅仅业余爱好实现,切勿对12306平台造成任何破坏
如有技术问题,欢迎指正
相关阅读
春运时期一票难求,为买到心仪的火车票我们需要使用手机、电脑来进行抢票。手机12306客户端为此也提供了自动刷票的功能,那么该如何
【解决方案】chrome打开新标签页自动打开chrome://new
简述 天,昨天开始遇到这个问题,还没有留心,结果今天多次使用chrome的时候,就发现有些不对了。。打开chrome的新标签页,结果出现了自动
我们在淘宝商城购物的时候,一般都会去咨询客服一些问题,比如说尺寸适合哪个尺、发什么快递、质量怎么样等等,这些问题都是很常见的,10
方法一 最简单的开机启动 https://zhinan.sogou.com/guide/detail/?id=1610009617 方法二 https://jingyan.baidu.com/article/20
本章主要讲解自动装配的几种方式,接上一章依赖注入的方式以及装配属性:https://blog.csdn.net/qq_34598667/article/details/83308