本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理

这个是实现结果,因为一天只能取消三次,所以最后一步点击确认被我注释了
1.首先实现使用selenium登陆12306
 这里实现了使用selenium登陆12306,实现全自动登陆12306链接
2.根据上面实现登陆后,实现购买火车票还需两步

这里只进行了二等座的查询和购票,想要买其他的自己也可以进行修改 1.进行车票的查询 这里面需要注意的是在输入目的地和起始地时需要先click一下文本框browser.find_element_by_id(‘fromStationText’).click() 不然输入的地址无效 还有将日期的只读属性去掉

def search_railway_ticket(fromstation,tostation,train_date):
    # 火车票页面查询url
    search_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
    # 转到查询车次页面
    browser.get(search_url)
    time.sleep(2)
    #输入出发地
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'fromStationText'))
    )
    #先点击一下
    browser.find_element_by_id('fromStationText').click()
    browser.find_element_by_id('fromStationText').send_keys(fromstation)
    browser.find_element_by_id('fromStationText').send_keys(Keys.ENTER)
    time.sleep(1)
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'toStationText'))
    )
    #输入目的地
    browser.find_element_by_id('toStationText').click()
    browser.find_element_by_id('toStationText').send_keys(tostation)
    browser.find_element_by_id('toStationText').send_keys(Keys.ENTER)
    time.sleep(5)
    #将日期的只读属性去掉
    js = 'document.getElementById("train_date").removeAttribute("readonly")'
    browser.execute_script(js)
    #去掉原本的时间
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'train_date'))
    )
    browser.find_element_by_id("train_date").clear()
    #输入出发时间
    browser.find_element_by_id('train_date').send_keys(train_date)
    # 等待查询按钮是否可用
    WebDriverWait(browser, 1000).until(
        EC.element_to_be_clickable((By.ID, 'query_ticket'))
    )
    searBtn = browser.find_element_by_id('query_ticket')
    searBtn.click()
    print('点击按钮')

2.购买火车票 在这个函数中需要注意的是最好把最后一步注释掉 browser.find_element_by_id(‘qr_submit_id’).click() 因为一天只能取消3次订单

def buy_ticket(fromstation,tostation,train_date,train_number,passenger):
 
    #查询火车票
    search_railway_ticket(fromstation,tostation,train_date)
    time.sleep(5)
    #获取每一个车次的信息
    tr_list = browser.find_elements_by_xpath('.//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
    for tr in tr_list:
        #获取车次号
        number = tr.find_element_by_class_name('number').text
        if number in  train_number:
            #获取是否还有票
            left_ticket = tr.find_element_by_xpath('./td[4]').text
            if left_ticket =='有'or left_ticket.isdigit:
                print(f'{number}还有票')
                #点击预订
                orderBtn = tr.find_element_by_class_name('btn72')
                orderBtn.click()
                time.sleep(5)
                #获取12306中乘客的信息
                passenger_list = browser.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li')
                for li in passenger_list:
                    name = li.find_element_by_xpath('./label').text
                    print(name)
                    #配对12306人名
                    if name == passenger:
                        li.find_element_by_tag_name('input').click()
                #提交订单
                submit = browser.find_element_by_id('submitOrder_id')
                submit.click()
                WebDriverWait(browser, 1000).until(
                    EC.element_to_be_clickable((By.ID, 'qr_submit_id'))
                )
                #一天只能取消3次 所以最好把最后一步注释了
                browser.find_element_by_id('qr_submit_id').click()
                print('已经提交订单')
                break

下面是源代码

测试的时候可以把#click_captcha()这个点击验证码的去掉自己手动点击,这样就不用扣超级鹰的积分(有钱的话当我没说),留下了贫穷的泪水。

from selenium import webdriver
from selenium.webdriver import Actionchains
import time
from PIL import Image
import requests
from hashlib import md5
from selenium.webdriver import ChromeOptions
#验证码识别处理
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
 
class Chaojiying_Client(object):
 
    def __init__(self, username, password, soft_id):
        self.username = username
        password =  password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }
 
    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
        return r.json()
 
    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()
 
def login(username,password):
    # 填写账号密码
    browser.find_element_by_id('J-userName').send_keys(username)
    browser.find_element_by_id('J-password').send_keys(password)
 
    # 获取验证码
    get_captcha()
 
    # 填写验证码
    click_captcha()
 
    #点击登录
    time.sleep(4)
    browser.find_element_by_id('J-login').click()
    time.sleep(4)
 
    #滑动验证码
    slider()
 
    print('成功登陆')
    time.sleep(5)
 
def slider():
    #滑动验证码
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.XPATH, '//*[@id="nc_1_n1z"]'))
    )
    span = browser.find_element_by_xpath('//*[@id="nc_1_n1z"]')
    # 对div_tag进行滑动操作
    action = Actionchains(browser)
    # 点击长按指定的标签
    action.click_and_hold(span).perform()
    action.drag_and_drop_by_offset(span, 400, 0).perform()
 
def click_captcha():
    # 获取验证码需要的为点击位置
    chaojiying = Chaojiying_Client('自己的用户名', '密码', '软件id')  # 用户中心>>软件ID 生成一个替换 96001
    im = open('./captcha.png', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    location = chaojiying.PostPic(im, 9004)['pic_str']  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
    print(chaojiying.PostPic(im, 9004))
    # 将位置进行分割成    [  [  ], [ ], [ ]  ]类型
    location_list = [i.split(',') for i in location.split('|')]
    for l in location_list:
        x = l[0]
        y = l[1]
        Actionchains(browser).move_to_element_with_offset(browser.find_element_by_class_name('login-pwd-code'), int(x),int(y)).click().perform()
        time.sleep(0.5)
 
def get_captcha():
    # 获取网页的截图
    allscreen = browser.get_screenshot_as_file('allscreen.png')
    # 获取captcha
    captcha = browser.find_element_by_class_name('login-pwd-code')
    # 获取captcha的左上角位置
    location = captcha.location
    # 获取图片大小
    size = captcha.size
    # 裁取captcha
    rangle = (location['x'],location['y'],(location['x']+size['width']),(location['y']+size['height']))
    i = Image.open('./allscreen.png')
    captcha_img = './captcha.png'
    frame = i.crop(rangle)
    frame.save(captcha_img)
 
def buy_ticket(fromstation,tostation,train_date,train_number,passenger):
 
    #查询火车票
    search_railway_ticket(fromstation,tostation,train_date)
    time.sleep(5)
    tr_list = browser.find_elements_by_xpath('.//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
    for tr in tr_list:
        number = tr.find_element_by_class_name('number').text
        if number in  train_number:
            left_ticket = tr.find_element_by_xpath('./td[4]').text
            if left_ticket =='有'or left_ticket.isdigit:
                print(f'{number}还有票')
                orderBtn = tr.find_element_by_class_name('btn72')
                orderBtn.click()
                time.sleep(5)
                passenger_list = browser.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li')
                for li in passenger_list:
                    name = li.find_element_by_xpath('./label').text
                    if name == passenger:
                        li.find_element_by_tag_name('input').click()
                submit = browser.find_element_by_id('submitOrder_id')
                submit.click()
                WebDriverWait(browser, 1000).until(
                    EC.element_to_be_clickable((By.ID, 'qr_submit_id'))
                )
                #一天只能取消3次 所以把最后一步注释了
                # browser.find_element_by_id('qr_submit_id').click()
                print('已经提交订单')
                break
 
def search_railway_ticket(fromstation,tostation,train_date):
    # 火车票页面查询url
    search_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
    # 转到查询车次页面
    browser.get(search_url)
    time.sleep(2)
    #输入出发地
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'fromStationText'))
    )
    #先点击一下
    browser.find_element_by_id('fromStationText').click()
    browser.find_element_by_id('fromStationText').send_keys(fromstation)
    browser.find_element_by_id('fromStationText').send_keys(Keys.ENTER)
    time.sleep(1)
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'toStationText'))
    )
    #输入目的地
    browser.find_element_by_id('toStationText').click()
    browser.find_element_by_id('toStationText').send_keys(tostation)
    browser.find_element_by_id('toStationText').send_keys(Keys.ENTER)
    time.sleep(5)
    #将日期的只读属性去掉
    js = 'document.getElementById("train_date").removeAttribute("readonly")'
    browser.execute_script(js)
    #去掉原本的时间
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'train_date'))
    )
    browser.find_element_by_id("train_date").clear()
    #输入出发时间
    browser.find_element_by_id('train_date').send_keys(train_date)
    # 等待查询按钮是否可用
    WebDriverWait(browser, 1000).until(
        EC.element_to_be_clickable((By.ID, 'query_ticket'))
    )
    searBtn = browser.find_element_by_id('query_ticket')
    searBtn.click()
    print('点击按钮')
 
if __name__ == '__main__':
    option = ChromeOptions()  # 实例化一个ChromeOptions对象
    option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 以键值对的形式加入参数
    option.add_experimental_option('useAutomationExtension', False)
 
    browser = webdriver.Chrome(options=option)
    # 获取响应
    browser.get('https://kyfw.12306.cn/otn/resources/login.html')
    script = 'Object.defineProperty(navigator,"webdriver",{get:()=>undefined,});'
    browser.execute_script(script)
    browser.maximize_window()
    time.sleep(1)
 
    # 点击账号登陆
    browser.find_element_by_class_name('login-hd-account').click()
    #登陆12306的账号密码
    login('用户名','密码')
    time.sleep(4)
    #例buy_ticket('南昌','抚州北','2020-12-15','D2241','xx')
    buy_ticket('起始地','目的地','出发日期','车次','姓名')

想要获取更多Python学习资料可以加
QQ:2955637827私聊
或加Q群630390733
大家一起来学习讨论吧!

Python实现全自动购买火车票!抢票回家过年咯的更多相关文章

  1. 春运到了,带你用python来抢票回家!

    不知不觉,一年一度的春运抢票大幕已经拉开,想快速抢到回家的车票吗?作为程序员,这些技术手段,你一定要知道. 为了让大家更快捷更便利的抢火车票,各种各样的抢票软件应需而生,这类软件大部分都是付费抢票的机 ...

  2. 火车票抢票API 根据乘客的车次与座席要求快速订票出票

    火车票抢票API 根据乘客的车次与座席要求快速订票出票:https://www.juhe.cn/docs/api/id/257 1.站站查询 接口地址:http://v.juhe.cn/grabTic ...

  3. python 并发编程 多进程 模拟抢票

    抢票是并发执行 多个进程可以访问同一个文件 多个进程共享同一文件,我们可以把文件当数据库,用多个进程模拟多个人执行抢票任务 db.txt {"count": 1} 并发运行,效率高 ...

  4. 实测两款 GitHub 开源抢票插件,所有坑都帮你踩过了

    如果你对自己手速和市面上的各种 “加速包” 都没什么信心的话,不妨试试用程序员的手段抢票? 况且,[12306 官方宣布屏蔽了一大批付费抢票软件],这也意味着你即使给这些软件付了会员费,也依旧抢不到票 ...

  5. 四、基于HTTPS协议的12306抢票软件设计与实现--水平DNS并发查询分享

    一.基于HTTPS协议的12306抢票软件设计与实现--实现效果 二.基于HTTPS协议的12306抢票软件设计与实现--相关接口以及数据格式 三.基于HTTPS协议的12306抢票软件设计与实现-- ...

  6. 智行火车票免费加速到VIP最高速抢票(不用朋友积攒或者购买加速包)

    更新: 2018.11.07, 昨天我买火车票,已经不行了,这个bug已经没有了,被修复了, 望大家知悉!!! 智行火车票免费加速到VIP最高速抢票(不用朋友积攒或者购买加速包) 1)下过单后选择抢到 ...

  7. 用Python抢到回家的车票,so easy!

    “ 盼望着,盼望着,春节的脚步近了,然而,每年到这个时候,最难的,莫过于一张回家的火车票. ​ 据悉,今年春运期间,全国铁路发送旅客人次同比将增长 8.0%.达到 4.4 亿人次. ​ 2020 年铁 ...

  8. 简单的Python 火车抢票程序

    当你想查询一下火车票信息的时候,你还在上12306官网吗?或是打开你手机里的APP?下面让我们来用Python写一个命令行版的火车票查看器, 只要在命令行敲一行命令就能获得你想要的火车票信息!如果你刚 ...

  9. Python操作12306抢票脚本

    有一段时间没有使用Python了,前几天经朋友提起一篇关于用Python实现抢火车票的文章,百度了实现抢火车票的技术细节,网上却有不少资料,也不是新鲜的东西.在了解了一些技术手段,阅读了一些大神的博文 ...

随机推荐

  1. css3系列之animation实现逐帧动画

    上面这个两个简单的动画,是用 animation-timing-function: steps();  这个属性实现的,具体如何实现,看下面: 这上面的图片,也就是我们的素材, 有些人,可能不是很理解 ...

  2. Codeforces Round #674 (Div. 3)

    A 除一下就完了. 时间复杂度 \(O\left(t\right)\). B 分在对称线上的矩阵和不在对称线上的矩阵讨论. 时间复杂度 \(O\left(tn^2\right)\). C 肯定是先增加 ...

  3. Java基础教程——字节流

    IO流 水流 特点 连续性 逝者如斯夫,不舍昼夜: 方向性 一江春水向东流.水往低处流.百川东到海,何时复西归?少壮不努力,老大徒伤悲! 源头尽头 唯有源头活水来:覆水难收 Java里的IO也有这样的 ...

  4. CentOS下搭建测试WEB平台

    LAMP MYSQL 下载免编译的软件包 cd /usr/local/src wget http://mirrors.sohu.com/mysql/MySQL-5.1/mysql-5.1.73-lin ...

  5. Springboot结合Jpa的外键使用

    当我们写项目的时候,总有些奇奇怪怪的理由,非让你连表查询,其实最好的就是什么都不连,数据库完全解耦 但我们还是要学习下Jpa怎么根据外键查询 (这里说下Jpa+springboot的感觉,刚开始就感觉 ...

  6. cJSON的使用

    1 安装cJSON github地址:https://github.com/DaveGamble/cJSON.git 下载完成后进入cJSON目录,执行下面命令生成Makefile文件 mkdir b ...

  7. django 不使用序列化器时进行查询结果序列化

    在app01views中添加 class User1(View): def post(self,request): user=User.objects.all() list=[] for i in u ...

  8. 转:csdn怎么快速别人的文章

    在csdn看到好的文章想转载,无奈找不到转载的功能,只能想办法了. 首先确定原文允许转载 在文章开头处一般有版权声明,如图 转载时要注明出处和作者 如何转载 用谷歌浏览器加载文章地址,打开文章 F12 ...

  9. PyQt(Python+Qt)学习随笔:containers容器类部件QStackedWidget堆叠窗口属性

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.堆叠窗口简介 StackedWidget堆叠窗口部件为一系列窗口部件的堆叠,对应类为QStack ...

  10. 第9.13节 Python文件操作总结

    本章老猿重点介绍了Python io模块的文件操作相关功能,包括文件打开.读.写.文件定位.文件关闭,并介绍了二进制文件和文本文件处理的差异,以及相关文件编码的一些知识,最后简单提及了Python中与 ...