Python爬⾍技术及PyQt5界⾯编程实现12306⽕车票查询
界⾯设计
界⾯设计使⽤了Qt 设计师(使⽤⽅法请⾃⾏探索)实现拖拽⽣成:
设计保存后会⽣成⼀个后缀位ui的⽂件,将这个⽂件放进项⽬中,此时我们还不能直接运⾏这个⽂件,也看不到界⾯,此时在PyCharm中做如下配置:
程序:所在的⽬录
实参:-m PyQt5.uic.pyuic$FileName$ -o $FileNameWithoutExtension$.py
⼯作⽬录:$FileDir$
添加好之后返回项⽬界⾯,右键刚才的ui后缀⽂件
选择External Tools—>PyUIC
执⾏后同级⽬录下会⽣成⼀个同名的py⽂件
此时的py⽂件运⾏是不能出现界⾯的,在刚才⽣成的py⽂件中添加如下代码:
# 显⽰主窗体
def show_MainWindow():
app = QtWidgets.QApplication(sys.argv)# 实例化QApplication,作为GUI主程序⼊⼝
MainWindow = QtWidgets.QMainWindow()# 创建QMainWindow
ui = Ui_MainWindow()# 实例UI类
ui.setupUi(MainWindow)# 设置窗体UI
MainWindow.show()# 显⽰窗体
<_())# 当窗⼝创建完成后需要结束主循环
if __name__ =='__main__':
show_MainWindow()# 调⽤显⽰窗体的⽅法
此时则可以实现运⾏出界⾯。(设计时的图⽚等路径可能需要更改才能正确显⽰)
技术实现
1、12306⽹页车票查询分析
此处需要具备爬⾍知识
经过分析得知:
这个链接就是获取车站的链接(输⼊车站名时怎么进⾏查询的?分析发现是根据 中⽂名对应的英⽂缩写,⽽这个链接就是获取这种对应关系的)
获取车站信息代码:
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
File Name:    get_stations.py
Author:        lenovo
Date:        2021/12/20
Create by:    PyCharm
Description :  获取车站信息---中⽂和对应英⽂缩写
-------------------------------------------------
"""
import os
python怎么读取json文件
import re
import requests
"""
1、”utf-8“ 是以字节为编码单元,它的字节顺序在所有系统中都是⼀样的,
没有字节序问题,因此它不需要BOM,所以当⽤"utf-8"编码⽅式读取带有BOM的⽂件时,
它会把BOM当做是⽂件内容来处理, 也就会发⽣类似上边的错误.
2、“utf-8-sig"中sig全拼为 signature 也就是"带有签名的utf-8”,
因此"utf-8-sig"读取带有BOM的"utf-8⽂件时"会把BOM单独处理,
与⽂本内容隔离开,也是我们期望的结果.
"""
def getStation():
# 发送请求获取所有车站名称,通过输⼊的站名称转化查询地址的参数
url ='kyfw.12306/otn/resources/js/framework/station_name.js?station_version=1.9050'    response = (url, verify=True)# 请求并进⾏验证
stations = re.findall(u'([\u4e00-\u9fa5]+)\|([A-Z]+)', )# 获取需要的车站名称
stations =dict(stations)# 转换为dic
stations =str(stations)# 转换为字符串类型否则⽆法写⼊⽂件
write(stations)# 调⽤写⼊⽅法
def write(stations):
if not ists('station/'):# 如果⽂件⽬录不存在则创建
os.makedirs('station/')
with open('','w', encoding='utf_8_sig')as f:# w⽂本写⼊
f.write(stations)
f.close()
def read():
file=open('','r', encoding='utf_8_sig')# 以写模式打开⽂件
data =adline()# 读取⽂件
file.close()
return data
def isStations():
isExist = ists('')# 判断车站⽂件是否存在
return isExist
获取查询结果
# -*- coding: utf-8 -*-
"""
-
------------------------------------------------
File Name:    query_data.py
Author:        lenovo
Date:        2021/12/20
Create by:    PyCharm
Description :  查询车辆信息
-------------------------------------------------
"""
from get_stations import*
'''
5-7 ⽬的地 3  车次 6  出发地 8  出发时间 9  到达时间 10 历时 26 ⽆坐 29 硬座
24 软座 28 硬卧 33 动卧 23 软卧 21 ⾼级软卧 30 ⼆等座 31 ⼀等座 32 商务座特等座
'''
data =[]# ⽤于保存整理好的车次信息
type_data =[]# 保存车次分类后最后的数据
def query(date, from_station, to_station):
"""
根据传⼊的⽇期,起始车站,⽬的车站返回查询结果
:param date: 出发⽇期
:param from_station: 起始车站
:param to_station: ⽬的车站
:return: 查询数据
"""
data.clear()# 清空数据
type_data.clear()# 清空车次分类保存的数据
headers ={
'Cookie':"_uab_collina=163999108472034091142832; JSESSIONID=C5C4C5E7526DC0B7BFC6A5717D1F8380; BIGipServerotn=368050698.24610 .0000; BIGipServerpool_passport=115606026.50215.0000; RAIL_EXPIRATION=1640270981777; RAIL_DEVICEID=lbec11dld1VeM-sTt-5XFnXTNwhNgpC ur_gC8sJjGNMKKBV3uSi0ISD97wfIwWm3kwTRoZUeiv4uB7BtHpBl_bA_6px32mcN8aNpC6MMoP9VmpMINrZxxaQM_KNWIV7rZ7mND7kKrQxv5MTYmO Mh6-I-KYFHkTvj; guidesStatus=off; highContrastMode=defaltMode; cursorStatus=off; route=495c805987d0f5c8c84b14f60212447d; _jc_save_fromDate=2 021-12-20; _jc_save_toDate=2021-12-20; _jc_save_wfdc_flag=dc; _jc_save_fromStation=%u5317%u4EAC%2CBJP; _jc_save_toStation=%u4E0A%u6D77 %2CSHH",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0. 1054.62"
}
# 查询请求地址
url ='kyfw.12306/otn/leftTicket/ain_date={}&leftTicketDTO.from_station={}&_station={}&purpose_codes =ADULT'.format(
date, from_station, to_station)
# 发送查询请求
response = (url=url, headers=headers)
# # 将json数据转换为字典类型,通过键值对取数据
if response.status_code !=200:# 直接返回空
return data
result = response.json()['data']['result']
# for i in result:
#    print(i)
if isStations():
stations =eval(read())# 读取所有车站并转换为dic类型
if len(result)!=0:# 判断返回数据是否为空
for i in result:
# # 分割数据并添加到列表中
tmp_list = i.split('|')
# 因为查询结果中出发站和到达站为站名的缩写字母,所以需要在车站库中到对应的车站名称
from_station =list(stations.keys())[list(stations.values()).index(tmp_list[6])]
to_station =list(stations.keys())[list(stations.values()).index(tmp_list[7])]
# 创建座位数组,由于返回的座位数据中含有空既“”,所以将空改成--这样好识别
seat =[tmp_list[3], from_station, to_station, tmp_list[8], tmp_list[9], tmp_list[10], tmp_list[32],
tmp_list[31], tmp_list[30], tmp_list[21], tmp_list[23], tmp_list[33], tmp_list[28],
tmp_list[24], tmp_list[29], tmp_list[26]]
newSeat =[]
# 循环将座位信息中的空即“”,改成--这样好识别
for s in seat:
if s =="":
s ="--"
else:
s = s
newSeat.append(s)# 保存新的座位信息
data.append(newSeat)
return data  # 返回整理好的车次信息
# 获取⾼铁信息的⽅法
def g_vehicle():
if len(data)!=0:
for g in data:# 循环所有⽕车数据
i = g[0].startswith('G')# 判断车次⾸字母是不是⾼铁
if i:# 如果是将该条信息添加到⾼铁数据中
type_data.append(g)
# 移除⾼铁信息的⽅法
def r_g_vehicle():
if len(data)!=0and len(type_data)!=0:
for g in data:
i = g[0].startswith('G')
if i:# 移除⾼铁信息
ve(g)
# 获取动车信息的⽅法
def d_vehicle():
if len(data)!=0:
for d in data:# 循环所有⽕车数据
i = d[0].startswith('D')# 判断车次⾸字母是不是动车
if i ==True:# 如果是将该条信息添加到动车数据中                type_data.append(d)
# 移除动车信息的⽅法
def r_d_vehicle():
if len(data)!=0and len(type_data)!=0:
for d in data:
i = d[0].startswith('D')
if i ==True:# 移除动车信息
ve(d)
# 获取直达车信息的⽅法
def z_vehicle():
if len(data)!=0:
for z in data:# 循环所有⽕车数据
i = z[0].startswith('Z')# 判断车次⾸字母是不是直达
if i ==True:# 如果是将该条信息添加到直达数据中                type_data.append(z)
# 移除直达车信息的⽅法
def r_z_vehicle():
if len(data)!=0and len(type_data)!=0:
for z in data:
i = z[0].startswith('Z')
if i ==True:# 移除直达车信息
ve(z)
# 获取特快车信息的⽅法
def t_vehicle():
if len(data)!=0:
for t in data:# 循环所有⽕车数据
i = t[0].startswith('T')# 判断车次⾸字母是不是特快
if i ==True:# 如果是将该条信息添加到特快车数据中                type_data.append(t)
# 移除特快车信息的⽅法