python之12306自动查票

作者: 充电实践 | 来源:发表于2018-02-20 16:34 被阅读386次

    一、导读

    本篇文章所采用的技术仅用于学习、研究,任何其他用途请自行承担后果。

    12306自动查票使用到的python库主要是splinter,同时也涉及到查票的城市编码,具体的城市编码请在网络上搜索,基本格式如下:

    北京北:VAP

    北京东:BOP

    北京: BJP

    北京南:VNP

    北京西:BXP

    实现的功能包括:
    (1)自动打开Google浏览器,进入12306登录页面
    (1)命令行手动输入账号、密码、出发、目的地,时间等相关信息,登录验证图片需要手动选择。
    (2)自动填充输入,完成查询和页面跳转。

    后续可以优化的功能:
    (1)从配置文件中读取账号、密码、出发、目的地,时间等相关信息。
    (2)从配置文件中获取城市编码
    (3)登录验证图片可以使用第三方识别自动选择

    二、初识Splinter

    1.简介

    Splinter 是用 Python 开发的一个开源web自动化测试的工具集。 它可以帮你自动化浏览器的行为,比如浏览 URLs 并和页面进行交互。

    Splinter是现有浏览器之上抽象层自动化工具(如 Selenium, PhantomJSzope.testbrowser )。它具有 高级API ,这使得它很容易去编写Web应用程序的自动化测试。

    例如, 用Splinter填写一个表单项:

    browser.fill('username', 'janedoe')

    在Selenium中, 等效代码会是:

    elem = browser.find_element.by_name('username')

    elem.send_keys('janedoe')

    2.安装

    命令行下执行以下命令:sudo pip install splinter

    3.快速上手

    (1)导入Browser类

    from splinter.browser import Browser

    (2)创建一个实例

    指定driver为chrome浏览器,如果你不为 Browser 指定 driver, 那么会默认使用 firefox。

    browser = Browser(driver_name='chrome',executable_path='xxx')

    其中executable_path为对应浏览器driver的本地目录。

    (3)访问百度搜索页面

    使用 browser.visit 方法可访问任意网站:

    browser.visit('http://baidu.com')

    (4)输入搜索关键词

    页面加载完毕后,可以在输入框填充字段,大过年的我们就搜索一下2018年新年祝福吧:

    browser.fill('wd', '2018年新年祝福')

    (5)点击搜索按钮

    Splinter 可以通过按钮的css, xpath, id, tag 或 name来识别,百度搜素按钮使用以下来操作:

    button = browser.find_by_xpath('//input[@type="submit"]').click()

    (6)匹配结果

    使用is_text_present查看匹配结果:

    if browser.is_text_present('春节'):
    
        print("找到了")
    
    else:
    
        print("没找到")
    

    (7)关闭浏览器

    结束测试后,我们需要使用 browser.quit 关闭浏览器:

    browser**.**quit()

    完整代码如下:

    # -*- coding: utf-8 -*-
    
    #导入Browser类
    
    from splinter.browser import Browser
    
    #创建一个实例, 指定driver为chrome浏览器,如果你不为 Browser 指定 driver, 那么会默认使用 firefox。
    
    browser = Browser(driver_name='chrome',executable_path='/Users/xxx/Downloads/chromedriver')
    
    browser.visit('http://baidu.com')
    
    browser.fill('wd', '2018年新年祝福')
    
    button = browser.find_by_xpath('//input[@type="submit"]').click()
    
    if browser.is_text_present('春节'):
    
        print("找到了")
    
    else:
    
        print("没找到")
    
    browser.quit()
    

    三、12306自动查票
    1、流程分析
    (1)执行python脚本后,能够自动打开浏览器,进入12306登录页面。因此需要加载浏览器驱动并打开登录页面。

    (2)命令行提示用户输入用户名、密码,并等待用户手动在浏览器选择验证码完成登录。

    (3)命令行提示用户输入出发地、目的地以及出发时间。

    (4)根据输入查询车次信息

    2、示例代码
    代码均有详细注释,根据上面的流程分析,我们简化为三步。
    第一步是加载基本信息,包括浏览器、url等。第二步是输入个人信息登录。第三步是输入查询条件查询车次信息。

    # -*- coding: utf-8 -*-
    
    from splinter.browser import Browser
    from time import sleep
    
    class TicketsUtil(object):
        
        def __init__(self):
            self.loadBasicInfo()
            
        def loadBasicInfo(self):
            # 登录的url
            self.loginUrl = 'https://kyfw.12306.cn/otn/login/init'
            #登录成功后的url
            self.myUrl = 'https://kyfw.12306.cn/otn/index/initMy12306'
            #余票查询页面
            self.ticketUrl = 'https://kyfw.12306.cn/otn/leftTicket/init'
            # 初始化驱动
            self.driver=Browser(driver_name='chrome',executable_path='/Users/xxx/Downloads/chromedriver')
            # 初始化浏览器窗口大小
            self.driver.driver.set_window_size(1400, 1000)
    
        def login(self):
            print("开始登录...")
            # 登录
            self.driver.visit(self.loginUrl)
            
            self.username = input("\n请输入用户名,输入按回车...")
            #合法性判断
            while True:   
                if self.username == '':
                    self.username = input("\n请输入用户名,输入按回车...")
                else:
                    break
    
            self.password = input("\n请输入密码,输入按回车...")
            #合法性判断
            while True:   
                if self.password == '':
                    self.password = input("\n请输入密码,输入按回车...")
                else:
                    break
    
            # 自动填充用户名
            self.driver.fill("loginUserDTO.user_name", self.username)
            # 自动填充密码
            self.driver.fill("userDTO.password", self.password)
                
    
            print(u"等待验证码,自行输入...")
    
            # 验证码需要自行输入,程序自旋等待,直到验证码通过,点击登录
            while True:
                if self.driver.url != self.myUrl:
                    sleep(1)
                else:
                    break
            
            print(u"登录成功...")
                    
        def query(self):
            self.source = input("\n请输入出发地(格式为:北京,BJP),输入按回车...")
            #合法性判断
            while True:   
                if self.source == '':
                    self.source = input("\n请输入出发地(格式为:北京,BJP),输入按回车...")
                else:
                    break
                    
            self.destination = input("\n请输入目的地(格式为:深圳,SZQ),输入按回车...")
            while True:   
                if self.destination == '':
                    self.destination = input("\n请输入目的地(格式为:深圳,SZQ),输入按回车...")
                else:
                    break
                    
            self.date = input("\n请输入出发日期(格式为:2018-02-14),输入按回车...")
            while True:   
                if self.date == '':
                    self.date = input("\n请输入出发日期,输入按回车...")
                else:
                    break
            #转换输入的出发地成"武汉,WHN",再进行编码
            self.source = self.source.encode('unicode_escape').decode("utf-8").replace("\\u", "%u").replace(",", "%2c")
            #转换输入的目的地
            self.destination = self.destination.encode('unicode_escape').decode("utf-8").replace("\\u", "%u").replace(",", "%2c")
                      
            # 加载出发地
            self.driver.cookies.add({"_jc_save_fromStation": self.source})
            # 加载目的地
            self.driver.cookies.add({"_jc_save_toStation": self.destination})
            # 加载出发日
            self.driver.cookies.add({"_jc_save_fromDate": self.date})
            
            # 带着查询条件,重新加载页面
            self.driver.reload()
            # 查询余票
            self.driver.find_by_text(u"查询").click()
            sleep(0.1)
            # 防止超时再次查询余票
            self.driver.find_by_text(u"查询").click()
            
            print('查询成功')
    
        """入口函数"""
        def start(self):
            self.loadBasicInfo()
    
            # 登录,自动填充用户名、密码,自旋等待输入验证码,输入完验证码,点登录后,访问 tick_url(余票查询页面)
            self.login()
    
            # 登录成功,访问余票查询页面
            self.driver.visit(self.ticketUrl)
            
            self.query()
    
    if __name__ == '__main__':
        print(u"===========自动查票开启===========")
        ticketsUtil = TicketsUtil()
        ticketsUtil.start()
    
    
    

    相关文章

      网友评论

        本文标题:python之12306自动查票

        本文链接:https://www.haomeiwen.com/subject/gesgtftx.html