1. 程式人生 > >python之12306自動查票

python之12306自動查票

date con lee 例如 工具集 png 查看 個人 開源

技術分享圖片

一、導讀

本篇文章所采用的技術僅用於學習、研究,任何其他用途請自行承擔後果。

12306自動查票使用到的python庫主要是splinter,同時也涉及到查票的城市編碼,具體的城市編碼請在網絡上搜索,基本格式如下:

北京北:VAP

北京東:BOP

北京: BJP

北京南:VNP

北京西:BXP

實現的功能包括:
(1)自動打開Google瀏覽器,進入12306登錄頁面
(2)命令行手動輸入賬號、密碼、出發、目的地,時間等相關信息,登錄驗證圖片需要手動選擇。
(3)自動填充輸入,完成查詢和頁面跳轉。

後續可以優化的功能:
(1)從配置文件中讀取賬號、密碼、出發、目的地,時間等相關信息。


(2)從配置文件中獲取城市編碼
(3)登錄驗證圖片可以使用第三方識別自動選擇

二、初識Splinter

1.簡介

Splinter 是用 Python 開發的一個開源web自動化測試的工具集。 它可以幫你自動化瀏覽器的行為,比如瀏覽 URLs 並和頁面進行交互。

Splinter是現有瀏覽器之上抽象層自動化工具(如 Selenium, PhantomJS 和 zope.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自動查票