本文共 26513 字,大约阅读时间需要 88 分钟。
简单写了一篇读取12306的票价和余票,不过没有处理最终的字符串,本文重新处理一下,并且封装成类,希望能给大家带来帮助。
原文:,
至于为什么用应用程序而不用网页实现,因为我不是要做抢票,而是做一个抓取数据然后对本地进行分析处理的功能。
1、票价的字符串处理////// 火车票票价类 /// public class TrainTicketPriceModel { private string trainCode; private string trainTeleCode; private string fromStation; private string arriveStation; private string shangwuzuo; private string tedengzuo; private string yidengzuo; private string erdengzuo; //高级软卧 private string gaojiruanwoUp; private string gaojiruanwoDown; //软卧 private string ruanwoUp; private string ruanwoDown; //硬卧 private string yingwoUp; private string yingwoMiddle; private string yingwoDown; private string ruanzuo; private string yingzuo; private string fromTime; private string arriveTime; private string throughTime; private string startStation; private string endStation; private string level; private string haveConditioner; ////// 车次 /// public string TrainCode { get { return trainCode; } set { trainCode = value; } } ////// 车次,电报码 /// public string TrainTeleCode { get { return trainTeleCode; } set { trainTeleCode = value; } } ////// 出发站 /// public string FromStation { get { return fromStation; } set { fromStation = value; } } ////// 到达站 /// public string ArriveStation { get { return arriveStation; } set { arriveStation = value; } } ////// 商务座 /// public string Shangwuzuo { get { return shangwuzuo; } set { shangwuzuo = DoFormatPrice(value); } } ////// 特等座 /// public string Tedengzuo { get { return tedengzuo; } set { tedengzuo = DoFormatPrice(value); } } ////// 一等座 /// public string Yidengzuo { get { return yidengzuo; } set { yidengzuo = DoFormatPrice(value); } } ////// 二等座 /// public string Erdengzuo { get { return erdengzuo; } set { erdengzuo = DoFormatPrice(value); } } ////// 高级软卧 /// public string GaojiruanwoUp { get { return gaojiruanwoUp; } set { gaojiruanwoUp = DoFormatPrice(value); } } public string GaojiruanwoDown { get { return gaojiruanwoDown; } set { gaojiruanwoDown = DoFormatPrice(value); } } ////// 软卧 /// public string RuanwoUp { get { return ruanwoUp; } set { ruanwoUp = DoFormatPrice(value); } } public string RuanwoDown { get { return ruanwoDown; } set { ruanwoDown = DoFormatPrice(value); } } ////// 硬卧 /// public string YingwoUp { get { return yingwoUp; } set { yingwoUp = DoFormatPrice(value); } } public string YingwoMiddle { get { return yingwoMiddle; } set { yingwoMiddle = DoFormatPrice(value); } } public string YingwoDown { get { return yingwoDown; } set { yingwoDown = DoFormatPrice(value); } } ////// 软座 /// public string Ruanzuo { get { return ruanzuo; } set { ruanzuo = DoFormatPrice(value); } } ////// 硬座 /// public string Yingzuo { get { return yingzuo; } set { yingzuo = DoFormatPrice(value); } } ////// 发时 /// public string FromTime { get { return fromTime; } set { fromTime = value; } } ////// 到时 /// public string ArriveTime { get { return arriveTime; } set { arriveTime = value; } } ////// 历时 /// public string ThroughTime { get { return throughTime; } set { throughTime = value; } } ////// 始发站 /// public string StartStation { get { return startStation; } set { startStation = value; } } ////// 终点站 /// public string EndStation { get { return endStation; } set { endStation = value; } } ////// 等级 /// public string Level { get { return level; } set { level = value; } } ////// 有无空调 /// public string HaveConditioner { get { return haveConditioner; } set { haveConditioner = value; } } private string DoFormatPrice(string price) { if (string.IsNullOrEmpty(price)) { return price; } if (!price.Contains("-")) { return price; } else { return @"----"; } } }
public class TrainTicketPriceQuery { private static string oldRandCodeImage = string.Empty; private static string setCookie = string.Empty; ////// 火车票票价信息字符串 /// private static string DoQueryTrainTicketPriceInfo(DateTime fromDate, string startStation, string arriveStation, string randCode) { string result = string.Empty; try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://dynamic.12306.cn/TrainQuery/iframeTicketPriceByStation.jsp"); request.Accept = @"text/html, application/xhtml+xml, */*"; request.UserAgent = @"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"; request.Referer = @"http://dynamic.12306.cn/TrainQuery/ticketPriceByStation.jsp"; request.ContentType = @"application/x-www-form-urlencoded"; request.Headers[HttpRequestHeader.Cookie] = setCookie; request.Method = "POST"; byte[] buffer = new byte[0]; DoGetTrainTicketPriceRandCodeImage(); string parameter = @"condition=&queryMode=1&nmonth2={0}&nmonth2_new_value=true&nday2={1}&nday2_new_value=false&startStation_ticketPrice1={2}&startStation_ticketPrice1_new_value=false&arriveStation_ticketPrice1={3}&arriveStation_ticketPrice1_new_value=false&trainCode=&trainCode_new_value=true&rFlag=1&name_ckball=value_ckball&tFlagDC=DC&tFlagZ=Z&tFlagT=T&tFlagK=K&tFlagPK=PK&tFlagPKE=PKE&tFlagLK=LK&randCode={4}"; parameter = string.Format(parameter, fromDate.Month, fromDate.Day, startStation, arriveStation, randCode); buffer = Encoding.UTF8.GetBytes(parameter); request.ContentLength = buffer.Length; using (Stream writer = request.GetRequestStream()) { writer.Write(buffer, 0, buffer.Length); writer.Flush(); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { result = reader.ReadToEnd(); } } } catch { } return result; } ////// 票价查询验证码 /// ///public static string DoGetTrainTicketPriceRandCodeImage() { string resultImage = string.Empty; try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://dynamic.12306.cn/TrainQuery/passCodeActi0n.do?rand=rrand"); request.Accept = @"image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5"; request.UserAgent = @"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"; request.Referer = @"http://dynamic.12306.cn/TrainQuery/ticketPriceByStation.jsp"; request.Method = "GET"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { setCookie = response.GetResponseHeader("Set-cookie"); setCookie = Regex.Replace(setCookie, "path(?:[^,]+),?", "", RegexOptions.IgnoreCase); using (Stream reader = response.GetResponseStream()) { string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, new Random().Next(10000, 99999) + @"queryTicketPrice.JPEG"); using (FileStream file = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write)) { reader.CopyTo(file); } resultImage = path; } } } catch { } return resultImage; } /// /// 读取票价信息 /// /// ///public static ObservableCollection DoQueryTrainTicketPriceInfoCollects(DateTime fromDate, string startStation, string arriveStation, string randCode) { string priceContent = DoQueryTrainTicketPriceInfo(fromDate, startStation, arriveStation, randCode); ObservableCollection priceCollects = new ObservableCollection (); try { if (string.IsNullOrEmpty(priceContent)) { return priceCollects; } Regex regex = new Regex(@"parent.mygrid.addRow"); string[] arrows = regex.Split(priceContent); for (int i = 0; i < arrows.Length; i++) { if (i == 0) { continue; } string[] singlePrices = arrows[i].Split(','); TrainTicketPriceModel priceModel = new TrainTicketPriceModel(); priceModel.TrainCode = singlePrices[2].Substring(0, singlePrices[2].IndexOf('^')); priceModel.TrainTeleCode = singlePrices[2].Substring(singlePrices[2].LastIndexOf('_') + 1); priceModel.FromStation = singlePrices[3].Substring(0, singlePrices[3].IndexOf('^')); priceModel.ArriveStation = singlePrices[4].Substring(0, singlePrices[4].IndexOf('^')); priceModel.Shangwuzuo = singlePrices[5]; priceModel.Tedengzuo = singlePrices[6]; priceModel.Yidengzuo = singlePrices[7]; priceModel.Erdengzuo = singlePrices[8]; string[] gaojiruanwo = singlePrices[9].Split('/'); priceModel.GaojiruanwoUp = gaojiruanwo[0]; priceModel.GaojiruanwoDown = gaojiruanwo.Length > 1 ? gaojiruanwo[1] : gaojiruanwo[0]; string[] ruanwo = singlePrices[10].Split('/'); priceModel.RuanwoUp = ruanwo[0]; priceModel.RuanwoDown = ruanwo.Length > 1 ? ruanwo[1] : ruanwo[0]; string[] yingwo = singlePrices[11].Split('/'); priceModel.YingwoUp = yingwo[0]; priceModel.YingwoMiddle = yingwo.Length > 2 ? yingwo[1] : yingwo[0]; priceModel.YingwoDown = yingwo.Length > 2 ? yingwo[2] : yingwo[0]; priceModel.Ruanzuo = singlePrices[12]; priceModel.Yingzuo = singlePrices[13]; priceModel.FromTime = singlePrices[14]; priceModel.ArriveTime = singlePrices[15]; priceModel.ThroughTime = singlePrices[16]; priceModel.StartStation = singlePrices[17].Substring(0, singlePrices[17].IndexOf('^')); priceModel.EndStation = singlePrices[18].Substring(0, singlePrices[18].IndexOf('^')); priceModel.Level = singlePrices[19]; priceModel.HaveConditioner = singlePrices[20].Substring(0, 1); priceCollects.Add(priceModel); } } catch { } return priceCollects; } }
////// 火车票余票类 /// public class TrainTicketLeftModel { private string trainCode; private string fromStation; private string arriveStation; private string throughTime; private string shangwuzuoQTY; private string tedengzuoQTY; private string yidengzuoQTY; private string erdengzuoQTY; private string gaojiruanwoQTY; private string ruanwoQTY; private string yingwoQTY; private string ruanzuoQTY; private string yingzuoQTY; private string wuzuoQTY; private string fromTime; private string arriveTime; ////// 车次 /// public string TrainCode { get { return trainCode; } set { trainCode = value; } } ////// 出发站 /// public string FromStation { get { return fromStation; } set { fromStation = value; } } ////// 到达站 /// public string ArriveStation { get { return arriveStation; } set { arriveStation = value; } } ////// 商务座 /// public string ShangwuzuoQTY { get { return shangwuzuoQTY; } set { shangwuzuoQTY = DoFormatLeftQTY(value); } } ////// 特等座 /// public string TedengzuoQTY { get { return tedengzuoQTY; } set { tedengzuoQTY = DoFormatLeftQTY(value); } } ////// 一等座 /// public string YidengzuoQTY { get { return yidengzuoQTY; } set { yidengzuoQTY = DoFormatLeftQTY(value); } } ////// 二等座 /// public string ErdengzuoQTY { get { return erdengzuoQTY; } set { erdengzuoQTY = DoFormatLeftQTY(value); } } ////// 高级软卧 /// public string GaojiruanwoQTY { get { return gaojiruanwoQTY; } set { gaojiruanwoQTY = DoFormatLeftQTY(value); } } ////// 软卧 /// public string RuanwoQTY { get { return ruanwoQTY; } set { ruanwoQTY = DoFormatLeftQTY(value); } } ////// 硬卧 /// public string YingwoQTY { get { return yingwoQTY; } set { yingwoQTY = DoFormatLeftQTY(value); } } ////// 软座 /// public string RuanzuoQTY { get { return ruanzuoQTY; } set { ruanzuoQTY = DoFormatLeftQTY(value); } } ////// 硬座 /// public string YingzuoQTY { get { return yingzuoQTY; } set { yingzuoQTY = DoFormatLeftQTY(value); } } ////// 无座 /// public string WuzuoQTY { get { return wuzuoQTY; } set { wuzuoQTY = DoFormatLeftQTY(value); } } ////// 发时 /// public string FromTime { get { return fromTime; } set { fromTime = value; } } ////// 到时 /// public string ArriveTime { get { return arriveTime; } set { arriveTime = value; } } ////// 历时 /// public string ThroughTime { get { return throughTime; } set { throughTime = value; } } private string DoFormatLeftQTY(string qty) { if (string.IsNullOrEmpty(qty)) { return "已售完"; } try { if (!qty.Contains("-") && Convert.ToInt32(qty) > 0) { return qty; } } catch{ } if (qty.Contains("无")) { return "无此席别"; } return "已售完"; } }
public class TrainTicketLeftQuery { ///界面代码:/// 余票返回字符串 /// /// /// /// /// ///private static string DoGetTrainTicketLeft(string fromTime, string fromStation, string arriveStation, string trainTeleCode) { string result = string.Empty; try { //0-时间 1-出发站 2-达到 3-车次 string trainTicketLeftUrl = @"http://dynamic.12306.cn/otsquery/query/queryRemanentTicketAction.do?method=queryLeftTicket&orderRequest.train_date={0}&orderRequest.from_station_telecode={1}&orderRequest.to_station_telecode={2}&orderRequest.train_no={3}&trainPassType=QB&trainClass=QB%23D%23Z%23T%23K%23QT%23&includeStudent=00&seatTypeAndNum=&orderRequest.start_time_str=00%3A00--24%3A00"; trainTicketLeftUrl = string.Format(trainTicketLeftUrl, fromTime, fromStation, arriveStation, trainTeleCode); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(trainTicketLeftUrl); request.Accept = @"application/json, text/javascript, */*"; request.UserAgent = @"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"; request.Referer = @"http://dynamic.12306.cn/otsquery/query/queryRemanentTicketAction.do?method=init"; request.ContentType = @"application/x-www-form-urlencoded"; request.Method = "GET"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { result = reader.ReadToEnd(); } } } catch { } return result; } /// /// 读取余票 /// /// ///public static ObservableCollection DoQueryTrainTicketLeftCollects(string fromTime, string fromStation, string arriveStation, string trainTeleCode) { string trainTicketLeftContent = DoGetTrainTicketLeft(fromTime, fromStation, arriveStation, trainTeleCode); ObservableCollection trainTicketLeftCollecs = new ObservableCollection (); try { var stations = JsonConvert.DeserializeObject (trainTicketLeftContent); Regex regex = new Regex(@","); string[] stationList = regex.Split(stations.datas); bool firstitem = true; for (int i = 0; i < stationList.Length; i++) { if (i == 0) { continue; } string[] sigleStation = stationList[0].Split(','); } foreach (string item in stationList) { if (firstitem) { firstitem = false; continue;//第一项不要 } string[] sigleStation = item.Split(','); TrainTicketLeftModel leftModel = new TrainTicketLeftModel(); string fstationContent = sigleStation[0].Replace(@" ", string.Empty); Regex fregex = new Regex(@" "); string[] fstation = fregex.Split(fstationContent); leftModel.FromStation = fstation[0].Substring(fstation[0].LastIndexOf('>') + 1); leftModel.FromTime = fstation[1]; string astationContent = sigleStation[1].Replace(@" ", string.Empty); Regex aregex = new Regex(@" "); string[] astation = aregex.Split(astationContent); leftModel.ArriveStation = astation[0].Substring(astation[0].LastIndexOf('>') + 1); leftModel.ArriveTime = astation[1]; leftModel.ThroughTime = sigleStation[2]; leftModel.ShangwuzuoQTY = sigleStation[3]; leftModel.TedengzuoQTY = sigleStation[4]; leftModel.YidengzuoQTY = sigleStation[5]; leftModel.ErdengzuoQTY = sigleStation[6]; leftModel.GaojiruanwoQTY = sigleStation[7]; leftModel.RuanwoQTY = sigleStation[8]; leftModel.YingwoQTY = sigleStation[9]; leftModel.RuanzuoQTY = sigleStation[10]; leftModel.YingzuoQTY = sigleStation[11]; leftModel.WuzuoQTY = sigleStation[12]; trainTicketLeftCollecs.Add(leftModel); } } catch { } return trainTicketLeftCollecs; } } [DataContract] public class StationOfficialInfo { [DataMember] public string datas { get; set; } [DataMember] public string time { get; set; } }
后台代码:
///结果:/// MainWindow.xaml 的交互逻辑 /// public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainWindow_Loaded); } void MainWindow_Loaded(object sender, RoutedEventArgs e) { string date = DateTime.Now.AddDays(3).ToString(@"yyyy-MM-dd"); this.txtDate.Text = date; this.txtStartStation.Text = @"广州"; this.txtArriveStation.Text = @"西安"; InitialRandCode(); } private void InitialRandCode() { //初始化验证码 string randCodeImageUrl = TrainTicketPriceQuery.DoGetTrainTicketPriceRandCodeImage(); if (!string.IsNullOrEmpty(randCodeImageUrl)) { ImageSource src = (ImageSource)(new ImageSourceConverter().ConvertFromString(randCodeImageUrl)); this.imageRandCode.Source = src; } } ////// 开始查询 /// /// /// private void BtnQueryPrice_Click(object sender, RoutedEventArgs e) { string startStation = this.txtStartStation.Text.Trim(); string arriveStation = this.txtArriveStation.Text.Trim(); string randCode = this.txtRandCode.Text.Trim(); string startDate = this.txtDate.Text; if (string.IsNullOrEmpty(startStation) || string.IsNullOrEmpty(arriveStation) || string.IsNullOrEmpty(randCode) || string.IsNullOrEmpty(startDate)) { MessageBox.Show("参数不完整,请重新填写!"); return; } DateTime fromDate = DateTime.Parse(startDate); var priceCollects= TrainTicketPriceQuery.DoQueryTrainTicketPriceInfoCollects(DateTime.Now.AddDays(4), startStation, arriveStation, randCode); if (priceCollects == null || priceCollects.Count <= 0) { MessageBox.Show(@"读取车票价格失败!"); } else { MessageBox.Show(@"读取车票价格成功!"); } } private void ButtonRandCode_Click(object sender, RoutedEventArgs e) { InitialRandCode(); } private void BtnQueryLeft_Click(object sender, RoutedEventArgs e) { var leftCollects = TrainTicketLeftQuery.DoQueryTrainTicketLeftCollects(DateTime.Now.AddDays(3).ToString("yyyy-MM-dd"), "GZQ", "BJP", ""); if (leftCollects == null || leftCollects.Count <= 0) { MessageBox.Show(@"读取车票余票失败!"); } else { MessageBox.Show(@"读取车票余票成功!"); } } }
界面
票价结果
余票结果: