利用python監控去哪兒網機票價格
阿新 • • 發佈:2019-01-03
# -*- coding: utf-8 -*- import xml.etree.ElementTree as etree import requests import time from lxml import etree from email.mime.text import MIMEText import smtplib def ShowDict(d): print('=================') for v in d: print(v, '->', d[v]) def TripDict(d): for v in d: d[v] = d[v].strip() # 從網上抓取票價資料,去哪兒網已經整理好放到一個xml檔案,直接解析就可以了 def GetPlaneTicketPrice(FromAddr, ToAddr): requrl = 'http://ws.qunar.com/holidayService.jcp?lane=%s-%s' % (FromAddr, ToAddr) user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36" headers = {"User-Agent": user_agent} request = requests.get(requrl, headers=headers) response = request.text.encode(encoding="utf-8") tree = etree.fromstring(response) # print(tree) # root = tree.getroot() root = tree.getiterator() print(type(root)) all_info = [] for node in root: cur_info = {} try: na = node.attrib cur_info = dict(na.items()) #print na["date"],na['go_avc'],na['go_start'],na['go_expires'] for child in node: ca = child.attrib item_1 = dict(cur_info.items() + ca.items()) # print(item_1) item_1['from_addr'] = FromAddr item_1['to_addr'] = ToAddr item_2 = {} for i in item_1: item_2[i.encode('utf-8')] = item_1[i] .encode('utf-8') all_info.append(item_2) #ShowDict(item_1) except: pass return all_info #時間轉換函式 def GetCurrentDate(): return time.strftime("%Y-%m-%d", time.localtime()) def GetTimeSruFromDateStr(date_str) : return time.strptime(date_str, "%Y-%m-%d") def GetDateStrFromTimeSru(ti): return "%04d-%02d-%02d" % (ti.tm_year, ti.tm_mon, ti.tm_mday) def GetTimeSruFromDateTimeStr(date_str): return time.strptime(date_str, "%Y-%m-%d %H:%M:%S") def GetDateTimeStrFromTimeSru (ti): return "%04d-%02d-%02d %02d:%02d:%02d" % (ti.tm_year, ti.tm_mon,ti.tm_mday , ti.tm_hour, ti.tm_min, ti.tm_sec ) #帥選需要的欄位資料和航班型別,按折扣排序 def GetTripByPrice(tp_info, trip_type='go', date_beg=None, date_end=None) : if not date_beg: date_beg = GetCurrentDate() if not date_end: date_end = date_beg tp = trip_type #過濾出需要的型別和資料型別轉換 trip_info = [] for v in tp_info: if v['type'] != trip_type: continue nv = {} nv['date'] = GetTimeSruFromDateStr(v['date']) nv['avc'] = v[tp + '_avc'] nv['price'] = int(v['price']) nv['from_addr'] = v['from_addr'] nv['to_addr'] = v['to_addr'] #time.strptime(date_str, "%Y-%m-%d") ds = v['date'] + ' ' + v[tp + '_start'] + ":00" nv['start_time'] = GetTimeSruFromDateTimeStr(ds) de = v['date'] + ' ' + v[tp + '_expires'] + ":00" nv['expires_time'] = GetTimeSruFromDateTimeStr(de) dis = v['discount'] fDis = None for i in dis: if i.isdigit(): fDis = float(''.join([ s for s in dis if (s.isdigit() or s == '.')])) break if fDis== None: cc = {"全價": 10.0, "半價": 5.0, "免費": 0.0} fDis = cc[dis] nv['discount'] = fDis nv['name'] = v['name'] trip_info.append(nv) #日期過濾 date_beg_t = GetTimeSruFromDateStr(date_beg) date_end_t = GetTimeSruFromDateStr(date_end) trip_info = [v for v in trip_info if date_beg_t <= v['start_time'] <= date_end_t] #按價格排序 sorted_tp = sorted(trip_info, key = lambda k: k['discount']) return sorted_tp #根據航班列表生成網頁原始碼 def MakeHtmlPage (TripList) : html_h = '''<html> <body> <center> <h4>【低價機票助手】#title#</h4> <table border="1" cellspacing="0" cellpadding="0" width="600" style="BORDER-COLLAPSE: collapse"> <tr> <th>航班</th> <th>出發時間</th> <th>抵達時間</th> <th>折扣</th> <th>價格</th> </tr>''' html_t = ''' </table> </center> </body> </html> ''' if not TripList: print('null trip found') return data_tr = '' from_addr = TripList[0]['from_addr' ] to_addr = TripList[0]['to_addr' ] title = '發現【%s->%s】低價機票,請注意哦!' % (from_addr, to_addr) html_h = html_h.replace('#title#', title) for v in TripList: cr = ' <tr>\r\n' ts = GetDateTimeStrFromTimeSru(v['start_time']) te = GetDateTimeStrFromTimeSru(v['expires_time']) dis = '%.1f折' % (v['discount']) price = '%d元' % (v['price']) cr = ' <tr>\r\n' cr += ' <th>%s</th>\r\n' % (v['avc']) cr += ' <th>%s</th>\r\n' % ts cr += ' <th>%s</th>\r\n' % te cr += ' <th>%s</th>\r\n' % dis cr += ' <th>%s</th>\r\n' % price cr += ' </tr>\r\n' data_tr += cr html = html_h + data_tr + html_t return html #判斷郵件內容是否可以傳送,統一郵件內容30分內只允許傳送一次 his_msg = [] def CanSend (msg) : tNow = time.time() MinTime = 30 * 60 bSend = True for i, m in enumerate(his_msg): if (msg == m[0]) and (tNow - m[1] < MinTime): bSend = False if tNow - m[1] > MinTime: del his_msg[i] if bSend: his_msg.append([msg, tNow]) return bSend #根據航班列表生成文字資訊 def MakeEmailMsg (TripList) : if not TripList: print('null trip found') return msg = '' from_addr = TripList[ 0]['from_addr' ] to_addr = TripList[ 0]['to_addr' ] msg += '發現【%s->%s】低價機票,請注意哦~~\r\n' % (from_addr, to_addr) msg += '=' * 60 + "\r\n" msg += '%s\t%s\t%s\t%s\t%s\r\n' % ('航班'.center(32), '出發日期'.center(32),'航班時間' .center(40),'折扣', '價格') for v in TripList: ts = GetDateTimeStrFromTimeSru(v['start_time']) te = GetDateTimeStrFromTimeSru(v['expires_time']) di = ts[:10] ti = '%s->%s' % (ts[- 8:], te[-8:]) dis = '%.1f折' % (v['discount']) price = '%d元' % (v['price']) msg += '%s\t%s\t%s\t%s\t%s\r\n' % (v['avc'], di, ti, dis, price) msg += '='*60 + "\r\n\r\n" return msg #傳送郵件,支援HTML格式和普通文字格式 def send_mail (to_list, sub,content ,ishtml=False) : if not CanSend(content): return False mail_host = "smtp.qq.com"# https://mail.qq.com/ mail_user = "xxxx" mail_pass = "xxxxx" mail_postfix = "qq.com" me=mail_user + "<" + mail_user + "@" + mail_postfix+">" msg = MIMEText(content) if ishtml: msg = MIMEText(content, _subtype='html', _charset='utf-8') msg ['Subject'] = sub msg ['From'] = me msg ['To'] = ";".join(to_list) try: s = smtplib.SMTP() s.connect(mail_host) s.login(mail_user, mail_pass) s.sendmail(me, to_list, msg.as_string ()) s.close() print('send emial success') return True except Exception as e: print(str(e)) print('send emial failed') return False #監控低價航班列表,一旦發現有低折扣的機票就傳送郵件 def MonitorLowTrip (FromAddr, ToAddr, DisCount=3, MaxNum=5 ): email_li = ['
[email protected]'] while True: all_info = GetPlaneTicketPrice(FromAddr, ToAddr) #print all_info LowTrip = GetTripByPrice(all_info, date_beg='2018-10-01' ,date_end= '2018-10-08')[:MaxNum] if LowTrip: if LowTrip[ 0]['discount' ] <= DisCount: msg = MakeHtmlPage(LowTrip) .encode('utf-8' ) send_mail(email_li, "[低價機票]", msg, True) print(msg) else: print('未發現符合要求的機票') time.sleep(10) if __name__ == '__main__': #啟動監控指令碼,監控從深圳飛往寧波的機票,低於4折就把最低價的10條記錄發往郵箱 MonitorLowTrip('深圳', '西安', 5, 10)