导读:火车剩余票数12306,返回之路不容易剩余票数12306,给出备选v2。在第一版《归乡剩余12306票之路不容易的查询和备选的推荐》中,给出了剩余票数的查询和备选的推荐,但当时有两个问
火车剩余票数12306,返回之路不容易剩余票数12306,给出备选v2。
在第一版《归乡剩余12306票之路不容易的查询和备选的推荐》中,给出了剩余票数的查询和备选的推荐,但当时有两个问题:
没有备选方案排名:虽然给出了备选方案,但没有给出哪个备选方案更好的排名。无座信息(商务/头等舱/二等座/硬座/硬卧/无座):虽然可以买到,但是不一定能买到适合自己的(便宜),有点奢侈。
所以这几天一直在更新代码。
首先说一下备选方案排序的原理。如果不能直接买到始发站和目的地的车票,只要在始发站和始发站之间买始发站,在始发站和终点站之间买到站,就可以顺利上这趟车,可以多买几站或者上车补票。所以我们的排序原则是花最少的钱回家。我们做什么呢始发站尽量买离始发站近的,到站尽量买离目的站近的,尽量补票而不是多买几站。毕竟我们坚持最少花钱的原则。
取得的效果如下
这次做2.0的时候,对代码进行了优化:
城市缩写由保存的文件读入,不使用12306接口获取,加快速度;(城市缩写文件可以由第一版的城市()
获取并保存如下形式的函数:){ "北京& # 34;: "VAP & # 34;, "北京东部& # 34;: "BOP & # 34, "北京& # 34;: "BJP & # 34;, "北京南部& # 34;: "VNP & # 34, "北京西部& # 34;: "BXP & # 34;, "广州南& # 34;: "IZQ & # 34, "重庆北& # 34;: "CUW & # 34;, "重庆& # 34;: "CQW & # 34;, "重庆& # 34;: "CRW & # 34;,...}增加爬虫自检机制,如果接口调用失败,延迟一段时间后再调用;
增加了座位信息;
订购替代品。
代码如下:
# coding = utf-8 import requests import URL lib . parse as parse import TIME import JSON import pretty _ errors import ref om fake _ user agent import UserAgentTRAIN _ N O = 2 train = 3 departure _ STATION = 6 terminus = 7 departure _ TIME = 8 arrival _ TIME = 9 duration = 10IF _ BOOK = 11 date = 13 from _ STATION _ NO = 16 to _ STATION _ NO = 7 set _ types = 35 # other = 22 NO _ seat = 26 # wz hard _ seat = 29 # A1秒, 'r & # 39)为f:Citys = JSON . load(f)def Time():& # 34;""获取当前时间:return:& # 34;""list _ time = list(time . local time())year = str(list _ time[0])month = str(list _ time[1])day = str(list _ time[2])if len(month)= = 1:month = & # 39;0'+月if len(day)= = 1:day = & # 39;0'+ day return年、月、日dayproxy = { & # 39http & # 39: '113.125.128.4:8888'}class Train: def __init__(self,from_station,to_station,Train _ date = Time()[0]+& # 39;-'+Time()[1]+& # 39;-'+Time()[2]):self . from _ station = from _ station self . to _ station = to _ station self . train _ date = train _ date self . URL = & # 39;https://kyfw.12306.cn/otn/leftTicket/queryA?离开了。% s & leftTicketDTO。% s & leftTicketDTO。% s & purpose _ codes =成人& # 39;self.headers = { & # 39用户代理& # 39;:str(UserAgent()。random)} self . session = requests . session()self . session . get(& # 39;https://kyfw.12306.cn/otn/leftTicket/init? link typeid = DC & fs = % E6 % 9D % AD % E5 % B7 % 9E % E4 % B8 % 9C,HGH & ts = % E5 % A4 % AA % E5 % 8E % 9F % E5 % 8D % 97,TNV&date=2022-01-19&flag=N,N,Y & # 39,headers=self.headers,proxies = proxy,timeout=5) def station(self,train _ number):& # 34;""找到火车的起点和终点:返回:& # 34;""url = f & # 39https://kyfw.12306.cn/otn/czxx/queryByTrainNo? & # 39;\ f & # 39{ parse . urlencode({ & # 34;火车号& # 34;:train _ number })} & & # 39;\ f & # 39{ parse . urlencode({ & # 34;from _ station _ telecode & # 34:cities[self . from _ station]})} & & # 39;\ f & # 39{ parse . urlencode({ & # 34;to _ station _ telecode & # 34:cities[self . to _ station]})} & & # 39;\ f & # 39{ parse . urlencode({ & # 34;出发日期& # 34;:self . train _ date })} & # 39;self . headers[& # 39;用户代理& # 39;] = str(UserAgent()。random)content = self . session . get(URL,headers=self.headers,proxies = proxy,time out = 5)content = content . content . decode(& # 39;utf-8 & # 39;)data = json.loads(内容)stations _ data = data[& # 39;数据& # 39;]['数据& # 39;]stations _ data . sort(key = lambda x:x[& # 39;站号& # 39;])from _ station _ idx = int(list(filter(lambda x:self . from _ station in x[& # 39;station _ name & # 39],stations _ data))[0][& # 39;站号& # 39;])to _ station _ idx = int(list(filter(lambda x:self . to _ station in x[& # 39;station _ name & # 39],stations _ data))[0][& # 39;站号& # 39;])from _ station _ buy =[station[& # 39;station _ name & # 39]for stations _ data[:from _ station _ idx]][::-1]to _ station _ buy _ 1 =[station[& # 39;station _ name & # 39]for stations _ data[from _ station _ idx:to _ station _ idx]][::-1]to _ station _ buy _ 2 =[station[& # 39;station _ name & # 39]for stations _ data[to _ station _ idx:]]to _ station _ buy = to _ station _ buy _ 1+to _ station _ buy _ 2返回from_station_buy,to _ station _ buy def train(self):& # 34;""获取信息:返回:& # 34;""URL = self . URL %(parse . urlencode({ & # 34;train _ date & # 34:self.train_date})、parse . urlencode({ & # 34;from _ station & # 34:cities[self . from _ station]})、parse . urlencode({ & # 34;to _ station & # 34:cities[self . to _ station]}))self . headers[& # 39;用户代理& # 39;] = str(UserAgent()。random)content = self . session . get(URL,headers=self.headers,proxies = proxy,time out = 5)content = content . content . decode(& # 39;utf-8 & # 39;)data = JSON . loads(content)dict _ train = data[& # 39;数据& # 39;]['结果& # 39;]dict _ map = data[& # 39;数据& # 39;]['地图& # 39;]RES =[]TRAINs =[]for train in dict _ train:train _ split = train . split(& # 39;|')如果TRAIN _ split[TRAIN]in TRAINs:continue print(TRAIN _ split[TRAIN])prices = self . price(TRAIN _ split[FROM _ STATION _ NO],train_split[TO_STATION_NO],train_split[SEAT_TYPES],TRAIN _ split[TRAIN _ NO])FROM _ STATION _ buy,TO _ STATION _ buy = self . STATION(TRAIN _ split[TRAIN _ NO])buy =[]for FROM _ STATION,to_station in [[x,y]for x in FROM _ STATION _ STATION _ buy for y in TO _ STATION _ buyN & # 39以及self.book_if(from_station,to_station,TRAIN _ split[TRAIN]):buy . append(f & # 39;{ from _ station }-{ to _ station } & # 39;)TRAIN _ str =[TRAIN _ split[火车],dict _ map[TRAIN _ split[出发_车站]],dict _ map[TRAIN _ split[终点站]],TRAIN _ split[出发_时间],TRAIN _ split[到达_时间],TRAIN _ split[持续时间],f & # 39{ train _ split[BUSINESS _ SEAT]}/{ prices . get(& # 34;A9 & # 34)}'如果train_split[BUSINESS_SEAT]和train_split[BUSINESS_SEAT]!= '无& # 39;else & # 39无& # 39;,f & # 39{ train _ split[FIRST _ SEAT]}/{ prices . get(& # 34;M & # 34)}'if train_split[FIRST_SEAT]和train_split[FIRST_SEAT]!= '无& # 39;else & # 39无& # 39;,f & # 39{ train _ split[SECOND _ SEAT]}/{ prices . get(& # 34;O & # 34)}'如果train_split[SECOND_SEAT]和train_split[SECOND_SEAT]!= '无& # 39;else & # 39无& # 39;,f & # 39{ train _ split[SOFT _ SLEEPER]}/{ prices . get(& # 34;A4 & # 34)}'如果train _ split[软卧]和train _ split[软卧]!= '无& # 39;else & # 39无& # 39;,f & # 39{ train _ split[HARD _ SLEEPER]}/{ prices . get(& # 34;A3 & # 34)}'如果train_split【硬卧】和train_split【硬卧】!= '无& # 39;else & # 39无& # 39;,f & # 39{ train _ split[HARD _ SEAT]}/{ prices . get(& # 34;A1 & # 34)}'如果train _ split[硬座]和train _ split[硬座]!= '无& # 39;else & # 39无& # 39;,f & # 39{ train _ split[NO _ SEAT]}/{ prices . get(& # 34;WZ & # 34;)}'如果train_split[NO_SEAT]和train_split[NO_SEAT]!= '无& # 39;else & # 39无& # 39;, '是的& # 39;IF train _ split[IF _ BOOK]= = & # 39;Y & # 39else & # 39不& # 39;, ', '。join(buy)]RES . append(& # 39;| '+ '| '。join(train _ str)+& # 39;|')trains . append(TRAIN _ split[TRAIN])return RES def book _ if(self,from_station,to_station,TRAIN _ number):& # 34;""检查是否有票:param from _ station::param to _ station::param train _ number::return:& # 34;""URL = self . URL %(parse . urlencode({ & # 34;train _ date & # 34:self.train_date})、parse . urlencode({ & # 34;from _ station & # 34:cities[from _ station]})、parse . urlencode({ & # 34;to _ station & # 34:cities[to _ station]})火车=[& # 39;'] for _ in范围(20):try:self . headers[& # 39;用户代理& # 39;] = str(UserAgent()。random)content = self . session . get(URL,headers=self.headers,proxies = proxy,time out = 5)content = content . content . decode(& # 39;utf-8 & # 39;)data = JSON . loads(content)dict _ train = data[& # 39;数据& # 39;]['结果& # 39;]train = list(filter(lambda x:x . split(& # 39;|')[TRAIN] == train_number,dict_train))如果不是train: return break除外:print(& # 39;查询剩余票证的请求失败。再次请求& # 39;)time.sleep(2)如果train[0]则返回True。拆分(& # 39;|')[IF _ BOOK]= = & # 39;Y & # 39else False def price(self,from_station_no,to_station_no,seat_types,train _ no):& # 34;""查一下票价:返回:& # 34;""url = f & # 39https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice? & # 39;\ f & # 39{ parse . urlencode({ & # 34;火车号& # 34;:train _ no })} & & # 39;\ f & # 39{ parse . urlencode({ & # 34;from _ station _ no & # 34:from _ station _ no })} & & # 39;\ f & # 39{ parse . urlencode({ & # 34;to _ station _ no & # 34:to _ station _ no })} & & # 39;\ f & # 39{ parse . urlencode({ & # 34;座位类型& # 34;:seat _ types })} & & # 39;\ f & # 39{ parse . urlencode({ & # 34;train _ date & # 34:self . train _ date })} & # 39;data = { } for _ in range(20):try:self . headers[& # 39;用户代理& # 39;] = str(UserAgent()。random)content = self . session . get(URL,headers=self.headers,proxies = proxy,time out = 5)content = content . content . decode(& # 39;utf-8 & # 39;)data = JSON . loads(content)break except:print(& # 39;价格查询请求失败。请再次请求& # 39;)time.sleep(2)返回data . get(& # 39;数据& # 39;)if _ _ name _ _ = = & # 39_ _ main _ _ & # 39:打印(& # 39;-12306信息查询-)while True:from _ station = input(& # 39;请输入原点:& # 39;)或者& # 39;杭州& # 39;if from _ station in city s:break while True:to _ station = input(& # 39;请输入目的地:& # 39;)或者& # 39;太原& # 39;if to _ station in city s:break pattern = re . compile(& # 39;\ d { 4 }-\ d { 2 }-\ d { 2 } & # 39;)而True:date = input(& # 39;请输入出发时间(注意格式:2022-02-01,默认为购票当天):& # 39;)if not date或re.match(pattern,date):break if not date:date = Time()[0]+& # 39;-'+Time()[1]+& # 39;-'+Time()[2]Train = Train(from _ station,to_station,date)# information = Train . Train()print(& # 39;- ')打印(& # 39;-)打印(& # 39;- ')打印(& # 39;|车次|始发站|到达站|出发时间|到达时间|时长|商务座|一等座|二等座|软卧|硬卧|无座|直购|备选| & # 39;)for info in information:print(info)print(& # 39;- '山西的疫情防控政策也有所松动。之前只要在北京海淀待过,就要回家14天集中隔离。恶意返家
事件发生后,政策也有所松动。目前海淀只需要核酸回去。这次回家之路顺利多了,给国家和山西政府点个赞!当然,目前的版本仍然存在问题:只是这个排名太死板了,只考虑了始发站和到达站的距离,没有考虑座位信息。例如,你可以多买几站,然后坐在后面,但是为了少买票而不得不站着是不合适的。
所以为了能舒舒服服回家,开始下一版…总结:以上内容参考了12306 火车的查询和12306 之路不容易的查询并对备选v2进行了详细介绍。文章内容部分转载自网络,希望对你理解12306的查询有帮助和价值。版权声明
本站搜集来源于网络,如侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意。