python爬取12306火车余票程序(二)网页集成

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

微信
jerry微信赞助
支付宝
jerry支付宝赞助

您尚未登录,暂时无法评论。请先 登录 或者 注册

0 人参与 | 0 条评论