導(dǎo)入需要的模塊
import requests
import re
import ssl
a = input("出發(fā)地:")
b = input("目的地:")
c = input("出發(fā)日期:")
#表示忽略未經(jīng)核實(shí)的SSL證書認(rèn)證,防止因?yàn)閔ttps認(rèn)證導(dǎo)致訪問失敗
ssl._create_default_https_context=ssl._create_unverified_context
當(dāng)然我們還有另一種的方法繞過ssl認(rèn)證
當(dāng)網(wǎng)頁需要ssl驗(yàn)證的時(shí)候,正常爬取會(huì)出現(xiàn)SSLError報(bào)錯(cuò),表示證書錯(cuò)誤,我們通過設(shè)置 verity 參數(shù) 為 False 來避免這個(gè)錯(cuò)誤
import requests
a = requests.get(“[https://www.12306.cn](https://www.12306.cn)”,verify=False)
print(a.status_code)
不過我們會(huì)發(fā)現(xiàn)一個(gè)警告,我們可以通過日志捕獲警告的方式,屏蔽警告
import requests
import logging
logging.captureWarnings(True)
a = requests.get(“[https://www.12306.cn](https://www.12306.cn)”,verify=False)
print(a.status_code)
構(gòu)造requests請求包

由于12306列車查詢界面使用的是GET傳輸,所以我們直接構(gòu)造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)#按正則表達(dá)式匹配
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] #將城市名轉(zhuǎn)換為城市代碼
to_station = text[to_station_name]
except:
date,from_station,to_station = '--','--','--'
#API URL構(gòu)造
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)
發(fā)送請求,并將爬取到的信息進(jìn)行整理
#獲取車次信息
def query_train_info(url,text):
#headers部分請務(wù)必參照自己的瀏覽器填寫,以下參數(shù)少一個(gè)都會(huì)被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數(shù)據(jù)中data字段的result結(jié)果
raw_trains = r.json()['data']['result']
for raw_train in raw_trains:
#循環(huán)遍歷每輛列車的信息
data_list = raw_train.split('|')
#車次號(hào)碼
train_no = data_list[3]
#出發(fā)站
from_station_code = data_list[6]
from_station_name = a
#終點(diǎn)站
to_station_code = data_list[7]
to_station_name = b
#出發(fā)時(shí)間
start_time = data_list[8]
#到達(dá)時(shí)間
arrive_time = data_list[9]
#總耗時(shí)
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 '--'
# 打印查詢結(jié)果
info = (
'-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n'
'|車次:{} | 出發(fā)站:{} | 目的地:{} | 出發(fā)時(shí)間:{} | 到達(dá)時(shí)間:{} | 消耗時(shí)間:{} | '
'| 一等座:「{}」| 二等座:「{}」| 軟臥:「{}」| 硬臥:「{}」| 硬座:「{}」| 無座:「{}」|\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)
#循環(huán)查詢,知道查詢到想要的車次有票終止
'''while True:
time.sleep(1)#刷票頻率
if query_train_info(url,text):
break'''
query_train_info(url,text)
效果如下
