用python搶火車票-----在debug中我終於成功了~。~
阿新 • • 發佈:2019-02-04
經院吉吉:
過年的時候一直在嘗試做這個事情,嘿嘿,沒想到終於成功了,有點小激動,網上也有部分程式碼,但是都失效了,甚至有的用python2,這個程式碼也有一定的侷限性,但是目的達到了。話不多說上程式碼
# -*- coding: utf-8 -*- """ Created on Wed May 9 14:12:25 2018 @author: JJ """ #12306賬號 myuser="賬號" mypasswd="密碼" import urllib.request import re import ssl import urllib.parse import http.cookiejar import datetime import time ssl._create_default_https_context = ssl._create_unverified_context areatocode={"上海":"SHH","北京":"BJP","南京":"NJH","崑山":"KSH","杭州":"HZH","桂林":"GLZ"} start1=input("請輸入起始站:") start=areatocode[start1] to1=input("請輸入到站:") to=areatocode[to1] isstudent=input("是學生嗎?是:1,不是:0") date=input("請輸入要查詢的乘車開始日期的年月,如1997-10-07:") if(isstudent=="0"): student="ADULT" else: student="0X00" url="https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date="+date+"&\ leftTicketDTO.from_station="+start+"&leftTicketDTO.to_station="+to+"&purpose_codes="+student context = ssl._create_unverified_context() data=urllib.request.urlopen(url).read().decode("utf-8","ignore") patrst01='"result":\[(.*?)\]' rst01=re.compile(patrst01).findall(data)[0] allcheci=rst01.split(",") checimap_pat='"map":({.*?})' checimap=eval(re.compile(checimap_pat).findall(data)[0]) print("車次\t出發站名\t到達站名\t出發時間\t到達時間\t一等座\t二等座\t硬座\t無座") for i in range(0,len(allcheci)): try: thischeci=allcheci[i].split("|") code=thischeci[3] fromname=thischeci[6] fromname=checimap[fromname] toname=thischeci[7] toname=checimap[toname] stime=thischeci[8] atime=thischeci[9] yz=thischeci[31] wz=thischeci[30] ze=thischeci[29] zy=thischeci[26] print(code+"\t"+fromname+"\t"+toname+"\t"+stime+"\t"+atime+"\t"+str(zy)+"\t"+str(ze)+"\t\ "+str(yz)+"\t"+str(wz)) except Exception as err: pass isdo=input("查票完成,請輸入1繼續…") if(isdo==1 or isdo=="1"): pass else: raise Exception("輸入不是1,結束執行") print("Cookie處理中…") cjar=http.cookiejar.CookieJar() opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cjar)) urllib.request.install_opener(opener) loginurl="https://kyfw.12306.cn/otn/login/init#" req0 = urllib.request.Request(loginurl) req0.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, lik\ e Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req0data=urllib.request.urlopen(req0).read().decode("utf-8","ignore") yzmurl="https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand" while True: urllib.request.urlretrieve(yzmurl,"圖片路徑") yzm=input("請輸入驗證碼,輸入第幾張圖片即可") if(yzm!="re"): break pat1='"(.*?)"' allpic=re.compile(pat1).findall(yzm) def getxy(pic): if(pic==1): xy=(35,45) if(pic==2): xy=(112,45) if(pic==3): xy=(173,45) if(pic==4): xy=(253,45) if(pic==5): xy=(35,114) if(pic==6): xy=(112,114) if(pic==7): xy=(173,114) if(pic==8): xy=(253,114) return xy allpicpos="" for i in allpic: thisxy=getxy(int(i)) for j in thisxy: allpicpos=allpicpos+str(j)+"," allpicpos2=re.compile("(.*?).$").findall(allpicpos)[0] print(allpicpos2) yzmposturl="https://kyfw.12306.cn/passport/captcha/captcha-check" yzmpostdata =urllib.parse.urlencode({ "answer":allpicpos2, "rand":"sjrand", "login_site":"E", }).encode('utf-8') req1 = urllib.request.Request(yzmposturl,yzmpostdata) req1.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, lik\ e Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req1data=urllib.request.urlopen(req1).read().decode("utf-8","ignore") loginposturl="https://kyfw.12306.cn/passport/web/login" loginpostdata =urllib.parse.urlencode({ "username":myuser, "password":mypasswd, "appid":"otn", }).encode('utf-8') req2 = urllib.request.Request(loginposturl,loginpostdata) req2.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, lik\ e Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req2data=urllib.request.urlopen(req2).read().decode("utf-8","ignore") loginposturl2="https://kyfw.12306.cn/otn/login/userLogin" loginpostdata2 =urllib.parse.urlencode({ "_json_att":"", }).encode('utf-8') req2_2 = urllib.request.Request(loginposturl2,loginpostdata2) req2_2.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, lik\ e Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req2data_2=urllib.request.urlopen(req2_2).read().decode("utf-8","ignore") #loginposturl3="https://kyfw.12306.cn/passport/web/auth/uamtk" loginposturl4="https://kyfw.12306.cn/otn/uamauthclient" loginpostdata4 =urllib.parse.urlencode({ "tk":"cli2f6l6ey0neIVsR_moEUOUHtyMFxiOFhQpnAnxy2y0", }).encode('utf-8') req2_4 = urllib.request.Request(loginposturl4,loginpostdata4) req2_4.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, lik\ e Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req2data_4=urllib.request.urlopen(req2_4).read().decode("utf-8","ignore") centerurl="https://kyfw.12306.cn/otn/index/initMy12306" req3 = urllib.request.Request(centerurl) req3.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, lik\ e Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req3data=urllib.request.urlopen(req3).read().decode("utf-8","ignore") print("登陸完成") isdo=input("如果需要訂票,請輸入1繼續,否則請輸入其他資料") if(isdo==1 or isdo=="1"): pass else: raise Exception("輸入不是1,結束執行") thiscode=input("請輸入要預定的車次:") chooseno="None" while True: try: initurl="https://kyfw.12306.cn/otn/leftTicket/init" reqinit=urllib.request.Request(initurl) reqinit.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.3\ 6 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') initdata=urllib.request.urlopen(reqinit).read().decode("utf-8","ignore") bookurl="https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date="+date+"&leftTi\ cketDTO.from_station="+start+"&leftTicketDTO.to_station="+to+"&purpose_codes="+student req4 = urllib.request.Request(bookurl) req4.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHT\ ML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req4data=urllib.request.urlopen(req4).read().decode("utf-8","ignore") patrst01='"result":\[(.*?)\]' rst01=re.compile(patrst01).findall(req4data)[0] allcheci=rst01.split(",") checimap_pat='"map":({.*?})' checimap=eval(re.compile(checimap_pat).findall(req4data)[0]) code=[] secretStr=[] zy=[] for i in range(0,len(allcheci)): try: thischeci=allcheci[i].split("|") thiscode1=thischeci[3] code.append(thiscode1) secretStr.append(thischeci[0].replace('"',"")) thiszy=thischeci[31] zy.append(thiszy) except Exception as err: pass trainzy={} for i in range(0,len(code)): trainzy[code[i]]=zy[i] traindata={} for i in range(0,len(code)): traindata[code[i]]=secretStr[i] checkurl="https://kyfw.12306.cn/otn/login/checkUser" checkdata =urllib.parse.urlencode({ "_json_att":"" }).encode('utf-8') req5 = urllib.request.Request(checkurl,checkdata) req5.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.3\ 6 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req5data=urllib.request.urlopen(req5).read().decode("utf-8","ignore") backdate=datetime.datetime.now() backdate=backdate.strftime("%Y-%m-%d") submiturl="https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest" submitdata =urllib.parse.urlencode({ "secretStr":traindata[thiscode], "train_date":date, "back_train_date":backdate, "tour_flag":"dc", "purpose_codes":student, "query_from_station_name":start1, "query_to_station_name":to1, }) submitdata2=submitdata.replace("%25","%") submitdata3=submitdata2.encode('utf-8') req6 = urllib.request.Request(submiturl,submitdata3) req6.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.3\ 6 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req6data=urllib.request.urlopen(req6).read().decode("utf-8","ignore") initdcurl="https://kyfw.12306.cn/otn/confirmPassenger/initDc" initdcdata =urllib.parse.urlencode({ "_json_att":"" }).encode('utf-8') req7 = urllib.request.Request(initdcurl,initdcdata) req7.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.3\ 6 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req7data=urllib.request.urlopen(req7).read().decode("utf-8","ignore") train_no_pat="'train_no':'(.*?)'" leftTicketStr_pat="'leftTicketStr':'(.*?)'" fromStationTelecode_pat="from_station_telecode':'(.*?)'" toStationTelecode_pat="'to_station_telecode':'(.*?)'" train_location_pat="'train_location':'(.*?)'" pattoken="var globalRepeatSubmitToken.*?'(.*?)'" patkey="'key_check_isChange':'(.*?)'" train_no_all=re.compile(train_no_pat).findall(req7data) if(len(train_no_all)!=0): train_no=train_no_all[0] else: raise Exception("train_no獲取失敗") leftTicketStr_all=re.compile(leftTicketStr_pat).findall(req7data) if(len(leftTicketStr_all)!=0): leftTicketStr=leftTicketStr_all[0] else: raise Exception("leftTicketStr獲取失敗") fromStationTelecode_all=re.compile(fromStationTelecode_pat).findall(req7data) if(len(fromStationTelecode_all)!=0): fromStationTelecode=fromStationTelecode_all[0] else: raise Exception("fromStationTelecod獲取失敗") toStationTelecode_all=re.compile(toStationTelecode_pat).findall(req7data) if(len(toStationTelecode_all)!=0): toStationTelecode=toStationTelecode_all[0] else: raise Exception("toStationTelecode獲取失敗") train_location_all=re.compile(train_location_pat).findall(req7data) if(len(train_location_all)!=0): train_location=train_location_all[0] else: raise Exception("train_location獲取失敗") tokenall=re.compile(pattoken).findall(req7data) if(len(tokenall)!=0): token=tokenall[0] else: raise Exception("Token獲取失敗") keyall=re.compile(patkey).findall(req7data) if(len(keyall)!=0): key=keyall[0] else: raise Exception("key_check_isChange獲取失敗") pattrain_location="'tour_flag':'dc','train_location':'(.*?)'" train_locationall=re.compile(pattrain_location).findall(req7data) if(len(train_locationall)!=0): train_location=train_locationall[0] else: raise Exception("train_location獲取失敗") getuserurl="https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs" getuserdata =urllib.parse.urlencode({ "REPEAT_SUBMIT_TOKEN":token, }).encode('utf-8') req8 = urllib.request.Request(getuserurl,getuserdata) req8.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.3\ 6 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req8data=urllib.request.urlopen(req8).read().decode("utf-8","ignore") namepat='"passenger_name":"(.*?)"' idpat='"passenger_id_no":"(.*?)"' mobilepat='"mobile_no":"(.*?)"' countrypat='"country_code":"(.*?)"' nameall=re.compile(namepat).findall(req8data) idall=re.compile(idpat).findall(req8data) mobileall=re.compile(mobilepat).findall(req8data) countryall=re.compile(countrypat).findall(req8data) if(chooseno!="None"): pass else: for i in range(0,len(nameall)): print("第"+str(i+1)+"位使用者,姓名:"+str(nameall[i])) chooseno=input("請選擇要訂票的使用者的序號,如需選擇多\ 位,可以自行修改一下程式碼") thisno=int(chooseno)-1 if(trainzy[thiscode]=="無"): print("當前無票,繼續監控…") continue checkOrderurl="https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo" checkdata=urllib.parse.urlencode({ "cancel_flag":2, "bed_level_order_num":"000000000000000000000000000000", "passengerTicketStr":"M,0,1,"+str(nameall[thisno])+",1,"+str(idall[thisno])+",\ "+str(mobileall[thisno])+",N", "oldPassengerStr":str(nameall[thisno])+",1,"+str(idall[thisno])+",1_", "tour_flag":"dc", "randCode":"", "whatsSelect":1, "_json_att":"", "REPEAT_SUBMIT_TOKEN":token, }).encode('utf-8') req9 = urllib.request.Request(checkOrderurl,checkdata) req9.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KH\ TML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req9data=urllib.request.urlopen(req9).read().decode("utf-8","ignore") print("確認訂單完成,即將進行下一步") getqueurl="https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount" thisdatestr=date thisdate=datetime.datetime.strptime(thisdatestr,"%Y-%m-%d").date() gmt='%a+%b+%d+%Y' thisgmtdate=thisdate.strftime(gmt) leftstr2=leftTicketStr.replace("%","%25") getquedata="train_date="+str(thisgmtdate)+"+00%3A00%3A00+GMT%2B0800&train_no="+train_no+"&sta\ tionTrainCode="+thiscode+"&seatType=M&fromStationTelecode="+fromStationTelecode+"&toStationTelecod\ e="+toStationTelecode+"&leftTicket="+leftstr2+"&purpose_codes=00&train_location="+train_location+"&_j\ son_att=&REPEAT_SUBMIT_TOKEN="+str(token) getdata=getquedata.encode('utf-8') req10 = urllib.request.Request(getqueurl,getdata) req10.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTM\ L, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req10data=urllib.request.urlopen(req10).read().decode("utf-8","ignore") print("獲取訂單佇列完成,即將進行下一步") confurl="https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue" confdata2=urllib.parse.urlencode({ "passengerTicketStr":"M,0,1,"+str(nameall[thisno])+",1,"+str(idall[thisno])+",\ "+str(mobileall[thisno])+",N", "oldPassengerStr":str(nameall[thisno])+",1,"+str(idall[thisno])+",1_", "randCode":"", "purpose_codes":"00", "key_check_isChange":key, "leftTicketStr":leftTicketStr, "train_location":train_location, "choose_seats":"", "seatDetailType":"000", "whatsSelect":"1", "roomType":"00", "dwAll":"N", "_json_att":"", "REPEAT_SUBMIT_TOKEN":token, }).encode('utf-8') req11 = urllib.request.Request(confurl,confdata2) req11.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.3\ 6 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req11data=urllib.request.urlopen(req11).read().decode("utf-8","ignore") print("配置確認提交完成,即將進行下一步") time1=time.time() while True: time2=time.time() if((time2-time1)//60>5): print("獲取orderid超時,正在進行新一次搶購") break getorderidurl="https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random="+str(int(time.time()*1000))+"&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN="+str(token) req12 = urllib.request.Request(getorderidurl) req12.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req12data=urllib.request.urlopen(req12).read().decode("utf-8","ignore") patorderid='"orderId":"(.*?)"' orderidall=re.compile(patorderid).findall(req12data) if(len(orderidall)==0): print("未獲取到orderid,正在進行新一次的請求。") continue else: orderid=orderidall[0] break print("獲取orderid完成,即將進行下一步") resulturl="https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue" resultdata="orderSequence_no="+orderid+"&_json_att=&REPEAT_SUBMIT_TOKEN="+str(token) resultdata2=resultdata.encode('utf-8') req13 = urllib.request.Request(resulturl,resultdata2) req13.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req13data=urllib.request.urlopen(req13).read().decode("utf-8","ignore") print("請求結果完成,即將進行下一步") try: payurl="https://kyfw.12306.cn/otn//payOrder/init" paydata="_json_att=&REPEAT_SUBMIT_TOKEN="+str(token) paydata2=paydata.encode('utf-8') req14 = urllib.request.Request(payurl,paydata2) req14.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0') req14data=urllib.request.urlopen(req14).read().decode("utf-8","ignore") print("訂單已經完成提交,您可以登入後臺進行支付了。") break except Exception as err: break except Exception as err: print(err)
使用前需要做的事情:
1.註釋掉的網站需要用抓包工具找出newapptk後面的東東,就是tk的內容
2.需要設定驗證碼圖片存放路徑
注意注意:
1.驗證碼只需要輸入第幾張圖片,注意有逗號
2.用之前,想好買哪張車票,不要嘗試,錯買,不然IP就封了,(剛才就被封了)。
說明:這段程式碼是站在巨人肩膀上完成的,結合了許多大佬們的程式碼。。
最後祝大家六一兒童節出行快樂!!!!!。。。。。。。。。。。。。