Python + selenium + requests實(shí)現(xiàn)12306全自動(dòng)搶票及驗(yàn)證碼破解加自動(dòng)點(diǎn)擊功能
測試結(jié)果:
整個(gè)買票流程可以再快一點(diǎn),不過為了穩(wěn)定起見,有些地方等待了一些時(shí)間
完整程序,拿去可用
整個(gè)程序分了三個(gè)模塊:購票模塊(主體)、驗(yàn)證碼識(shí)別模塊、余票查詢模塊
購票模塊:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException, ElementNotVisibleException import time import requests from urllib.parse import urlencode from pyquery import PyQuery as pq from check_ticket import Check from verify import Code import json class Buy_Ticket(): def __init__(self, start_station, end_station, date, username, password, purpose): self.num = 1 self.start = start_station self.end = end_station self.date = date self.username = username self.password = password self.purpose = purpose self.login_url = 'https://kyfw.12306.cn/otn/login/init' self.ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init' def login(self): browser.get(self.login_url) try: input_name = browser.find_element_by_id('username') input_pd = browser.find_element_by_id('password') button = browser.find_element_by_id('loginSub') time.sleep(1) input_name.send_keys(self.username) input_pd.send_keys(self.password) c = Code(browser) #調(diào)用驗(yàn)證碼識(shí)別模塊 c.main() button.click() time.sleep(2) #等待頁面跳轉(zhuǎn),如果驗(yàn)證碼識(shí)別錯(cuò)誤,就執(zhí)行下面的while語句 while browser.current_url == self.login_url + '#': c = Code(browser) c.main() button.click() time.sleep(2) #self.get_passenger() self.check() except NoSuchElementException: self.login() def check(self): #調(diào)用余票查詢模塊 check = Check(self.date, self.start, self.end, self.purpose) start_end = check.look_up_station() self.num = check.get_info() #cookie的添加,json.dumps把以漢字形式呈現(xiàn)的起始、終點(diǎn)站轉(zhuǎn)化成unicode編碼,可在審查元素里查看cookie browser.add_cookie({'name':'_jc_save_fromStation', 'value':json.dumps(self.start).strip('"').replace('\\', '%') + '%2C' + start_end[0]}) browser.add_cookie({'name':'_jc_save_toStation', 'value':json.dumps(self.end).strip('"').replace('\\', '%') + '%2C' + start_end[1]}) browser.add_cookie({'name':'_jc_save_fromDate', 'value':self.date}) browser.get(self.ticket_url) if self.purpose == '學(xué)生': btn = browser.find_element_by_id('sf2') time.sleep(1) btn.click() button = browser.find_element_by_id('query_ticket') time.sleep(1) button.click() def book_ticket(self): print('開始預(yù)訂車票...') #先查找出所有車次對應(yīng)的預(yù)訂按鈕,再根據(jù)余票查詢模塊返回的車次序號(hào),點(diǎn)擊相應(yīng)的預(yù)訂按鈕 button = browser.find_elements_by_class_name('btn72') button[self.num-1].click() time.sleep(3) button2 = browser.find_element_by_id('normalPassenger_0') #按實(shí)際情況,可自行修改,這里就選擇的第一個(gè)常用聯(lián)系人, #第二個(gè)是normalPassenger_1,依此類推 button2.click() button3 = browser.find_element_by_id('submitOrder_id') time.sleep(1) button3.click() time.sleep(3) #等待頁面加載完畢,不然后面可能會(huì)報(bào)錯(cuò),等待時(shí)間自行決定 try: button4 = browser.find_element_by_id('qr_submit_id') button4.click() except ElementNotVisibleException: button4 = browser.find_element_by_id('qr_submit_id') button4.click() print('車票預(yù)定成功!請?jiān)?0分鐘內(nèi)完成付款!') def main(self): self.login() self.book_ticket() if __name__ == '__main__': begin = time.time() browser = webdriver.Chrome() b = Buy_Ticket('上海', '重慶', '2018-09-18', '賬號(hào)', '密碼', 'ADULT') #賬號(hào)、密碼自行修改 b.main() end = time.time() print('總耗時(shí):%d秒' % int(end-begin)) #browser.close()
驗(yàn)證碼識(shí)別模塊:
import requests from PIL import Image from selenium.webdriver import ActionChains import time from io import BytesIO class Code(): def __init__(self, browser): self.browser = browser self.verify_url = 'http://littlebigluo.qicp.net:47720/' #驗(yàn)證碼識(shí)別網(wǎng)址,返回識(shí)別結(jié)果 #確定驗(yàn)證碼的位置 def get_position(self): time.sleep(3) element = self.browser.find_element_by_class_name('touclick-img-par') time.sleep(2) location = element.location size = element.size position= (location['x'], location['y'], location['x'] + size['width'], location['y'] + size['height']) return position #截取整個(gè)網(wǎng)頁頁面 def get_screenshot(self): screenshot = self.browser.get_screenshot_as_png() screenshot = Image.open(BytesIO(screenshot)) return screenshot #從截取的網(wǎng)頁,裁剪出驗(yàn)證碼圖片,并保存到本地 def get_touclick_img(self, name = 'captcha.png'): position = self.get_position() print('驗(yàn)證碼的位置:', position) screenshot = self.get_screenshot() captcha = screenshot.crop(position) captcha.save('captcha.png') #驗(yàn)證碼解析 def parse_img(self): files = {'file': open('captcha.png', 'rb')} #打開保存到本地的驗(yàn)證碼圖片 response = requests.post(self.verify_url, files=files) num = response.text.split('<B>')[1].split('<')[0] print('驗(yàn)證碼識(shí)別成功!圖片位置:%s' % num) try: if int(num): return [int(num)] except ValueError: num = list(map(int,num.split())) return num #識(shí)別結(jié)果num都以列表形式返回,方便后續(xù)驗(yàn)證碼的點(diǎn)擊 #實(shí)現(xiàn)驗(yàn)證碼自動(dòng)點(diǎn)擊 def move(self): num = self.parse_img() try: element = self.browser.find_element_by_class_name('touclick-img-par') for i in num: if i <= 4: ActionChains(self.browser).move_to_element_with_offset(element,40+72*(i-1),73).click().perform() else : i -= 4 ActionChains(self.browser).move_to_element_with_offset(element,40+72*(i-1),145).click().perform() except: print('元素不可選!') def main(self): self.get_touclick_img() self.move()
余票查詢模塊:
import requests from urllib.parse import urlencode class Check(): def __init__(self, date, start, end, purpose): self.base_url = 'https://kyfw.12306.cn/otn/leftTicket/queryA?' self.url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9018' self.date = date self.start_station = start self.end_station = end if purpose == '學(xué)生': self.purpose = '0X00' else: self.purpose = purpose #查找出車站的英文簡稱,用于構(gòu)造cookie、完整的余票查詢鏈接 def look_up_station(self): response1 = requests.get(self.url) a = response1.text.split('@') a.pop(0) for each in a: i = each.split('|') if self.start_station == i[1]: self.start_station = i[2] elif self.end_station == i[1]: self.end_station = i[2] return [self.start_station, self.end_station] def get_info(self): start_end = self.look_up_station() #構(gòu)造請求參數(shù) data = { 'leftTicketDTO.train_date':self.date, 'leftTicketDTO.from_station':start_end[0], 'leftTicketDTO.to_station':start_end[1], 'purpose_codes':self.purpose } url = self.base_url + urlencode(data) response = requests.get(url) json = response.json() maps = json['data']['map'] count = 0 #用于對車次編號(hào) for each in json['data']['result']: count += 1 s = each.split('|')[3:] info = { 'train':s[0], 'start_end':maps[s[3]] + '-' + maps[s[4]], 'time':s[5] + '-' + s[6], '歷時(shí)':s[7], '一等座':s[-5], '二等座':s[-6] } try: #余票的結(jié)果有3種:有、一個(gè)具體的數(shù)字(如:18、6等)、無,判斷如果余票是有或者一個(gè)具體的數(shù)字就直接輸出對應(yīng)的車次信息,然后返回 if info['二等座'] == '有' or int(info['二等座']): print('[%d]' % count, info) return count except ValueError: continue
總結(jié)
以上所述是小編給大家介紹的Python + selenium + requests實(shí)現(xiàn)12306全自動(dòng)搶票及驗(yàn)證碼破解加自動(dòng)點(diǎn)擊功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- Python +Selenium解決圖片驗(yàn)證碼登錄或注冊問題(推薦)
- Selenium+Python 自動(dòng)化操控登錄界面實(shí)例(有簡單驗(yàn)證碼圖片校驗(yàn))
- selenium+python實(shí)現(xiàn)1688網(wǎng)站驗(yàn)證碼圖片的截取功能
- Python使用selenium實(shí)現(xiàn)網(wǎng)頁用戶名 密碼 驗(yàn)證碼自動(dòng)登錄功能
- Python Selenium Cookie 繞過驗(yàn)證碼實(shí)現(xiàn)登錄示例代碼
- python+selenium識(shí)別驗(yàn)證碼并登錄的示例代碼
- 使用 Python 和 Selenium 解決 Cloudflare 驗(yàn)證碼的問題
相關(guān)文章
Python中enumerate()函數(shù)編寫更Pythonic的循環(huán)
本篇文章主要大家通過實(shí)例講述了Python中enumerate()函數(shù)編寫更Pythonic的循環(huán)的知識(shí)點(diǎn),有興趣的朋友參考學(xué)習(xí)下。2018-03-03python實(shí)現(xiàn)修改固定模式的字符串內(nèi)容操作示例
這篇文章主要介紹了python實(shí)現(xiàn)修改固定模式的字符串內(nèi)容操作,結(jié)合實(shí)例形式詳細(xì)分析了Python修改固定模式字符串原理、實(shí)現(xiàn)方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-12-12JSONLINT:python的json數(shù)據(jù)驗(yàn)證庫實(shí)例解析
本文介紹的 jsonlint 啟發(fā)自 python 的表單驗(yàn)證工具 wtforms,wtforms 通過繼承 Form 類也能進(jìn)行 json 數(shù)據(jù)驗(yàn)證,下面通過一些例子給大家詳細(xì)介紹,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-11-11