前几日买十一回家的火车票,同事说这个12306的爬虫你能不能做,我简单的分析了一下,发现不难,便寻思着通过爬虫及爬虫后的结果来分析在买不到火车票时该如何购买回家的火车票。说干就干。
首先抓包,发现火车票信息都能直接查到在result中。
URL为https://kyfw.12306.cn/otn/leftTicket/queryA?leftTicketDTO.train_date=2018-10-01&leftTicketDTO.from_station=HGH&leftTicketDTO.to_station=TZH&purpose_codes=ADULT
我们发现需要train_date(查询的时间),from_station(起始站),to_station(终点站),其余的参数不可去除。
那么起始站终点站的编码("HGH":"杭州东","TZH":"台州")该怎么得到。
重新刷新页面,发现有个station_name.js,返回的是我们需要的编码
代码如上,将返回值拼成一个字符串,得到一个数组如下,省略了一部分
CITY_JSON={"北京北":"VAP","北京东":"BOP","北京":"BJP","北京南":"VNP","北京西":"BXP"}
调用时就直接CITY_JSON["杭州东"]
编码的问题解决了,就可以直接调用了
选择输入的时间,出发地,目的地及列车类型,开始查询。
将所传的参数传入之前的URL,返回后进行解析,注意,高铁和普通列车分割时车票信息的位置不一样,需要区分处理。
这里我们将无票的车次进行了上车补票的查询,即查询该班列车所经过的其他地点是否有票以便上车补票。
选中某一班列车,观察抓包情况。
可以发现该班列车的所有站点信息都被查询出来了
URL为https://kyfw.12306.cn/otn/czxx/queryByTrainNo?train_no=5l000G754340&from_station_telecode=HGH&to_station_telecode=TZH&depart_date=2018-10-01
除了和之前一样的时间地点参数,我们还需要一个train_no,train_no在之前的URL中也能查到,所以这些参数也都解决了。
我们取到杭州东到台州的中间车站的信息,替换之前的终点站进行查询,再筛选同一班车次判断是否有票,若无,则查询下一个城市直至所有经过的城市都查询完成。
查询部分结果如下。
这样我们就能看到该在哪一站上车补票了。
当然,如果碰到比较热门的时间和车次,我们连买中间站补票的机会都没有的话,就需要进行换乘了。
12306其实本身就自带换乘查询,原先想直接爬取12306换乘查询的数据进行解析的,不过想想还是自己通过现有的几个接口进行分析。
中间站换乘,首要的是时间,你第一班列车抵达时间必须要在第二班列车开始之前,这里我设置了半小时,即第一班列车抵达后至少要半小时第二班列车才发车,也是为了能赶上火车吧。为了等待时间考虑,第一班列车两小时后发动的列车就不再显示,毕竟作为中间站,要在那儿待两个小时已经是比较久的了。因为日期不好界定 ,在23:30之后的我统一调为23:59.
这里我封装了一个时间加半小时及两小时的方法
到时查询时直接调用该方法修改时间。
查询的逻辑不算复杂,先是查询所有在你限定的出发时间段所开出的列车所要经过的中间站,取到所有的中间站,再对对应的中间站查询,先查询出发地到中间站的列车,若有,则查询在第一班列车抵达后一段时间内到终点站的列车是否有票,若无,则不作显示,查询完一个地点后查询下一个地点,直到所有地点都查询完毕,得到我们所需要的换乘信息。
这里如何得到所有中间站信息,需要先查询所有该时间段的列车,再通过train_no查询每一班列车所经过的站点,最后append进一个数组。
在将所有站点append后,由于会出现重复的信息,我们调用去重方法list(set(train_no_list))
最后得到一个没有重复的数组。
遍历该数组,并进行逐个查询。查询结果如下:
麻麻再也不用担心我回家的火车票!
代码较多,就不发了,有需要的小伙伴可以留言
网友评论