Python-又到了抢票的季节(带验证码识别验证)

本文介绍了一位新手程序员如何使用Python从零开始构建一个12306抢票助手的过程,详细讲解了获取验证码、自动识别、登录验证及后续操作的步骤,适合Python初学者和对抢票程序感兴趣的人士。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

初入Python,打算搞个练手项目,正巧又到了抢票的季节,那就12306了,反正也早就被玩坏了,哈哈哈哈。。。由于是边练手边写的,为了方便,没有啥优雅的姿势,每个功能一个方法大概如下:

1.获取登录需要的验证码图片保存到本地
2.自动识别验证码(或手动识别)
3.验证验证码并登录
4.多重验证(验证之后才能获取真正的登录状态)
5.扫票
6.下订单
7.获取联系人
8....

大概是这么个样子,那么就开始吧~~~~~~~~
复制代码

直奔主题:

用到的包:
import json
import random
import re
import time
import requests
复制代码

第一步:获取验证码图片保存到本地

# 首先为了之后能保持登录状态,我们要先弄一个全局的会话,以后的session都是这个了
session = requests.session()
# 获取验证码图片并保存
def get_code():
    # 这是验证码图片接口 后面是个随机数
    code_url = 'https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{}'.format(
        str(random.random()))
    r = session.get(code_url)
    with open('code.png', 'wb') as f:
        f.write(r.content)
    print('获取验证码并保存成功')
复制代码

第二步:获取验证码的正确坐标

首先我们看到保存的验证图片如下(已打上编号):

那么就先说下手动验证,就是用你的钛合金狗眼分辨上图 然后输入:4 6

# 对8个小图坐标化,因为最终验证接口是得用坐标做参数的,比如上图对应的参数就应该是: 260,40,110,120
code = ['40,40', '110,40', '180,40', '260,40', '40,120', '110,120', '180,120', '260,120']
# 识别验证码 并得到正确坐标
def code_answer():
    num = input('请输入:')
    try:
        num = [int(num)]
    except ValueError:
        num = list(map(int, num.split()))
    answer = ''  # 构建一个空字符串
    for i in num:  # 对验证码序号列表进行遍历
        answer += code[i - 1] + ','  # 将每个验证码序号对应的位置信息添加到字符串中,并加上','号
    answer_result = answer.rstrip(',')
    print('得到验证码坐标:', answer_result)
    return answer_result
复制代码

然后就是高科技了,使用一个牛X的网站自动识别(最近不大稳定,可能要多几次):

# 识别验证码 并得到正确坐标
def code_answer():
    # 自动识别的网站 
    url = 'http://littlebigluo.qicp.net:47720/'
    files = {'file': open('code.png', 'rb')}
    r = session.post(url, files=files)
    num = r.text.split('<B>')[1].split('<')[0]
    #其实也就是上面这块获取 num 手动改成自动了 有兴趣的朋友可以做个判断,自动不稳定时提醒手动输入
    try:
        num = [int(num)]
    except ValueError:
        num = list(map(int, num.split()))
    print(num)
    answer = ''  # 构建一个空字符串
    for i in num:  # 对验证码序号列表进行遍历
        answer += code[i - 1] + ','  # 将每个验证码序号对应的位置信息添加到字符串中,并加上','号
    answer_result = answer.rstrip(',')
    print('得到验证码坐标:', answer_result)
    return answer_result
复制代码

第三步:验证验证码并登录

def check_and_login():
    # 如果之前没加 User-Agent 这里加一下
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
    }
    # 验证验证码的接口
    check_url = 'https://kyfw.12306.cn/passport/captcha/captcha-check'
    # 登录接口
    login_url = 'https://kyfw.12306.cn/passport/web/login'
    # 验证参数
    check_data = {
        'answer': code_answer(),# 这里就是上面我们得到的验证码坐标
        'login_site': 'E',
        'rand': 'sjrand'
    }
    # 登录参数
    login_data = {
        'username': '12306账号',
        'password': '12306密码',
        'appid': 'otn'
    }
    print('开始验证验证码...')
    check_r = session.post(check_url, data=check_data, headers=headers, verify=False)  # 注意关掉SSL验证
    check_result = json.loads(check_r.text)
    if check_result['result_code'] == '4':  # 4代表成功,5代表验证码错误,8代表验证信息为空
        print(check_result['result_message'])
        login_r = session.post(login_url, data=login_data, headers=headers, verify=False)
        login_result = json.loads(login_page.text)
        print(login_result)
        # 这里就是表面上登录成功了,但是是得不到用户信息得,还得需要多次验证
        validate_apptk(get_apptk()) # 获取tk并验证tk
        isLogin() # 验证登录 如果正确 返回带有实名的结果 至此登录完成
    else:
        print('验证失败,开始重新验证')
        get_code()
        check_and_login()
        return
复制代码

第四步:验证登录

# 首先获取一个 apptk
def get_apptk():
    url = 'https://kyfw.12306.cn/passport/web/auth/uamtk'
    data = {'appid': 'otn'}
    r = session.post(url, data=data)
    result = json.loads(r.text)
    return result['newapptk']
# tk验证 把上面获取到的 apptk Post去验证
def validate_apptk(newapptk):
    url = 'https://kyfw.12306.cn/otn/uamauthclient'
    data = {'tk': newapptk}
    r = session.post(url, data=data)
    result = json.loads(r.text)
    print('postTk', result)
# 最后验证
def isLogin():
    url = 'https://kyfw.12306.cn/otn/login/conf'
    r = session.get(url)
    result = json.loads(r.text)
    print(result) # 打印结果 如果结果有 name = 你的实名 则真正登录成功,接下来就可以用这个保存登录状态的session去浪了~
复制代码

第五步: 下面就是真正的骚操作了

都已经拿到保存登录状态的session了,接下来 就是抓接口 去扫票下单了。 接口就不说了,我用的google浏览器 打开12306网站 F12 然后正常操作一遍扫票流程,就可以在右找到了。吃饭前给到大家发个红包 滑稽~滑稽~

转载于:https://juejin.im/post/5c18be5cf265da610e800541

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值