Python Requests 12306列车车次信息爬取


导入需要的模块

import  requests
import  re
import ssl

a = input("出发地:")
b = input("目的地:")
c = input("出发日期:")

#表示忽略未经核实的SSL证书认证,防止因为https认证导致访问失败
ssl._create_default_https_context=ssl._create_unverified_context

当然我们还有另一种的方法绕过ssl认证
当网页需要ssl验证的时候,正常爬取会出现SSLError报错,表示证书错误,我们通过设置 verity 参数 为 False 来避免这个错误

import requests

a = requests.get(“[https://www.12306.cn](https://www.12306.cn)”,verify=False)
print(a.status_code)

不过我们会发现一个警告,我们可以通过日志捕获警告的方式,屏蔽警告

import requests
import logging

logging.captureWarnings(True)

a = requests.get(“[https://www.12306.cn](https://www.12306.cn)”,verify=False)
print(a.status_code)

构造requests请求包


由于12306列车查询界面使用的是GET传输,所以我们直接构造url

def get_station():
    #12306的城市名和城市代码js文件和URL
    url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9143'
    r = requests.get(url)
    pattern = u'([\u4e00-\u9fa5]+)\|([A-Z]+)'#\u4e00-\u9fa5是所有汉字的Unicode编码范围
    result = re.findall(pattern,r.text)#按正则表达式匹配
    station=dict(result)
    #print(station)
    return station

#生成查询的URL
def get_query_url(text):
    #城市名代码查询字典
    #key:城市名 value:城市代码,如:{'北京北': 'VAP', '北京东': 'BOP', '北京': 'BJP'}
    try:
        from_station_name= a
        to_station_name= b
        date= c
        from_station = text[from_station_name] #将城市名转换为城市代码
        to_station = text[to_station_name]
    except:
        date,from_station,to_station = '--','--','--'
    #API URL构造
    url = (
        'https://kyfw.12306.cn/otn/leftTicket/query?'
        'leftTicketDTO.train_date={}&'
        'leftTicketDTO.from_station={}&'
        'leftTicketDTO.to_station={}&'
        'purpose_codes=ADULT'
    ).format(date,from_station,to_station)
    return url
    #print (url)

发送请求,并将爬取到的信息进行整理

#获取车次信息
def query_train_info(url,text):
    #headers部分请务必参照自己的浏览器填写,以下参数少一个都会被12306判定为爬虫
    headers = {
        'Host':'kyfw.12306.cn',
        'Referer': 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=%E6%B2%88%E9%98%B3,SYT&ts=%E9%9E%8D%E5%B1%B1,AST&date=2020-06-24&flag=N,Y,Y',
        'Pragma': 'no-cache',
        'Accept': '*/*',
        'Connection': 'keep-alive',
        'Accept-Language': 'zh-cn',
        'Accept-Encoding': 'br, gzip, deflate',
        'Cookie':'RAIL_DEVICEID=JPQw57vzB656fgPjLHskLw9ssSt400F26k4-Z1PKlzY-Zn5nk1sjEWvuyBUCsq2Tc8FFmYD4OXSTlTxjm0tOf_0ZDzbjqMRIzwTUA-bGOmVccwg9K4x7zj7ZTrrDPsjvsXeUeQjdylKWVNREuZAZ46VS0nViglny; RAIL_EXPIRATION=1592564633156; BIGipServerindex=1138295050.43286.0000',
        'If-Modified-Since': '0',
        'Cache-Control': 'no-cache',
        'X-Requested-With': 'XMLHttpRequest',
        'User-Agent':
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36'
}
    try:
        r = requests.get(url,headers = headers)
        #print(r.json())
        #获取返回json数据中data字段的result结果
        raw_trains = r.json()['data']['result']
        for raw_train in raw_trains:
            #循环遍历每辆列车的信息
            data_list = raw_train.split('|')

            #车次号码
            train_no = data_list[3]
            #出发站
            from_station_code = data_list[6]
            from_station_name = a
            #终点站
            to_station_code = data_list[7]
            to_station_name = b
            #出发时间
            start_time = data_list[8]
            #到达时间
            arrive_time = data_list[9]
            #总耗时
            time_fucked_up = data_list[10]
            #一等座
            first_class_seat = data_list[31] or '--'
            #二等座
            second_class_seat = data_list[30] or '--'
            # 软卧
            soft_sleep = data_list[23] or '--'
            # 硬卧
            hard_sleep = data_list[28] or '--'
            # 硬座
            hard_seat = data_list[29] or '--'
            # 无座
            no_seat = data_list[26] or '--'
            # 打印查询结果
            info = (
                '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n'
                '|车次:{} | 出发站:{} | 目的地:{} | 出发时间:{} | 到达时间:{} | 消耗时间:{} | '
                '| 一等座:「{}」| 二等座:「{}」| 软卧:「{}」| 硬卧:「{}」| 硬座:「{}」| 无座:「{}」|\n'
                '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'.format(train_no,from_station_name,to_station_name,start_time,arrive_time,
                                     time_fucked_up,first_class_seat,
                                     second_class_seat,soft_sleep,hard_sleep,hard_seat,no_seat)
            )
            print(info)
            
    except Exception as e:
        print(e)

if __name__ == '__main__':
    text = get_station()
    url = get_query_url(text)
     #循环查询,知道查询到想要的车次有票终止
    '''while True:
        time.sleep(1)#刷票频率
        if query_train_info(url,text):
            break'''
    query_train_info(url,text)

效果如下

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。