您的位置:首页 > 理论基础 > 计算机网络

C#利用HttpWebRequest、HttpWebResponse调用12306接口,实现登录、查票、买票。

2017-10-14 17:08 856 查看
【免责申明】本文只为学习使用,若有用作商业、其他行为,与本人无关。

使用工具

- UI bootstrap

- 后台C#

- 插件 datetimepicker.js,select.js

UI界面效果预览









UI界面源码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">

<title>火车抢票系统</title>
<link href="css/bootstrap.min.css" rel="stylesheet" />
<link href="css/bootstrap-datetimepicker.min.css" rel="stylesheet" />
<link href="css/bootstrap-select.min.css" rel="stylesheet" />
<style>
body{
width:90%;
margin:0 5%;
}
table th{
text-align:center;
}
td{
text-align:center;
}

</style>
</head>
<body>
<nav class="navbar navbar-default ">
<div class="container-fluid">
<p class="navbar-text navbar-right" style="padding-right:5%;"> <a href="#" class="navbar-link" onclick="Login()"> 登录 </a><a href="#" class="navbar-link" onclik="LoginOut()"> 退出 </a></p>
</div>
</nav>
<form class="form-horizontal" >
<div class="form-group">
<label class="col-md-1 control-label">出发地</label>
<div class="col-md-2">
<select class="selectpicker" data-live-search="true" id="FromStation">

</select>
</div>
<label class="col-md-1 control-label">目的地</label>
<div class="col-md-2 ">
<select class="selectpicker" data-live-search="true" id="ToStation">
</select>
</div>
<label class="col-md-1 control-label">出发日</label>
<div class="col-md-2">
<input type="text" class="form-control" id="txtTranDate" placeholder="请输入出发日期">
</div>
<div class="col-md-3">
<button type="button" class="btn btn-primary " id="btnSearch">查询</button>
</div>
</div>
</form>
<div>
<table class="table table-bordered table-hover" >
<thead style="background-color:turquoise"><tr><th>车次</th><th>出发站<br />到达站</th><th>出发时间<br />到达时间</th><th>历时</th><th>商务座<br />特等座</th><th>一等座</th><th>二等座</th><th>高级<br />软卧</th><th>软卧</th><th>动卧</th><th>硬卧</th><th>软座</th><th>硬座</th><th>无座</th><th>其他</th><th>备注</th></tr></thead>
<tbody id="tbTranContent"></tbody>
</table>
</div>
<script src="scripts/jquery-1.11.1.min.js"></script>
<script src="scripts/bootstrap.min.js"></script>

<script src="scripts/bootstrap-datetimepicker.min.js" ></script>
<script src="scripts/locales/bootstrap-datetimepicker.zh-CN.js" charset="utf-8"></script>

<script src="scripts/bootstrap-select.min.js"></script>
<script src="scripts/layer/layer.js"></script>

<script src="scripts/index.js"></script>
</body>

</html>


后台

主要的功能查询火车票、查询到站信息、查询价格、获取验证码、校验验证码、校验密码

主要的技术还是利用HttpWebRequest、HttpWebResponse来调用12306的接口。

登录界面



 获取验证码接口:

调用的12306的接口获取文件流,然后出入二进制流。

void GetValidateImg(HttpContext context)
{
#region 获取登录验证码
string url = "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand";

Stream stream = GetStreamByGet(url);
if (stream != null)
{
List<byte> bytes = new List<byte>();
int i = stream.ReadByte();
while (i != -1)
{
bytes.Add((byte)i);
i = stream.ReadByte();
}

context.Response.Clear();
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(bytes.ToArray());

}
#endregion
}


校验验证码:12306的验证码是290px*190px的图片,每个照片分为8个小的图片。12306根据点击小图片的相对坐标。例如第二张小图片相对于整张的坐标(左上角为0,0)为50,90,。到时候post请求时候带的参数就是answer=50,90。

void ValidateCode(HttpContext context)
{
#region 校验验证码
string answer = "";
if (!string.IsNullOrEmpty(context.Request["answer"]))
answer = context.Request["answer"];

string url = "https://kyfw.12306.cn/passport/captcha/captcha-check";//
string result = GetValidhtmlByPost(url, "answer=" + answer + "&login_site=E&rand=sjrand");

context.Response.Write(result);
context.Response.End();
#endregion
}


登陆

登陆需要post参数(username,password,appid)

void Login(HttpContext context)
{
#region 登录
string username = "";
if (!string.IsNullOrEmpty(context.Request["username"]))
username = context.Request["username"];

string password = "";
if (!string.IsNullOrEmpty(context.Request["password"]))
password = context.Request["password"];

string url = "https://kyfw.12306.cn/passport/web/login";
string result = GetValidhtmlByPost(url, "username=" + username + "&password="+ password + "&appid=otn");

context.Response.Write(result);
context.Response.End();
#endregion
}


HttpWebRequest 模拟get请求:

因为12306是Https,所以有安全证书,和一般http请求有一些小的区别。

//回调验证证书问题
private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
// 总是接受
return true;
}
/// <summary>
/// get请求(有证书验证)
/// </summary>
/// <param name="Url">URL</param>
/// <returns></returns>
private string GetValidhtmlByGet(string Url)
{
HttpWebRequest webRequest;
HttpWebResponse webResponse;
try
{
//这一句一定要写在创建连接的前面。使用回调的方法进行证书验证。
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);

b080
ServicePointManager.CheckCertificateRevocationList = true;

webRequest = (HttpWebRequest)WebRequest.Create(Url);
webRequest.Method = "GET";
webRequest.Accept = "*/*";

// 获取对应HTTP请求的响应
webResponse = (HttpWebResponse)webRequest.GetResponse();
// 获取响应流
Stream responseStream = webResponse.GetResponseStream();
// 对接响应流(以"utf-8"字符集)
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
string result = reader.ReadToEnd();
reader.Close();
return result;

}
catch (Exception ex)
{
return "";
}

}

/// <summary>
/// 获取文件流
/// </summary>
/// <param name="Url"></param>
/// <returns></returns>
private Stream GetStreamByGet(string Url)
{
HttpWebRequest webRequest;
HttpWebResponse webResponse;
cookie = new CookieContainer();
try
{
//这一句一定要写在创建连接的前面。使用回调的方法进行证书验证。
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);
ServicePointManager.CheckCertificateRevocationList = true;

webRequest = (HttpWebRequest)WebRequest.Create(Url);
webRequest.Method = "GET";
webRequest.Accept = "*/*";
webRequest.CookieContainer = cookie;
// 获取对应HTTP请求的响应
webResponse = (HttpWebResponse)webRequest.GetResponse();

// 获取响应流
Stream responseStream = webResponse.GetResponseStream();
return responseStream;

}
catch (Exception ex)
{
return null;
}

}

///<summary>
///post请求(有证书验证)
///</summary>
///<param name="URL">url地址</param>
///<param name="strPostdata">发送的数据</param>
///<returns></returns>
public string GetValidhtmlByPost(string url, string strPostData)
{
HttpWebRequest webRequest;
HttpWebResponse webResponse;
try
{
// 这一句一定要写在创建连接的前面。使用回调的方法进行证书验证。
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);
ServicePointManager.CheckCertificateRevocationList = true;

webRequest = (HttpWebRequest)HttpWebRequest.Create(url);

webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.KeepAlive = true;
webRequest.CookieContainer = cookie;

byte[] buffer = Encoding.UTF8.GetBytes(strPostData);
webRequest.ContentLength = buffer.Length;
webRequest.GetRequestStream().Write(buffer, 0, buffer.Length);

webResponse = (HttpWebResponse)webRequest.GetResponse();
StreamReader reader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8);
string result = reader.ReadToEnd();
return result;
}
catch (Exception ex)
{
return ex.Message;
}
}


Demo地址

http://download.csdn.net/download/qq237183141/10024750

关于

技术层面就是HTTPWebRequest、HttpWebResponse,这两个类。

主要是12306业务的逻辑,例如查询火车的json数据很乱,本人也是一个一个对着12306的页面,才一一找到的业务的含义。

希望大家还是买票还是去12306上买,本文只为学习上使用。欢迎大家一起学习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐