#!/usr/bin/env python2.7 12306查票腳本 有基本的餘票查詢,監控功能,暫無訂票功能 # -*- coding: utf-8 -*- """ author='Mr RaoJL', author_email='[email protected]', description=' Train ticket inquiry Script' aothor Date='Wed Jan 11 17:42:14 2017' """ import urllib2 import ssl import json import sys import re import time import smtplib # from City_code import City_Code from email.mime.text import MIMEText email_FROM_city='' email_TO_city='' email_DATE_city='' DESC_title = """ __ __ ____ _ _ | \/ |_ __ | _ \ __ _ ___ | | | | |\/| | '__| | |_) / _` |/ _ \ _ | | | | | | | | | _ < (_| | (_) | |_| | |___ |_| |_|_| |_| \_\__,_|\___/ \___/|_____| """ HELPR=""" 1 查詢 2 將查詢的信息發送郵件 Q 查詢可用站點 用法: 1> Q [站點名] 2> Q ALL 列出全部(較長) F 監控餘票 使用: F [出發地] [目的地] [日期,標準格式:xxxx-xx-xx] [座位類型,如:硬座] [列車編號,如:K935] [查詢次數,默認爲1次] exit 退出程序 """ send_head = { "Host": "kyfw.12306.cn", "User-Agent": 'Mozilla / 5.0(X11;Fedora;Linux x86_64;rv:50.0) Gecko / 20100101Firefox / 50.0', "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 'Connection': 'keep-alive' } City_Code = {} reload(sys) sys.setdefaultencoding('utf-8') ssl._create_default_https_context = ssl._create_unverified_context Faile = 0 def HTTP_query(trainDate, From_city, To_city): try: try: bagful = "https://kyfw.12306.cn/otn/leftTicket/queryA?" \ "leftTicketDTO.train_date={0}&" \ "leftTicketDTO.from_station={1}&" \ "leftTicketDTO.to_station={2}" \ "&purpose_codes=ADULT" \ "".format(trainDate, City_Code[From_city], City_Code[To_city]) req = urllib2.Request(bagful, headers=send_head) except KeyError: print "無法找到的站點" return False except NameError: print "無法找到輸入的站點" return False global GET_INFO GET_INFO = urllib2.urlopen(req).read() return True except urllib2.HTTPError as alter: print "錯誤: [%s]!"% alter pass def Get_City_code(): print "讀取站點數據庫..." try: Ci_url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8994' Ci_text = urllib2.urlopen(Ci_url).read() Ci_text = Ci_text.replace('\'', '').replace('var station_names =\'', '') city = re.findall('\|\W+\|[A-Z]{3}', Ci_text) for i in city: City_Code[re.split('\|', i)[1]] = re.split('\|', i)[2] print "讀取成功!\n輸入h或help獲取幫助" except urllib2.URLError as erron: print "錯誤:%s無法讀取站點數據,請檢查網絡後重試!"%erron sys.exit() def Get_Data(trainDate, From_city, To_city): global info json._default_encoder = 'UTF-8' try: data = json.loads(GET_INFO, encoding='UTF-8') except NameError: print "無法找到輸入的站點" return False tables = [] info = [] try: for i in data['data']: tables.append(i) if True: for j in tables: info.append(j['queryLeftNewDTO']) except KeyError: print "\033[31m未查詢到數據\033[0m" pass return Faile List_Data(From_city, To_city, trainDate) def Filter_Data(From, To, Date, zw_type, tr_Num): HTTP_query(Date, From, To) F_info = [] F_table = [] json._default_encoder = 'uft-8' try: assert isinstance(GET_INFO, object) data = json.loads(GET_INFO, encoding='UTF-8') except NameError: print "無法找到輸入的站點" return False try: for i in data['data']: F_table.append(i) if True: for j in F_table: F_info.append(j['queryLeftNewDTO']) except KeyError: print "\033[31m未查詢到數據\033[0m" try: exchange_name(zw_type) for i in F_info: if i['station_train_code'] == tr_Num and (i[zw_type] == '有' or re.search('\d+', i[zw_type])): print '從{0}到{1},日期爲{2},列車 {3} {4}:{7}{5}{8} 出發時間:{7}{6}{8} '.format(From, To, Date, i['station_train_code'], ZW_NAME, i[zw_type], i['start_time'], StartColor, EndColor) except KeyError: print "輸入錯誤" return False def exchange_name(self): global ZW_NAME ZW_NAME='' if self == 'yz_num': ZW_NAME = '硬座' if self == 'rw_num': ZW_NAME = '軟我' if self == 'yw_num': ZW_NAME = '硬臥' if self == 'wz_num': ZW_NAME = '無座' else: print "" return False def List_Data(From_city, To_city, trainDate): if True: seq = 0 print "查詢結果:" global StartColor global EndColor StartColor = '\033[32m' EndColor = '\033[0m' try: from prettytable import PrettyTable List_train = PrettyTable(['序列', '列車類型', '出發時間', '到達時間', '歷時', '硬座', '硬臥', '軟臥', '無座', '起始站','終點站','列車狀態']) for z in info: seq += 1 if re.search('K', z['station_train_code']): liche_code = "快速 " elif re.search('G', z['station_train_code']): liche_code = "高鐵 " elif re.search('Z', z['station_train_code']): liche_code = "直達 " elif re.search('T', z['station_train_code']): liche_code = "特快 " elif re.search('D', z['station_train_code']): liche_code = "動車組 " elif re.search('Y', z['station_train_code']): liche_code = "旅行專列 " elif re.search('C', z['station_train_code']): liche_code = "城際 " elif re.search('\d+', z['station_train_code']): liche_code = '普通 ' else: liche_code = "" List_train.add_row( [StartColor + str(seq) + EndColor, StartColor + liche_code + z['station_train_code'] + EndColor, StartColor + z['start_time'] + EndColor, StartColor + z['arrive_time'] + EndColor, StartColor + z['lishi'] + EndColor, StartColor + z['yz_num'] + EndColor, StartColor + z['yw_num'] + EndColor, StartColor + z['rw_num'] + EndColor, StartColor + z['wz_num'] + EndColor, StartColor + z['start_station_name'] + EndColor, StartColor+z['end_station_name']+EndColor, StartColor + z['controlled_train_message'] + EndColor]) print List_train print "查詢完成,從 {2} 到 {3},日期爲{1}的列車,共{0}條記錄.".format(len(info), trainDate, From_city, To_city, trainDate) return True except ImportError: for z in info: seq += 1 if re.search('K', z['station_train_code']): liche_code = "快速 " elif re.search('G', z['station_train_code']): liche_code = "高鐵 " elif re.search('Z', z['station_train_code']): liche_code = "直達 " elif re.search('T', z['station_train_code']): liche_code = "特快 " elif re.search('D', z['station_train_code']): liche_code = "動車組 " elif re.search('Y', z['station_train_code']): liche_code = "旅行專列 " elif re.search('C', z['station_train_code']): liche_code = "城際 " elif re.search('\d+', z['station_train_code']): liche_code = '普通 ' else: liche_code = "" print "-" * 140 print "{5}\t{4}:\033[32m{0}\033[0m\t出發時間:\033[32m{1}\033[0m\t到達時間:\033[32m{2}\033[0m\t歷時:\033[32m{3}\033[0m\t" \ .format(z['station_train_code'], z['start_time'], z['arrive_time'], z['lishi'], liche_code, seq), print '硬座:\033[32m{0}\033[0m\t硬臥:\033[32m{2}\033[0m\t軟臥:\033[32m{3}\033[0m\t\033[0m無座:\033[32m{4}\033[0m\t列車狀態:\033[32m{1}\033[0m' \ .format(z['yz_num'], z['controlled_train_message'], z['yw_num'], z['rw_num'], z['wz_num']) print "查詢完成,從 {2} 到 {3},日期爲{1}的列車,共{0}條記錄.".format(len(info), trainDate, From_city, To_city, trainDate) def Get_Input(): """global From_city global To_city global trainDate """ print "\033[32m-->>\033[0m進入12306查票控制檯" From_city = raw_input("請輸入出發城市(中文): ") To_city = raw_input("請輸入目的城市(中文): ") trainDate = raw_input("請輸入乘車日期(如:{0})默認即回車爲今日: ".format(time.strftime('%Y-%m-%d'))) if trainDate == '': trainDate = time.strftime('%Y-%m-%d') print "請稍等,正在查詢從{0}到{1}日期:{2}的列車......".format(From_city, To_city, trainDate) else: CheckDate = re.search('[0-9]{4}.[0-9]{2}.[0-9]{2}', trainDate) if CheckDate: print "請稍等,正在查詢從{0}到{1},日期:{2}的列車......".format(From_city, To_city, trainDate) else: print "日期格式錯誤!請重試!" return False email_DATE_city = trainDate email_FROM_city = From_city email_TO_city = To_city HTTP_query(trainDate, From_city, To_city) Get_Data(trainDate, From_city, To_city) def Check_Input(): if True: print "12306查票腳本(收錄全國{0}個站點,作者Mr RaoJL".format(City_Code.__len__()) print DESC_title if True: while True: snedmail = raw_input("控制檯 >>> ") if snedmail == '2': print "發送郵件..." Get_Msg(email_FROM_city, email_TO_city, email_DATE_city) if True: print "發送成功" continue else: print "發送失敗" continue elif snedmail == '1': Get_Input() if False: print "查詢失敗" continue elif re.findall('Q \S+', snedmail): search_wd = re.findall('Q \S+', snedmail)[0] search_wd = search_wd.split(' ')[1] for key in City_Code: if search_wd in key: print '\t' + key elif search_wd == 'ALL': print '\t' + key else: pass if False: print "無法找到你輸入的站點" elif re.findall('F \S+', snedmail): if len(snedmail.split(' ')) < 6: print "請輸入完整信息!" else: In_info = snedmail.split(' ') s_city = In_info[1] e_city = In_info[2] s_date = In_info[3] zw_type = '' if In_info[4] == '硬座': zw_type = 'yz_num' elif In_info[4] == '硬臥': zw_type = 'rw_num' elif In_info[4] == '無座': zw_type = 'wz_num' elif In_info[4] == '軟臥': zw_type = 'rw_num' else: print "參數錯誤" continue train_num = In_info[5] i=0 cish = 1 try: if In_info.__len__() == 7 and re.search('\d+',In_info[6]): cish = int(In_info[6]) try: while i < cish: i += 1 print "第%s次查詢" % i Filter_Data(s_city, e_city, s_date, zw_type, train_num) except NameError: print "請先查詢" continue else: Filter_Data(s_city, e_city, s_date, zw_type, train_num) except IndexError as esa: Filter_Data(s_city, e_city, s_date, zw_type, train_num) elif snedmail == '': continue elif snedmail == 'h' or snedmail == 'help': print HELPR elif snedmail == 'exit': print "退出程序!" break else: print "輸入 h 或者 help 獲取幫助" continue else: print "" sys.exit() def Send_Mail(content): mail = smtplib.SMTP('smtp.sina.com.cn') mail_addr = '[email protected]' mail_pass = 'xxxxxxx' mail.login(mail_addr, mail_pass) To = mail_addr msg = MIMEText(content, _subtype='html', _charset='utf-8') msg['Subject'] = "12306 Inspection results TIME:{0}".format(time.ctime()) msg['From'] = mail_addr msg['To'] = To mail.sendmail(mail_addr, To, msg.as_string()) def Get_Msg(From_city, To_city, trainDate): TdSty = "style='color:#fff;width:100px;text-align:center'" TdstyT = "style='text-align:center'" content = "<center><table><tr bgcolor='#333'><td {0}>列車類別</td><td {0}>出發時間</td>" \ "<td {0}>到達時間</td>" \ "<td {0}>歷時</td>" \ "<td {0}>硬座</td>" \ "<td {0}>硬臥</td>" \ "<td {0}>軟臥</td>" \ "<td {0}>無座</td>" \ "<td {0}>列車狀態</td></tr>".format(TdSty) seq = 0 for i in info: seq += 1 if re.search('K', i['station_train_code']): liche_code = "快速" elif re.search('G', i['station_train_code']): liche_code = "高鐵" elif re.search('Z', i['station_train_code']): liche_code = "直達" elif re.search('T', i['station_train_code']): liche_code = "特快" elif re.search('D', i['station_train_code']): liche_code = "動車組" elif re.search('Y', i['station_train_code']): liche_code = "旅行專列" else: liche_code = "列車編號" content += \ "<tr style='color:blue'><td>{0}</td>" \ "<td {9}>{1}</td>" \ "<td {9}>{2}</td>" \ "<td {9}>{3}</td>" \ "<td {9}>{4}</td>" \ "<td {9}>{5}</td>" \ "<td {9}>{6}</td>" \ "<td {9}>{7}</td>" \ "<td {9}>{8}</td></tr>" \ .format(liche_code + i['station_train_code'], i['start_time'], i['arrive_time'], i['lishi'], i['yz_num'], i['yw_num'], i['rw_num'], i['wz_num'], i['controlled_train_message'], TdstyT) content += "</table></center><h1 style='color:red'> {0} => {1} Time: {2}; Total: {3}; QueryTime: {4}".format( From_city, To_city, trainDate, seq, time.strftime('%F %H:%M:%S')) try: Send_Mail(content) return True except smtplib.SMTPAuthenticationError as e: print "驗證失敗", e return False try: Get_City_code() Check_Input() except KeyboardInterrupt: print "\n\033[31m程序終止,已退出!\033[0m"
Python爬蟲之:12306查票
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.