python爬蟲實(shí)現(xiàn)最新12306搶票
1.環(huán)境
python 3.7
谷歌瀏覽器
chromedriver.exe(瀏覽器驅(qū)動程序,要與瀏覽器版本對應(yīng),并將其添加到環(huán)境變量或放到當(dāng)前py文件所在目錄下)
2.相關(guān)模塊
time
(用于某些地方對程序的強(qiáng)制等待)datatime
(用于獲取當(dāng)前時間)selenium 3.1
自動化測試模塊,這里用于操作瀏覽器)
3.思路
首先進(jìn)行登錄(支持手機(jī)掃碼),登錄完成進(jìn)入頁面之后,我們會看到有“溫馨提示”的彈窗,即當(dāng)前界面,我們需要處理第一次彈窗,
處理完后就是信息的輸入,在這里日期的輸入不是輸入框,是鼠標(biāo)點(diǎn)擊,在代碼中已處理,輸入完成后,查詢列車信息(我寫的只能查詢動車以及火車的二等座),如果有票,則預(yù)約,然后進(jìn)入新的頁面
處理乘車人信息(由于本人是學(xué)生,此代碼也可搶學(xué)生票),最后提交訂單。
其實(shí)說明白了,就是通過代碼讓瀏覽器模擬人來操作瀏覽器,從而實(shí)現(xiàn)購票,要求要對selenium這個模塊掌握的熟練。不說了,直接上代碼,量有點(diǎn)大,各位道友一定要撐住哈。
import time import datetime from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class Qiangpiao(): ? ? def __init__(self,from_station,to_station,depart_time,train_num,passenger): ? ? ? ? self.login_url = 'https://kyfw.12306.cn/otn/resources/login.html' ? ? ? ? self.init_my_url = 'https://kyfw.12306.cn/otn/view/index.html' ? ? ? ? self.order_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc' ? ? ? ? # input("出發(fā)地:") ? ? ? ? self.from_station = from_station ? ? ? ? # input("目的地:") ? ? ? ? self.to_station = to_station ? ? ? ? # 時間格式必須是M-d的方式 ? ? ? ? # input("出發(fā)時間(格式必須是M-d的方式):") ? ? ? ? self.depart_time = depart_time ? ? ? ? # input("列車號:") ? ? ? ? self.train_num = train_num ? ? ? ? self.passenger = passenger ? ? ? ? #獲取當(dāng)前月份 ? ? ? ? self.now_month = datetime.date.today().month ? ? ? ? self.leave_month = int(self.depart_time.split('-')[0]) ? ? ? ? self.leave_day = int(self.depart_time.split('-')[1]) ? ? ? ? self.driver = webdriver.Chrome() ? ? def _login(self): ? ? ? ? self.driver.get(self.login_url) ? ? ? ? # 窗口最大化 ? ? ? ? #self.driver.maximize_window() ? ? ? ? # 設(shè)置窗口大小 ? ? ? ? self.driver.set_window_size(1300,800) ? ? ? ? #print('調(diào)整前尺寸:', self.driver.get_window_size()) ? ? ? ? #顯式等待 ? ? ? ? #這里進(jìn)行手動登錄,可以掃碼,也可以輸入賬號密碼點(diǎn)擊登錄 ? ? ? ? WebDriverWait(self.driver,1000).until(EC.url_to_be(self.init_my_url)) ? ? ? ? print('登錄成功!') ? ? def _pop_window(self): ? ? ? ? time.sleep(1) ? ? ? ? self.driver.find_element_by_xpath('//*[@class="dzp-confirm"]/div[2]/div[3]/a').click() ? ? def _enter_order_ticket(self): ? ? ? ? action = ActionChains(self.driver) ? # 實(shí)例化一個動作鏈對象 ? ? ? ? element = self.driver.find_element_by_link_text('車票') ? ? ? ? # 鼠標(biāo)移動到 '車票' 元素上的中心點(diǎn) ? ? ? ? action.move_to_element(element).perform() ? ? ? ? # 點(diǎn)擊'單程' ? ? ? ? self.driver.find_element_by_xpath('//*[@id="J-chepiao"]/div/div[1]/ul/li[1]/a').click() ? ? ? ? # 消除第二次彈窗 ? ? ? ? self.driver.find_element_by_link_text('確認(rèn)').click() ? ? def _search_ticket(self): ? ? ? ? #出發(fā)地輸入 ? ? ? ? self.driver.find_element_by_id("fromStationText").click() ? ? ? ? self.driver.find_element_by_id("fromStationText").send_keys(self.from_station) ? ? ? ? self.driver.find_element_by_id("fromStationText").send_keys(Keys.ENTER) ? ? ? ? #目的地輸入 ? ? ? ? self.driver.find_element_by_id("toStationText").click() ? ? ? ? self.driver.find_element_by_id("toStationText").send_keys(self.to_station) ? ? ? ? self.driver.find_element_by_id("toStationText").send_keys(Keys.ENTER) ? ? ? ? #出發(fā)日期輸入 ? ? ? ? self.driver.find_element_by_id("date_icon_1").click() ? ? ? ? if self.leave_month == self.now_month: ? ? ? ? ? ? xpath_str = f"/html/body/div[37]/div[1]/div[2]/div[{self.leave_day}]" ? ? ? ? ? ? if EC.element_to_be_clickable((By.XPATH, xpath_str)): ? ? ? ? ? ? ? ? self.driver.find_element_by_xpath(xpath_str).click() ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? print("當(dāng)前日期未到或已過售票日期,無法購票!") ? ? ? ? elif self.leave_month == self.now_month + 1: ? ? ? ? ? ? xpath_str = f"/html/body/div[37]/div[2]/div[2]/div[{self.leave_day}]" ? ? ? ? ? ? if EC.element_to_be_clickable((By.XPATH, xpath_str)): ? ? ? ? ? ? ? ? self.driver.find_element_by_xpath(xpath_str).click() ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? print("當(dāng)前日期未到或已過售票日期,無法購票!") ? ? ? ? else: ? ? ? ? ? ? print("月份超前一個月以上,無法購票!") ? ? ? ? #等待查詢按鈕是否可用 ? ? ? ? WebDriverWait(self.driver,1000).until(EC.element_to_be_clickable((By.ID,"query_ticket"))) ? ? ? ? #執(zhí)行點(diǎn)擊事件 ? ? ? ? search_btn = self.driver.find_element_by_id("query_ticket") ? ? ? ? search_btn.click() ? ? ? ? #等待查票信息加載 ? ? ? ? WebDriverWait(self.driver, 1000).until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr'))) ? ? def _order_ticket(self): ? ? ? ? train_num_list = [] ?# 列車號列表 ? ? ? ? train_num_ele_list = self.driver.find_elements_by_xpath('//tr/td[1]/div/div[1]/div/a') ?# 列車號元素列表 ? ? ? ? for t in train_num_ele_list: ? ?# 遍歷列車號元素列表,并把列車號添加到列車號列表 ? ? ? ? ? ? train_num_list.append(t.text) ? ? ? ? tr_list = self.driver.find_elements_by_xpath('//*[@id="queryLeftTable"]/tr[not(@datatran)]') ?#每一列列車整行信息列表,列車號元素是tr的子元素 ? ? ? ? if self.train_num in train_num_list: ? ? ? ? ? ? for tr in tr_list: ? ? ? ? ? ? ? ? train_num = tr.find_element_by_xpath("./td[1]/div/div[1]/div/a").text ?#取出元素tr里的列車號 ? ? ? ? ? ? ? ? if self.train_num == train_num: ? ? ? ? ? ? ? ? ? ? #動車二等座余票信息 ? ? ? ? ? ? ? ? ? ? text_1 = tr.find_element_by_xpath("./td[4]").text ? ? ? ? ? ? ? ? ? ? # 火車二等座余票信息 ? ? ? ? ? ? ? ? ? ? text_2 = tr.find_element_by_xpath("./td[8]").text ? ? ? ? ? ? ? ? ? ? if (text_1 == "有" or text_1.isdigit()) or (text_2 == "有" or text_2.isdigit()): ? ? ? ? ? ? ? ? ? ? ? ? #點(diǎn)擊預(yù)訂按鈕 ? ? ? ? ? ? ? ? ? ? ? ? order_btn = tr.find_element_by_class_name("btn72") ? ? ? ? ? ? ? ? ? ? ? ? order_btn.click() ? ? ? ? ? ? ? ? ? ? ? ? #等待訂票頁面 ? ? ? ? ? ? ? ? ? ? ? ? WebDriverWait(self.driver,1000).until(EC.url_to_be(self.order_url)) ? ? ? ? ? ? ? ? ? ? ? ? # 選定乘車人 ? ? ? ? ? ? ? ? ? ? ? ? self.driver.find_element_by_xpath(f'//*[@id="normal_passenger_id"]/li/label[contains(text(),"{self.passenger}")]').click() ? ? ? ? ? ? ? ? ? ? ? ? #如果乘客是學(xué)生,對提示點(diǎn)擊確定 ? ? ? ? ? ? ? ? ? ? ? ? if EC.presence_of_element_located((By.XPATH, '//div[@id="dialog_xsertcj"]')): ? ? ? ? ? ? ? ? ? ? ? ? ? ? self.driver.find_element_by_id('dialog_xsertcj_ok').click() ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 提交訂單 ? ? ? ? ? ? ? ? ? ? ? ? ? ? self.driver.find_element_by_id('submitOrder_id').click() ? ? ? ? ? ? ? ? ? ? ? ? ? ? time.sleep(2) ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 點(diǎn)擊確認(rèn)訂單 ? ? ? ? ? ? ? ? ? ? ? ? ? ? self.driver.find_element_by_id('qr_submit_id').click() ? ? ? ? ? ? ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 提交訂單 ? ? ? ? ? ? ? ? ? ? ? ? ? ? self.driver.find_element_by_id('submitOrder_id').click() ? ? ? ? ? ? ? ? ? ? ? ? ? ? time.sleep(2) ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 點(diǎn)擊確認(rèn) ? ? ? ? ? ? ? ? ? ? ? ? ? ? self.driver.find_element_by_id('qr_submit_id').click() ? ? ? ? ? ? ? ? ? ? ? ? ? ? print("購票成功!") ? ? ? ? ? ? ? ? ? ? ? ? ? ? break ? ? ? ? ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? ? ? ? ? print("二等座無票!") ? ? ? ? else: ? ? ? ? ? ? print("無此列車!") ? ? def run(self): ? ? ? ? #登錄 ? ? ? ? self._login() ? ? ? ? #消除登錄后(第一次)的彈窗 ? ? ? ? self._pop_window() ? ? ? ? #進(jìn)入購票頁面 ? ? ? ? self._enter_order_ticket() ? ? ? ? #查票 ? ? ? ? self._search_ticket() ? ? ? ? #訂票 ? ? ? ? self._order_ticket() ? ? ? ? #關(guān)閉瀏覽器 ? ? ? ? time.sleep(6) ? ? ? ? self.driver.quit() if __name__ == '__main__': ? ? qiangpiao = Qiangpiao("蘭州","烏魯木齊","8-6","D55","小紅") ? ? qiangpiao.run()
4.結(jié)語
看到這里你們有么有崩潰,哈哈哈,事實(shí)上作為一名計(jì)算機(jī)系的大學(xué)生,我們一定要腳踏實(shí)地,多實(shí)踐多敲代碼,切記,在學(xué)習(xí)過程中一定要自己動手敲,這個世界運(yùn)行的底層邏輯不是白piao,是價(jià)值捆綁,作為程序員要多思考思考底層邏輯,形成閉環(huán)思維。
同時你們是否有疑惑,這程序運(yùn)行一次怎么搶票,事實(shí)上代碼運(yùn)行是比手操作快的,而且,你完全可以設(shè)置一個for循環(huán),然后設(shè)置一個時間(time)間隔,讓其每隔一段時間運(yùn)行一次,直到搶票成功時停止,讓其運(yùn)行個幾天,這樣票剛一發(fā)售,程序會立馬搶到,從而實(shí)現(xiàn)真正意義上的搶票,同時,還有許多內(nèi)容可以完善,比如座位種類,乘客多選,以及做模擬登錄然后隱藏瀏覽器(無頭瀏覽器了解一下)等等,有興趣的可以試試哦!
到此這篇關(guān)于python爬蟲實(shí)現(xiàn)最新12306搶票的文章就介紹到這了,更多相關(guān)python爬蟲實(shí)現(xiàn)12306搶票 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 教你用Python來制作一個自動搶票的腳本小程序
- 基于Python實(shí)現(xiàn)火車票搶票軟件
- 一款開源的Python一鍵搶票神器詳細(xì)配置
- Python自動化xpath實(shí)現(xiàn)自動搶票搶貨
- Python爬蟲 12306搶票開源代碼過程詳解
- python并發(fā)編程多進(jìn)程 模擬搶票實(shí)現(xiàn)過程
- Python實(shí)現(xiàn)12306火車票搶票系統(tǒng)
- python+splinter自動刷新?lián)屍惫δ?/a>
- python+Splinter實(shí)現(xiàn)12306搶票功能
- 一百多行python代碼實(shí)現(xiàn)搶票助手
- Python編寫一個多線程的12306搶票程序的示例
相關(guān)文章
Python數(shù)據(jù)結(jié)構(gòu)與算法之鏈表定義與用法實(shí)例詳解【單鏈表、循環(huán)鏈表】
這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)與算法之鏈表定義與用法,結(jié)合具體實(shí)例形式較為詳細(xì)的分析了單鏈表、循環(huán)鏈表等的定義、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-09-09python 2.7 檢測一個網(wǎng)頁是否能正常訪問的方法
今天小編就為大家分享一篇python 2.7 檢測一個網(wǎng)頁是否能正常訪問的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12Python標(biāo)準(zhǔn)庫之time庫的使用教程詳解
這篇文章主要介紹了Python的time庫的使用教程,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)python基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下2022-04-04Python人工智能深度學(xué)習(xí)模型訓(xùn)練經(jīng)驗(yàn)總結(jié)
這篇文章主要為大家介紹了Python人工智能深度學(xué)習(xí)模型訓(xùn)練的經(jīng)驗(yàn)總結(jié)及建議,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11Python把excel文件數(shù)據(jù)轉(zhuǎn)化為字典格式存儲詳解
這篇文章主要介紹了Python把excel文件數(shù)據(jù)轉(zhuǎn)化為字典格式存儲詳解,在Python中有時候需要操作excel表格的數(shù)據(jù),把excel表格轉(zhuǎn)化為字典存起來,方便讀取,今天我們就來看看如何轉(zhuǎn)換,需要的朋友可以參考下2023-08-08python實(shí)現(xiàn)的用于搜索文件并進(jìn)行內(nèi)容替換的類實(shí)例
這篇文章主要介紹了python實(shí)現(xiàn)的用于搜索文件并進(jìn)行內(nèi)容替換的類,涉及Python針對文件及字符串的相關(guān)操作技巧,需要的朋友可以參考下2015-06-06python 自動識別并連接串口的實(shí)現(xiàn)
這篇文章主要介紹了python 自動識別并連接串口的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01