nyatom

  悲催的12306,彻底沦为各路抢票软件的服务提供方。元旦伊始,纯粹12306官网及APP抢票,愈一周的时间,仅到手一张凌晨3:55回家的站票。为远离脑残,无奈选择抢票软件,预购年后返沪车票。BTW,研究一下抢票脚本的实现思路,参考:(https://juejin.im/post/5b116504f265da6e0636cbc2 - Python3.6实现12306火车票自动抢票)。

  在原作者之上,对执行代码做了以下处理:

  1. 删除短信/邮件通知功能
  2. 删除控制台输入功能
  3. 新增登陆cookie的刷新
  4. 新增多车次抢票
  5. 新增多座位类型抢票

  注:使用 splinter.browser 在调用时,注意将 chrome驱动路径(chromedriver.exe所在)配置在环境变量 -  path 下。

代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from splinter.browser import Browser
from time import sleep
import sys

class BrushTicket(object):
    """买票类及实现方法"""
    def __init__(self, passengers, from_time, from_station, to_station, number_seat):
        """定义实例属性,初始化"""
        # 乘客姓名
        self.passengers = passengers
        # 起始站和终点站
        self.from_station = from_station
        self.to_station = to_station
        # 乘车日期
        self.from_time = from_time
        # 车次 - 座位 dict
        num_seat_dic = {}
        for num_seat in number_seat:
            use = num_seat.split(\':\')
            num = use[0]
            seats = use[1]
            seats_use = seats.split(\',\')
            seat_str = \'\'
            for seat in seats_use:
                # 座位类型所在td位置
                if seat == \'商务座特等座\':
                    seat_type_index = 1
                    seat_type_value = 9
                elif seat == \'一等座\':
                    seat_type_index = 2
                    seat_type_value = \'M\'
                elif seat == \'二等座\':
                    seat_type_index = 3
                    seat_type_value = 0
                elif seat == \'高级软卧\':
                    seat_type_index = 4
                    seat_type_value = 6
                elif seat == \'软卧\':
                    seat_type_index = 5
                    seat_type_value = 4
                elif seat == \'动卧\':
                    seat_type_index = 6
                    seat_type_value = \'F\'
                elif seat == \'硬卧\':
                    seat_type_index = 7
                    seat_type_value = 3
                elif seat == \'软座\':
                    seat_type_index = 8
                    seat_type_value = 2
                elif seat == \'硬座\':
                    seat_type_index = 9
                    seat_type_value = 1
                elif seat == \'无座\':
                    seat_type_index = 10
                    seat_type_value = 1
                elif seat == \'其他\':
                    seat_type_index = 11
                    seat_type_value = 1
                else:
                    seat_type_index = 7
                    seat_type_value = 3
                seat_str += (str(seat_type_index) + \'-\' + str(seat_type_value) + \',\')
            num_seat_dic[num] = seat_str
        self.num_seat_dic = num_seat_dic
        # 新版12306官网主要页面网址
        self.login_url = \'https://kyfw.12306.cn/otn/resources/login.html\'
        self.init_my_url = \'https://kyfw.12306.cn/otn/view/index.html\'
        self.ticket_url = \'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc\'
        # 浏览器驱动信息,驱动下载页:https://sites.google.com/a/chromium.org/chromedriver/downloads
        self.driver_name = \'chrome\'
        self.driver = Browser("chrome")
    def do_login(self):
        """登录功能实现,手动识别验证码进行登录"""
        self.driver.visit(self.login_url)
        sleep(1)
        # 选择登陆方式登陆
        print(\'请扫码登陆或者账号登陆……\')
        while True:
            if self.driver.url != self.init_my_url:
                sleep(1)
            else:
                break
    def start_brush(self):
        """买票功能实现"""
        # 浏览器窗口最大化
        self.driver.driver.maximize_window()
        # 登陆
        self.do_login()
        # 跳转到抢票页面
        self.driver.visit(self.ticket_url)
        try:
            print(\'开始刷票……\')
            # 加载车票查询信息
            self.driver.cookies.add({"_jc_save_fromStation": self.from_station})
            self.driver.cookies.add({"_jc_save_toStation": self.to_station})
            self.driver.cookies.add({"_jc_save_fromDate": self.from_time})
            self.driver.reload()
            count = 0
            while self.driver.url == self.ticket_url:
                self.driver.find_by_text(\'查询\').click()
                sleep(1)
                count += 1
                print(\'第%d次点击查询……\' % count)
                if count % 50 == 0:
                    self.driver.find_by_id(\'login_user\').click()
                    sleep(1)
                    self.driver.visit(self.ticket_url)
                    sleep(1)
                    print(\'继续刷票......\')
                    # 加载车票查询信息
                    self.driver.cookies.add({"_jc_save_fromStation": self.from_station})
                    self.driver.cookies.add({"_jc_save_toStation": self.to_station})
                    self.driver.cookies.add({"_jc_save_fromDate": self.from_time})
                    self.driver.reload()
                    if self.driver.url == self.ticket_url:
                        continue
                try:
                    # 多车次处理
                    for bander in self.num_seat_dic.keys():
                        current_tr = self.driver.find_by_xpath(\'//tr[@datatran="\' + bander + \'"]/preceding-sibling::tr[1]\')
                        if current_tr:
                            # 多座次处理
                            seat_value = self.num_seat_dic[bander]
                            seat_split = seat_value.split(\',\')
                            for seat in seat_split:
                                if seat:
                                    seat_type = seat.split(\'-\')
                                    seat_type_index = int(seat_type[0])
                                    seat_type_value = int(seat_type[1])
                                    if current_tr.find_by_tag(\'td\')[seat_type_index].text == \'--\':
                                        print(bander + \' 还未出售\')
                                        sleep(1)
                                    elif current_tr.find_by_tag(\'td\')[seat_type_index].text == \'无\':
                                        print(bander + \' 无票,继续尝试……\')
                                        sleep(1)
                                    else:
                                        # 有票,尝试预订
                                        print(bander + \' 刷到票了(余票数:\' + str(
                                            current_tr.find_by_tag(\'td\')[seat_type_index].text) + \'),开始尝试预订……\')
                                        current_tr.find_by_css(\'td.no-br>a\')[0].click()
                                        sleep(1)
                                        key_value = 1
                                        for p in self.passengers:
                                            # 选择用户
                                            print(\'开始选择用户……\')
                                            self.driver.find_by_text(p).last.click()
                                            # 选择座位类型
                                            print(\'开始选择席别……\')
                                            if seat_type_value != 0:
                                                self.driver.find_by_xpath(
                                                    "//select[@id=\'seatType_" + str(key_value) + "\']/option[@value=\'" + str(
                                                        seat_type_value) + "\']").first.click()
                                            key_value += 1
                                            sleep(0.2)
                                            if p[-1] == \')\':
                                                self.driver.find_by_id(\'dialog_xsertcj_ok\').click()
                                        print(\'正在提交订单……\')
                                        self.driver.find_by_id(\'submitOrder_id\').click()
                                        sleep(2)
                                        # 查看放回结果是否正常
                                        submit_false_info = self.driver.find_by_id(\'orderResultInfo_id\')[0].text
                                        if submit_false_info != \'\':
                                            print(submit_false_info)
                                            self.driver.find_by_id(\'qr_closeTranforDialog_id\').click()
                                            sleep(0.2)
                                            self.driver.find_by_id(\'preStep_id\').click()
                                            sleep(0.3)
                                            continue
                                        print(\'正在确认订单……\')
                                        self.driver.find_by_id(\'qr_submit_id\').click()
                                        print(\'预订成功,请及时前往支付……\')
                        else:
                            print(\'不存在当前车次【%s】,已结束当前刷票,请重新开启!\' % self.number)
                            sys.exit(1)
                except Exception as error_info:
                    print(error_info)
        except Exception as error_info:
            print(error_info)
if __name__ == \'__main__\':
    # nya
    passengers=[\'***\'] # 用户名
    from_time=\'2019-02-01\' # 出发日期
    from_station=\'%u4E0A%u6D77%2CSHH\'  # 起始站点 - 来自12306 余票查询 请求 - cookie (此处 - 上海)
    to_station=\'%u6C11%u6743%2CMQF\' # 结束站点 (此处 - 民权)
    number_seat=[\'K4054:硬座,无座\',\'K4168:硬座,无座\'] # 车次:座位类型
    # 开始抢票
    ticket = BrushTicket(passengers, from_time, from_station, to_station, number_seat)
    ticket.start_brush()

分类:

技术点:

相关文章:

  • 2022-02-08
  • 2021-07-15
  • 2021-05-10
  • 2022-01-14
  • 2022-02-27
  • 2021-12-18
  • 2021-09-05
  • 2021-07-28
猜你喜欢
  • 2021-12-25
  • 2021-06-17
  • 2021-10-05
  • 2021-12-10
  • 2021-12-16
  • 2021-04-02
  • 2021-05-03
相关资源
相似解决方案