2019年1月3日
Jerry
4864
2019年6月22日
想给博客新增一个在线程序模块,可以集成一些自己搞的小程序或者好用的小工具。这里拿测试博客搞一下余票查询。效果截图在文章最后。
1、创建、添加APP
在mysite中新建了一个tools APP,并添加到全局settings.py,方法之前文章有写。
2、新增url路由
新增两个url路由:
1)/tools/ticketleft/init/ 用来做余票查询的主页
2)/tools/ticketleft/init/ 用来做余票查询的post URL
urlpatterns = [
path('ticketleft/init/', ticketleft_init_view, name='ticketleft_init_url'),
path('ticketleft/query/', ticketleft_query_view, name='ticketleft_query_url'),
]
3、新增view视图
新增两个view如下,查询代码跟上篇文章基本一样,只不过多出来一步:把爬出来的结果通过list json数据传到了html页面用于显示。
def ticketleft_init_view(request):
return render(request,'tools/ticketleft_init.html')
@require_POST
def ticketleft_query_view(request):
if request.is_ajax():
from_sta = request.POST.get('from_sta')
to_sta = request.POST.get('to_sta')
train_date = request.POST.get('train_date')
ticket_type = request.POST.get('ticket_type')
url = getUrl(from_sta, to_sta, train_date, ticket_type)
html = requests.get(url)
if html.status_code == 200:
list_All = []
res = html.json()["data"]["result"]
# print(res)
sta_dict = html.json()["data"]["map"] #获得到一个字典 用于站点的汉字和字符标记转换
for data in res:
list_Child = []
list = data.split("|") #分割,获取所有信息填入的list
#print(list)
if list[1]=='列车停运': #根据json 挨个分析
continue
line_no = list[3]
from_sta = list[6]
to_sta = list[7]
start_time = list[8]
stop_time = list[9]
cost_time = list[10]
#字符串 赋值 : or 两个都有值,取第一个,第一个没有值,取第二个
TDZ=list[32] or "--" #特等座
YDZ=list[31] or "--" #一等座
EDZ=list[30] or "--" #二等座
RW=list[23] or "--" #软卧
YW=list[28] or "--" #硬卧
RZ=list[27] or "--" #软座
YZ=list[29] or "--" #硬座
WZ=list[26] or "--" #无座
list_Child.append(line_no)
list_Child.append(sta_dict[from_sta])
list_Child.append(sta_dict[to_sta])
list_Child.append(start_time)
list_Child.append(stop_time)
list_Child.append(cost_time)
list_Child.append(TDZ)
list_Child.append(YDZ)
list_Child.append(EDZ)
list_Child.append(RW)
list_Child.append(YW)
list_Child.append(RZ)
list_Child.append(YZ)
list_Child.append(WZ)
list_All.append(list_Child)
return JsonResponse({'msg':'成功!','res':list_All})
return JsonResponse({'msg':'失败!','url':url})
4、新增模板文件
创建ticketleft_init.html文件用于显示输入框和数据展示,按钮实现类似评论提交的实现,ajax提交,将页面输入的数据给后台用于爬取。
{% extends "blog/base.html" %}
{% load static %}
{% block base_content %}
<style>
.col-center-block {
float: none;
display: block;
margin: 0 auto;
/* margin-left: auto; margin-right: auto; */
}
</style>
<script type="text/javascript">
$(function() {
$("#submit").click(function(){
var from_sta = $("#from_sta").val();
var to_sta = $("#to_sta").val();
var train_date = $("#train_date").val();
var ticket_type = $('input:radio:checked').val();
//从html获取相关字段 html 里面写的data-*, 这里就写 *
var csrf = $(this).data('csrf');
var ajax_url = $(this).data('ajax_url')
//设置post Json字段
var post_data={
"from_sta":from_sta,
"to_sta":to_sta,
"train_date":train_date,
"ticket_type":ticket_type,
};
//清空表格,只剩表头
$("#mytable tr:not(:first)").html("");
$.ajaxSetup({
data:{'csrfmiddlewaretoken': csrf }
});
$.ajax({
url:ajax_url,
type:'post',
data:post_data,
//{#请求成功回调函数#}
success:function (data) {
//alert(data.msg+data.res);
list = data.res;
for(var i=0; i < list.length; i++)
{
trtd="<tr>"
for(var j=0; j < list[i].length; j++)
{
trtd += "<th>" + list[i][j] + "</th>"
}
trtd += "</tr>"
$("#mytable").find('tbody').append(trtd);
}
},
//{#请求失败回调函数#}
error:function (data) {
alert("err "+ data.url);
}
});
});
})
</script>
<div class="container">
<div class="row">
<div class="col-lg-8 col-center-block">
<h4>输入相关信息进行余票查询(截止到 2019-01-03 测试成功)</h4>
<h6>站点URL:'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9088'</h6>
<h6>请求URL:'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=' + date + '&leftTicketDTO.from_station=' + from_sta_code + '&leftTicketDTO.to_station=' + to_sta_code + '&purpose_codes=' + ticket_type</h6>
<input type="text" class="form-control" id="from_sta" placeholder="出发站" required=True><br>
<input type="text" class="form-control" id="to_sta" placeholder="到达站" required=True><br>
<input type="date" class="form-control" id="train_date" placeholder="发车日期" required=True><br>
<input type="radio" checked="checked" name="ticket_type" value="ADULT" />成人票
<input type="radio" name="ticket_type" value="0X00" />学生票
<button class="btn btn-primary pull-right" type="submit" id="submit" data-csrf="{{ csrf_token }}" data-ajax_url="{% url 'tools:ticketleft_query_url' %}">查询</button>
<br><br>
<table class="table table-striped" style="display:block" id="mytable">
<tr>
<th>车次</th>
<th>出发站</th>
<th>到达站</th>
<th>出发时间</th>
<th>到达时间</th>
<th>历时</th>
<th>特等座</th>
<th>一等座</th>
<th>二等座</th>
<th>软卧</th>
<th>硬卧</th>
<th>软座</th>
<th>硬座</th>
<th>无座</th>
</tr>
</table>
</div>
</div>
</div>
{% endblock %}
最后实现的效果如下:
其实还可以搞个定时查询,查询到余票发送邮件提醒等功能。这个纯属学习测试玩玩,毕竟12306就有这个功能。测试中还发现,12306网站会做检测,如果短时间内请求太多次,就会获取不到数据了,过段时间再获取就有能获取到了。
代码上传到GitHub Mysite库。
原创文章,转载请注明出处:
https://jerrycoding.com/article/12306_ticket_left_2
微信
支付宝