12306抢票爬虫selenium+Chromedriver(升级版)

先看代码执行结果:

此爬虫是对之前版本爬虫(网络上大部分博客的版本)的修改和调整,具体具体流程如下:

  1. 运行程序时,输入出发地,目的地和出发城市。
  2. 若是学生,则选择学生票,学生身份需要通过12306网站验证。
  3. 登录完成之后,自动跳转到查询车次页面,这样做是想先让购票者比较各个车次信息之后,输入想要购买的车次和座次。
  4. 根据查询信息,输入想要购买的车次以及座次信息。
  5. 程序会自动根据输入的车次和乘车人进行购票。
  6. 购票成功后,程序会发送一条短信息给购票人,提示:您选择的车票预订成功,请在30分钟内,完成支付。

     

  7. 另外还可以通过pyinstaller -Fc 打包成exe文件,发给身边的小伙伴使用了。

代码如下:

# project: exe
# author: liulei   
# time: 2019/8/28 10:37  
# file: qiangpiao.py

import random
import re
import time
import requests
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from twilio.rest import Client


class qiangpiao1(object):
    def __init__(self):
        self.station_name_url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9108'
        self.login_url = 'https://kyfw.12306.cn/otn/login/init'
        self.initmy_url = 'https://kyfw.12306.cn/otn/view/index.html'
        self.url = ''
        self.confirmPassenger = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
        self.driver = webdriver.Chrome(executable_path=r'D:\chromedriver_win32\chromedriver.exe')

    def input_info(self):
        r = requests.get(self.station_name_url)
        # print(r.text)
        pattern = u'([\u4e00-\u9fa5]+)\|([A-Z]+)'
        # print(pattern)
        result = re.findall(pattern, r.text)
        city_dic = dict(result)  # 所有车站信息
       
        from_station = input('输入出发城市:')
        from_station_code = city_dic[from_station]
        fs1 =(from_station, from_station_code)
        fs = ",".join(fs1)
        to_station = input('输入目的城市:')
        to_station_code = city_dic[to_station]
        ts1 = (to_station, to_station_code)
        ts = ",".join(ts1)
        date = input('出发日期(eg:2018-08-28):')

        flag = input("学生购票请输入'学生',普通票直接回车: ")
        if flag == '学生':
            flag = 'Y,N,Y'
        else:
            flag = 'N,N,Y'
        # https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=%E5%8C%97%E4%BA%AC,BJP&ts=%E4%B8%8A%E6%B5%B7,SHH&date=2019-08-30&flag=N,N,Y
        url = (
            'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&'
            'fs={}&'
            'ts={}&'
            'date={}&'
            'flag={}'
        ).format(fs, ts, date, flag)
        self.url = url

    def login(self):
        print("请到网页完成登录:")
        self.driver.get(self.login_url)
        WebDriverWait(self.driver, 1000).until(EC.url_to_be(self.initmy_url))
        print("恭喜您,登录成功!")
        self.driver.get(self.url)
  

    def order_ticket(self):
        trains = input("请根据查询结果输入车次: ")
        seat_info = input("请输入座次信息(9:商务座,M:一等座,O:二等座,4:软卧,3:硬卧,1:硬座): ")
        # seat_info = input("请输入座次信息(1:商务座,2:一等座,3:二等座,4:软卧,5:硬卧,6:硬座): ")
        passengers = input("请输入乘车人(多名乘客用英文逗号隔开): ")
        WebDriverWait(self.driver, 1000).until(
            EC.presence_of_element_located((By.XPATH, ".//tbody[@id = 'queryLeftTable']/tr")))
        tr_list = self.driver.find_elements_by_xpath(".//tbody[@id ='queryLeftTable']/tr[not(@datatran)]")
        left_ticket = ''
        for tr in tr_list:
            train_number = tr.find_element_by_class_name('number').text
      

            if train_number in trains:

                # 如果暂时无票,抢票(循环不停的刷新余票)
                count = 1
                searchBotton = self.driver.find_element_by_id("query_ticket")
                while left_ticket == '无' or left_ticket == '--' or left_ticket == '候补':
                    # print("该车次暂无余票,正在进行第%s次抢票···" % count)
                    print("暂无余票,正在尝试第%s次抢票···" % count)
                    time.sleep(random.randint(30, 90))
                    searchBotton.click()
                    count += 1

                if left_ticket == '有' or left_ticket.isdigit:  # 判断输入的车次是否在列表中
                    orderBotton = tr.find_element_by_class_name('btn72')
                    orderBotton.click()

                    # 等待是否来到乘客确认页面
                    WebDriverWait(self.driver, 1000).until(EC.url_to_be(self.confirmPassenger))
                    # 等待所有的乘客信息被加载完毕
                    WebDriverWait(self.driver, 1000).until(
                        EC.presence_of_element_located((By.XPATH, ".//ul[@id = 'normal_passenger_id']/li")))
                    # 获取席别信息
                    seat_types = self.driver.find_element_by_xpath('.//select[starts-with(@id,"seatType")]')
                    seat_ptions_list = seat_types.find_elements_by_tag_name("option")
                    for option in seat_ptions_list:
                        # print("Value is: " + option.get_attribute("value"))
                        # print("Text is: " + option.text.strip())
                        # print("Seat info is: " + seat_info)
                        # if left_ticket in option.text:
                        seat_text = option.text.strip()
                        if seat_info in option.get_attribute("value"):
                            option.click()

                    # 获取所有的乘客信息
                    passanger_labels = self.driver.find_elements_by_xpath(".//ul[@id = 'normal_passenger_id']/li/label")
                    for passanger_label in passanger_labels:  # 遍历所有的label标签
                        name = passanger_label.text
                        if name in passengers:  # 判断名字是否与之前输入的名字重合
                            time.sleep(1)
                            passanger_label.click()  # 执行点击操作
                    submitBotton = self.driver.find_element_by_id('submitOrder_id')
                    time.sleep(1)
                    submitBotton.click()
                    # 显示等待确认订单对话框是否出现
                    WebDriverWait(self.driver, 1000).until(
                        EC.presence_of_element_located((By.CLASS_NAME, 'dhtmlx_wins_body_outer')))
                    # 显示等待确认按钮是否加载出现,出现后执行点击操作
                    WebDriverWait(self.driver, 1000).until(EC.presence_of_element_located((By.ID, 'qr_submit_id')))
                    ConBotton = self.driver.find_element_by_id('qr_submit_id')
                    time.sleep(1)
                    ConBotton.click()
                    self.send_message(trains)
                    print("恭喜,您的%s车次车票预定成功,请检查信息无误后,手动完成支付!祝您旅途愉快!" % trains)
                    print("车票预订完成,系统即将退出……")
                    exit()

    def run(self):
        self.input_info()
        self.login()
        self.order_ticket()


if __name__ == '__main__':
    spider = qiangpiao1()
    spider.run()

PS:

  • 该爬虫不能实现自动付款功能,需要购票者在30分钟内手动完成付款。
  • 判断用户输入的购票日期,是否是可购票的日期内。
  • 该程序,还是需要用户手动登录完成,特别是登录时的图片验证码,笔者打算研究下通过程序自动识别图片验证码,从而实现自动登录的功能,最大的障碍是自动识别图片验证码,需要大量的机器训练。

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页