python 100行代码实现 12306 自动抢票

基于SeleniumChrome浏览器实现。
默认抢票类型为普通票,硬座。需求多的话可以在源码里改,我写的注释挺详细。
复制粘贴就能使用,2019年8月13日 测试可用。

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait,Select
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time,sys

class robTickets(object):
    def __init__(self):
        '登录页、主页、抢票页'
        self.login_url="https://kyfw.12306.cn/otn/resources/login.html"
        self.initmy_url="https://kyfw.12306.cn/otn/view/index.html"
        self.search_url="https://kyfw.12306.cn/otn/leftTicket/init"
        self.driver = webdriver.Chrome()
        self.hastictket=False

    def run(self):
        self._login()
        self._order_ticket()

    def _login(self):
        '登录页面手动登录'
        self.driver.get(self.login_url)
        time.sleep(1)
        self.driver.find_element_by_class_name("login-hd-account").click()
        username = input("请输入 用户名/手机号/邮箱 :")
        password = input("请输入 密码:")
        print("请在浏览器中完成验证码并确认")
        self.driver.find_element_by_id("J-userName").send_keys(username)
        self.driver.find_element_by_id("J-password").send_keys(password)
        WebDriverWait(self.driver,1000).until(
            EC.url_to_be(self.initmy_url)
        )
        print("登录成功!")
        self._wait_input()
        self._order_ticket()

    def _wait_input(self):
        self.from_station=input("请输入出发地:")
        self.to_station=input("请输入目的地:")
        self.depart_time=input("出发时间(yyy-mm-dd):")

    def _order_ticket(self):
        '选票页面手动选票,自动抢票'
        self.driver.get(self.search_url)
        self.url = "https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=%s,BJP&ts=%s,SHH&date=%s&flag=N,N,Y"%(self.from_station,self.to_station,self.depart_time)
        self.driver.get(self.url)
        self.order_url="https://kyfw.12306.cn/otn/confirmPassenger/initDc"

        WebDriverWait(self.driver,60).until(
            EC.presence_of_all_elements_located((By.XPATH,"//tbody[@id='queryLeftTable']/tr"))
        )
        tr_list = self.driver.find_elements_by_xpath("//tbody[@id='queryLeftTable']/tr[not(@datatran)]")
        print("共搜索到 "+str(len(tr_list))+" 条结果!")

        self.passengers = input("请输入乘客姓名(多个乘客的话,用英文逗号隔开):").split(",")
        self.trains = input("请输入车次(多个车次,用英文逗号隔开):").split(",")

        # 循环检票
        TNT = int(input("抢票监测时间(秒):"))
        st = time.time()
        i=0
        while time.time()-st<TNT:
            for tr in tr_list:
                train_number = tr.find_element_by_class_name("number").text
                if train_number in self.trains:
                    self.hastictket=True
                    ticket = tr.find_element_by_xpath(".//td[last()-3]").text
                    if ticket == "有" or ticket.isdigit():
                        print(train_number+" "+ticket+" 票")
                        tr.find_element_by_class_name("btn72").click()
                        self._money()
            if self.hastictket==False:
                print("未查询到相关班次!")
                self.driver.quit()
                sys.exit()
            # 未找到票,刷新界面
            self.driver.refresh()
            tr_list = self.driver.find_elements_by_xpath("//tbody[@id='queryLeftTable']/tr[not(@datatran)]")
            WebDriverWait(self.driver, 60).until(
                EC.presence_of_all_elements_located((By.XPATH, "//tbody[@id='queryLeftTable']/tr"))
            )
            i+=1
            print("抢票第 %d 次"%i)

    def _money(self):
        '支付界面自动下单'
        WebDriverWait(self.driver, 60).until(
            EC.url_to_be(self.order_url)
        )
        WebDriverWait(self.driver, 60).until(
            EC.presence_of_all_elements_located((By.XPATH, "//ul[@id='normal_passenger_id']//li"))
        )
        lis = self.driver.find_elements_by_xpath("//ul[@id='normal_passenger_id']//li")
        x = 0
        for li in lis:
            # 遍历联系人寻找乘客
            if li.find_element_by_xpath("./label").text in self.passengers:
                li.find_element_by_xpath("./input[@class='check']").click()
                x += 1
                WebDriverWait(self.driver, 1000).until(
                    EC.visibility_of_element_located((By.ID, "seatType_%d" % x))
                )
                # 此处value为1代表硬座,修改此处可以更改票的类型
                selectTag = Select(self.driver.find_element_by_id("seatType_%d" % x))
                selectTag.select_by_value("1")

        print("正在提交订单,请等待60s...")
        self.driver.find_element_by_id("submitOrder_id").click()
        WebDriverWait(self.driver, 20).until(
            EC.element_to_be_clickable((By.ID, "qr_submit_id"))
        )
        # 提交并检查订单,此处限时60s
        start = time.time()
        while time.time() - start < 60:
            try:
                self.driver.find_element_by_xpath(r"//a[@id='qr_submit_id']").click()
            except:
                if self.driver.current_url != self.order_url:
                    print("订单已完成,请打开12306完成支付!")
                    time.sleep(1000)
                else:
                    if self.driver.find_element_by_xpath(r"//div[@class='tit']").text == "下单成功。":
                        print("订单已完成,请打开12306完成支付!")
                        self.driver.get("https://kyfw.12306.cn/otn/view/train_order.html")
                        time.sleep(1000)
                    else:
                        time.sleep(0.1)

if __name__=='__main__':
    print("本程序默认抓取的是普通票,硬座,想实现更多功能请在源码里修改")
    spider = robTickets()
    spider.run()

运行截图:
在这里插入图片描述

在这里插入图片描述

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值