Bootstrap

python爬虫——爬取12306火车票信息




前提准备:requests、pandas、threading等第三方库的导入(未下载的先进行下载)
导入库代码

from threading import Thread #多线程库
import requests
import pandas as pd  
import json   #json库



完整步骤

1.在网页找到需要的数据

(1)任意输入出发地——目的地——日期,点击查询(我这里查询的是:2024年7月6日长沙到武汉的票)

(2)打开抓包工具,重新刷新页面

(3)在抓包工具里面找到内容所在页面
在这里插入图片描述

通过比对发现车票数据在这个json页面内容里面,但是内容有点复杂,需要我们自己去提取,经过选择,结果如下:

    result = front_content.json()['data']['result']    #返回json字典数据
    for it in result:
        info_list = it.split("|")  #切割数据,中文转英文
        num = info_list[3]
        start = info_list[8]        #启动时间
        arrive = info_list[9]       #到达时间
        time = info_list[10]        #经历时长
        business_seat = info_list[32]   #高铁商务座
        first_seat = info_list[31]      #高铁一等座
        second_seat = info_list[30]     #高铁二等座
        soft_sleeper = info_list[23]       #火车软卧
        hard_sleeper = info_list[28]       #火车硬卧
        soft_seat = info_list[27]         #火车软座
        hard_seat = info_list[29]        #火车硬座
        none_seat = info_list[26]         #无座







2.爬取网页数据(带负载)

①url前半部分
在这里插入图片描述
②url后半部分负载
在这里插入图片描述


两者结合得到需要的url(带负载,请求头)

    front_url = "https://kyfw.12306.cn/otn/leftTicket/query"
    data = {
       "leftTicketDTO.train_date": time,
       "leftTicketDTO.from_station": start,
       "leftTicketDTO.to_station": end,
       "purpose_codes": "ADULT"
    }
    header = {
        "User Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/"
                     "537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
        "Cookie": ("_uab_collina=171612732780866759993918; JSESSIONID=1753D82C75A9D1B5FD26D74F047D5B2F; _jc_save_wfdc_flag=dc; BIGipServerotn=1373176074.50210.0000; BIGipServerpassport=837288202.50215.0000; guidesStatus=off; highContrastMode=defaltMode; cursorStatus=off; route=c5c62a339e7744272a54643b3be5bf64; BIGipServerportal=3084124426.17183.0000; _jc_save_fromStation=%u957F%u6C99%2CCSQ; "
                   "_jc_save_toStation=%u4E0A%u6D77%2CSHH; _jc_save_fromDate=2024-06-28; _jc_save_toDate=2024-06-28")
    }

    front_content = requests.get(front_url, params=data, headers=header)  #发起requests请求


(注:长沙:CSQ 武汉:WHN,这些城市对应的代码放在文末的json文件里面,需要自取)




3.额外设计


(1)对出发地——目的地——时间,这三个输入增加了一个函数进行判断输入格式或内容是否正确,并返回三个元素组成的列表
#判断函数并且返回出发地——目的地——时间(列表)
def chaxun(city):

    #判断出发地
    while True:
        in_start = input("请输入出发地:\n")
        if in_start not in city.keys():
            print("输入的城市有误,请重新输入:")
            continue
        else:
            break
    #判断目的地
    while True:
        in_end = input("请输入目的地:\n")
        if in_end not in city.keys():
            print("输入的城市有误,请重新输入:")
            continue
        else:
            break
    # 判断输入时间格式
    while True:
        time = input("请输入时间(格式:xxxx.xx.xx):\n")
        if (len(time.split(".")) != 3 or len(time.split(".")[0]) != 4
                or len(time.split(".")[1]) != 2 or len(time.split(".")[2]) != 2):
            print("输入的时间有误,请重新输入:")
            continue
        else:
            break
    time = time.replace('.', '-')
    in_start = city[in_start]
    in_end = city[in_end]
    chaxun_list = [in_start, in_end, time]
    return chaxun_list




(2)对需要查询的动车类型单独增加一个函数,返回动车类型

def the_kind():
    #输入动车类型
    kind_list = ['高铁', '火车', '全部']
    while True:
        kind = input("请输入要查询的类型(高铁/火车/全部):\n")
        if kind in kind_list:
            break
        else:
            continue
    return kind




(3)将结果写入excel文件,结果更加整齐清晰

 #三种类型票 高铁 火车 全部
    content_G = pd.DataFrame(lst_G)
    content_KTZ = pd.DataFrame(lst_KTZ)
    content_all = pd.DataFrame(lst_all)

    if kind == '高铁':
        with pd.ExcelWriter("火车票查询.xlsx",mode="w") as w:
            content_G.to_excel(w, sheet_name="高铁票", index=False)
    elif kind == '火车':
        with pd.ExcelWriter("火车票查询.xlsx", mode="w") as w:
            content_KTZ.to_excel(w, sheet_name="火车票", index=False)
    else:
        with pd.ExcelWriter("火车票查询.xlsx", mode="w") as w:
            content_all.to_excel(w, sheet_name="全部票", index=False)





4.完整代码

from threading import Thread
import requests
import pandas as pd
import json

#导入城市
f2 = open('city.json', 'r')
city = json.load(f2)


#查询函数
def chaxun(city):

    #判断出发地
    while True:
        in_start = input("请输入出发地:\n")
        if in_start not in city.keys():
            print("输入的城市有误,请重新输入:")
            continue
        else:
            break
    #判断目的地
    while True:
        in_end = input("请输入目的地:\n")
        if in_end not in city.keys():
            print("输入的城市有误,请重新输入:")
            continue
        else:
            break
    # 判断输入时间格式
    while True:
        time = input("请输入时间(格式:xxxx.xx.xx):\n")
        if (len(time.split(".")) != 3 or len(time.split(".")[0]) != 4
                or len(time.split(".")[1]) != 2 or len(time.split(".")[2]) != 2):
            print("输入的时间有误,请重新输入:")
            continue
        else:
            break
    time = time.replace('.', '-')
    in_start = city[in_start]
    in_end = city[in_end]
    chaxun_list = [in_start, in_end, time]
    return chaxun_list

#动车类型函数
def the_kind():
    #输入动车类型
    kind_list = ['高铁', '火车', '全部']
    while True:
        kind = input("请输入要查询的类型(高铁/火车/全部):\n")
        if kind in kind_list:
            break
        else:
            continue
    return kind

#爬取并输出函数
def func(time, start, end, kind):

    front_url = "https://kyfw.12306.cn/otn/leftTicket/query"
    data = {
       "leftTicketDTO.train_date": time,
       "leftTicketDTO.from_station": start,
       "leftTicketDTO.to_station": end,
       "purpose_codes": "ADULT"
    }
    header = {
        "User Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/"
                     "537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
        "Cookie": ("_uab_collina=171612732780866759993918; JSESSIONID=1753D82C75A9D1B5FD26D74F047D5B2F; _jc_save_wfdc_flag=dc; BIGipServerotn=1373176074.50210.0000; BIGipServerpassport=837288202.50215.0000; guidesStatus=off; highContrastMode=defaltMode; cursorStatus=off; route=c5c62a339e7744272a54643b3be5bf64; BIGipServerportal=3084124426.17183.0000; _jc_save_fromStation=%u957F%u6C99%2CCSQ; "
                   "_jc_save_toStation=%u4E0A%u6D77%2CSHH; _jc_save_fromDate=2024-06-28; _jc_save_toDate=2024-06-28")
    }

    front_content = requests.get(front_url, params=data, headers=header)
    front_content.encoding = "utf-8"
    front_content.close()    #关闭requests
    result = front_content.json()['data']['result']    #返回json字典数据

    lst_G = [] #高铁信息
    lst_KTZ = [] #火车信息
    lst_all = [] #全部信息

    for it in result:
        info_list = it.split("|")  #切割数据,中文转英文
        num = info_list[3]
        start = info_list[8]        #启动时间
        arrive = info_list[9]       #到达时间
        time = info_list[10]        #经历时长
        business_seat = info_list[32]   #高铁商务座
        first_seat = info_list[31]      #高铁一等座
        second_seat = info_list[30]     #高铁二等座
        soft_sleeper = info_list[23]       #火车软卧
        hard_sleeper = info_list[28]       #火车硬卧
        soft_seat = info_list[27]         #火车软座
        hard_seat = info_list[29]        #火车硬座
        none_seat = info_list[26]         #无座
        dic = {
               "车次": num,
               "启动时间": start,   # 启动时间
               "到达时间": arrive,      #到达时间
               "中途时长": time,        #经历时长
               "商务座": business_seat,  #高铁商务座
               "一等座": first_seat,      #高铁一等座
               "二等座": second_seat,    #高铁二等座
               "软卧": soft_sleeper,       #火车软卧
               "硬卧": hard_sleeper,       #火车硬卧
               "软座": soft_seat,         #火车软座
               "硬座": hard_seat,        #火车硬座
               "无座": none_seat         #无座
        }

    #进行三种分类
        lst_all.append(dic)
        if 'G' in num:
            lst_G.append(dic)
        else:
            lst_KTZ.append(dic)

    #dataframe格式设置
    pd.set_option('display.unicode.ambiguous_as_wide', True)
    pd.set_option('display.unicode.east_asian_width', True)
    pd.set_option('display.max_rows', None)
    pd.set_option('display.max_columns', None)
    pd.set_option('display.width', 100)

    #三种类型票 高铁 火车 全部
    content_G = pd.DataFrame(lst_G)
    content_KTZ = pd.DataFrame(lst_KTZ)
    content_all = pd.DataFrame(lst_all)

    if kind == '高铁':
        with pd.ExcelWriter("火车票查询.xlsx",mode="w") as w:
            content_G.to_excel(w, sheet_name="高铁票", index=False)
    elif kind == '火车':
        with pd.ExcelWriter("火车票查询.xlsx", mode="w") as w:
            content_KTZ.to_excel(w, sheet_name="火车票", index=False)
    else:
        with pd.ExcelWriter("火车票查询.xlsx", mode="w") as w:
            content_all.to_excel(w, sheet_name="全部票", index=False)

if __name__ ==  '__main__':
    lis = chaxun(city)
    in_start = lis[0]
    in_end = lis[1]
    time = lis[2]
    kind = the_kind()
    func(time, in_start, in_end, kind)
    





5.结果

在这里插入图片描述
在这里插入图片描述


额外:城市代码的city.json文件在本人主页的资源里面,可以直接免费下载保存

;