我们去买车票不可能输入城市的英文代码,我们都是输入城市的中文名称,然后直接查询,下单。所以我们需要将输入的中文名称转为服务器认识的英文编码。
https://kyfw.12306.cn/otn/leftTicket/init
https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9051
需要将该js文件下载下来,可以通过正则来提取出中文名称和对应的英文编号。从而在查票和后续的下单中能够使用到。
import requests
import bs4
import logging
import os
def getStationNamesVersion():
# 获取 station_names.js 这个文件最新的版本号
logging.captureWarnings(True)
url = "https://kyfw.12306.cn/otn/leftTicket/init"
station_name_version = "" # 先初始化为 0 , 防止没有获取到的时候不能正常返回
response = requests.get(url, verify=False)
content = response.text.encode("UTF-8")
soup = bs4.BeautifulSoup(content, "html.parser")
scripts = soup.findAll("script")
srcs = [] # 保存 HTML 中所有的 script 标签的 src 属性
for i in scripts:
try: # 这里使用 try 是因为有的 script 标签并没有 src 这个属性
src = i['src']
srcs.append(src)
except:
pass
for i in srcs: # 这里设计地比较有扩展性 , 如果还要获取别的某个文件的版本 , 只需要在循环中添加判断即可
if "station_name" in i: # 找到含有 station_names 的一条 src
station_name_version = i.split("station_version=")[1] # 截取版本号
# print "成功获取到车站信息版本 :" , station_name_version # 打印日志
return station_name_version
def getUrlForStationNames(station_name_version):
# 构建用于下载 station_names.js 这个文件的地址
return "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=" + station_name_version
def downloadFile(url, filename):
#下载文件并保存到本地
logging.captureWarnings(True)
f = open(filename, "a",encoding='GBK')
f.write(requests.get(url, verify=False).text)
f.close()
# 获取官网的这个文件的版本
print("正在获取官网的火车站信息文件版本...")
station_names_version = getStationNamesVersion()
print("获取成功 !")
print("官网版本号 : [", station_names_version, "]")
# 比对本地文件
print("正在获取本地缓存文件文件名...")
local_file_name = ""
local_file_version = ""
for filename in os.listdir("./"):
if filename.endswith("_station_names"):
local_file_name = filename
if local_file_name != "":
print("获取成功 ! 本地文件名 : [", local_file_name, "]")
print("正在解析本地文件版本号...")
local_file_version = local_file_name.split("_")[0]
print("本地版本号 : [", local_file_version, "]")
else:
print("本地没有缓存文件 , 准备开始下载...")
# 下载文件 , 保存文件名以版本开始 (便于下次运行的时候比对)
if local_file_version == "":
print("官网火车站文件更新 , 正在下载...")
downloadFile(getUrlForStationNames(station_names_version),
station_names_version + "_" + "station_names")
else:
if local_file_version != station_names_version:
print("官网火车站文件更新 , 正在下载...")
downloadFile(getUrlForStationNames(station_names_version),
station_names_version + "_" + "station_names")
else:
print("本地文件已最新 , 直接使用!")
def getStationCodes(station_name):
results =[]
# 读取文件
station_names = open("./" + station_names_version + "_" + "station_names", "r",encoding='GBK')
content = station_names.read()
station_names.close()
content = content[20:-2] # 去掉多余的 js 关键字 , 只提取出字符串内容
stations = content.split("@")[1:] # 由于这个文件开头就是 '@' , 因此需要去掉第一个元素
for station in stations:
fields = station.split("|")
# station_name_pinyin_simple = fields[0]
station_name_standard = fields[1]
station_code = fields[2]
# station_name_pinyin = fields[3]
# station_name_pinyin_simple_fuzz = fields[4]
# station_num = fields[5]
if station_name==station_name_standard:
# results=station_code
results.append({"station_code": station_code, "station_name": station_name_standard})
return results
def printStationInfo(station_info):
for result in station_info:
print("[ %s ] -> [ %s ]" % (result["station_name"], result["station_code"]))
printStationInfo(getStationCodes('长沙'))
运行效果:
可以看到长沙的对应英文编号CSQ,其他城市一样,只需改动代码即可,同时还可以转拼音...完成转码后,可以在需要的时候使用。