前言
每到节假日出行高峰,火车票都比较紧张,这时候如果有个小工具能自动查询余票信息,并且微信通知,相信大家都会觉得很方便.12306官网的自动提醒功能,每5s才能刷新一次,很不友好.既然如此,我们应该让他对我们友好.
程序设计
请求、解析、处理数据是通用爬虫的三个步骤。在这个案例中,我们请求12306的查询接口,解析自己想要车票数据,再通过第三方服务微信通知我们。
分析网页
点击查询获取数据的响应
通过分析链接发现是get请求,并且需要携带三个参数,并且发车站和到车站用JS处理过,后台传过去的是代号
通过搜索功能搜索到城市代码表
分析
https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9142
,发现中文 | CODE
是我们需要的格式我需要的数据是
车次
,出发时间
,到达时间
,二等座票数
。分析返回的响应数据,我想要的数据分别对应3
,8
,9
,30
。(www.hedaoshe.com)
Server酱推送功能
Server酱推送在她官网有详细介绍,我这里就不罗嗦了。
代码实现
根据我们以上的分析,下面就开始写代码了. 步骤:
获取城市站点名称和代码对应规则
根据获取的规则拼接我们要请求的url
发送请求,解析,并通过server酱推送到我们微信
-- coding: utf-8 --
import requests import re import time
requests.packages.urllib3.disable_warnings()
headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36' }
封装的server酱推送函数
def send_msg(title,info): url=('https://sc.ftqq.com/SCU92306T720aa3d22514912ba47be0fd854826ef5e85b1970ff90.send?' 'text={}&desp={}').format(title,info) requests.get(url) #获取城市站点名称和代码对应规则 def get_city_station_code(): url="https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9142" r = requests.get(url,verify=False,headers=headers) pattern = u'([\u4e00-\u9fa5]+)|([A-Z]+)' result = re.findall(pattern,r.text) city_station_rule=dict(result) return city_station_rule
拼接我们的请求URL
def get_query_url(from_station_name,to_station_name,date,ticket_type="ADULT"): station_rule=get_city_station_code() from_station_code=station_rule[from_station_name] to_station_code=station_rule[to_station_name] url=('https://kyfw.12306.cn/otn/leftTicket/query?' 'leftTicketDTO.train_date={}&' 'leftTicketDTO.from_station={}&' 'leftTicketDTO.to_station={}&' 'purpose_codes={}' ).format(date,from_station_code,to_station_code,ticket_type) return url #发送请求,解析,并通过server酱推送到我们微信 def query_analysis_send(url): s=requests.session() r= s.get('https://kyfw.12306.cn/otn/leftTicket/init',headers=headers) r= s.get(url,verify=False,headers=headers) raw_trains=r.json()['data']['result'] train_info='' info_list=[] for raw_train in raw_trains: data_list = raw_train.split('|') train_no=data_list[3] start_time = data_list[8] arrive_time = data_list[9] second_seat=data_list[30] or '--' info = ('车次:{} ,' '出发时间:{} ,' '到达时间:{} ,' '二等座票数:{}\n' ).format(train_no,start_time,arrive_time,second_seat) if(second_seat.isdigit()): info_list.append(info) if(info_list.len()>0): for value in info_list: train_info+=value+'\n' send_msg(title='有票啦',info = train_info) return True #执行程序入口 if name == "main": url = get_query_url("南昌","上海","2020-04-17") while True: time.sleep(1) if query_analysis_send(url): break