python之12306自動查票
一、導讀
本篇文章所采用的技術僅用於學習、研究,任何其他用途請自行承擔後果。
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自動查票