App下載

怎么使用PyQt5實(shí)現(xiàn)帶GUI的爬取車票信息程序

發(fā)呆業(yè)務(wù)愛好者 2021-08-10 17:17:34 瀏覽數(shù) (2651)
反饋

我們常見的爬蟲基本上都是命令行的樣式,對于爬蟲而言這樣頁面就足夠了。但是進(jìn)行數(shù)據(jù)分析的時候這樣的頁面是遠(yuǎn)遠(yuǎn)不夠的。今天我們介紹一個python爬取車票信息的代碼,使用pyqt5實(shí)現(xiàn)GUI頁面的部分。話不多說,快來了解這個項(xiàng)目吧。

1、搭載QT環(huán)境

按win+R輸入 pip install pyqt5 下載QT5 當(dāng)然也可以去Qt的官網(wǎng)的下載 ,使用命令行更快捷方便 所以建議使用命令行 ,去官網(wǎng)下載安裝有它的好處就是不用自己安裝 toosl
作者使用的是pyCharm 完成后期的后臺程序設(shè)置,使用pyCharm 外部工具鏈接把Designer,pyUIC,qrcTopy程序加進(jìn)去

配置qt環(huán)境

2、主窗體設(shè)置

打Qt5主程序設(shè)置主窗體,設(shè)計完成保存為windows
添加到創(chuàng)建好的python項(xiàng)目中,然后選中單擊右鍵-》External toosl-》Py UIC 將ui文件轉(zhuǎn)換成py文件
windows.py

from PyQt5.QtGui import QPalette, QPixmap, QColor


# result = []  # 保存車次分類后最后的數(shù)據(jù)


# UI類
class Ui_MainWindow(object):

    # 設(shè)置UI的方法
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")  # 設(shè)置窗體對象名稱
        MainWindow.resize(960, 786)  # 設(shè)置窗體大小
        MainWindow.setMinimumSize(QtCore.QSize(960, 786))  # 主窗體最小值
        MainWindow.setMaximumSize(QtCore.QSize(960, 786))  # 主窗體最大值
        self.centralwidget = QtWidgets.QWidget(MainWindow)  # 主窗體的widget控件
        self.centralwidget.setObjectName("centralwidget")  # 設(shè)置對象名稱

        # 通過label控件顯示頂部圖片
        self.label_title_img = QtWidgets.QLabel(self.centralwidget)
        self.label_title_img.setGeometry(QtCore.QRect(0, 0, 960, 141))
        self.label_title_img.setObjectName("label_title_img")
        title_img = QPixmap('img/TE3.png')  # 打開頂部位圖
        self.label_title_img.setPixmap(title_img)  # 設(shè)置調(diào)色板

        # 查詢部分的widget
        self.widget_query = QtWidgets.QWidget(self.centralwidget)
        self.widget_query.setGeometry(QtCore.QRect(0, 141, 960, 80))
        self.widget_query.setObjectName("widget_query")
        # 開啟自動填充背景
        self.widget_query.setAutoFillBackground(True)
        palette = QPalette()  # 調(diào)色板類
        palette.setBrush(QPalette.Background, QtGui.QBrush(QtGui.QPixmap('img/bg2.png')))  # 設(shè)置背景圖片
        self.widget_query.setPalette(palette)  # 為控件設(shè)置對應(yīng)的調(diào)色板即可

        # 出發(fā)地與對應(yīng)的編輯框控件
        self.label = QtWidgets.QLabel(self.widget_query)
        self.label.setGeometry(QtCore.QRect(30, 30, 54, 12))
        self.label.setObjectName("label")
        self.textEdit = QtWidgets.QTextEdit(self.widget_query)
        self.textEdit.setGeometry(QtCore.QRect(80, 20, 104, 31))
        font = QtGui.QFont()  # 創(chuàng)建QFont()對象
        font.setPointSize(13)  # 設(shè)置編輯框字體大小的值
        self.textEdit.setFont(font)  # 設(shè)置編輯框字體
        self.textEdit.setObjectName("textEdit")  # 出發(fā)地對應(yīng)編輯框?qū)ο竺Q

        # 目的地與對應(yīng)的編輯框
        self.label_2 = QtWidgets.QLabel(self.widget_query)
        self.label_2.setGeometry(QtCore.QRect(220, 30, 54, 12))
        self.label_2.setObjectName("label_2")
        self.textEdit_2 = QtWidgets.QTextEdit(self.widget_query)
        self.textEdit_2.setGeometry(QtCore.QRect(270, 20, 104, 31))
        font = QtGui.QFont()
        font.setPointSize(13)
        self.textEdit_2.setFont(font)
        self.textEdit_2.setObjectName("textEdit_2")

        # 出發(fā)日與有對應(yīng)的編輯框
        self.label_3 = QtWidgets.QLabel(self.widget_query)
        self.label_3.setGeometry(QtCore.QRect(410, 30, 54, 12))
        self.label_3.setObjectName("label_3")
        self.textEdit_3 = QtWidgets.QTextEdit(self.widget_query)
        self.textEdit_3.setGeometry(QtCore.QRect(460, 20, 104, 31))
        font = QtGui.QFont()
        font.setPointSize(13)
        self.textEdit_3.setFont(font)
        self.textEdit_3.setObjectName("textEdit_3")
        # 查詢按鈕
        self.pushButton = QtWidgets.QPushButton(self.widget_query)
        self.pushButton.setGeometry(QtCore.QRect(610, 20, 91, 31))
        self.pushButton.setObjectName("pushButton")

        # 選擇車次類型的widget
        self.widget_checkBox = QtWidgets.QWidget(self.centralwidget)
        self.widget_checkBox.setGeometry(QtCore.QRect(0, 220, 961, 35))
        self.widget_checkBox.setAutoFillBackground(False)
        self.widget_checkBox.setObjectName("widget_checkBox")
        # 開啟自動填充背景
        self.widget_checkBox.setAutoFillBackground(True)
        palette = QPalette()  # 調(diào)色板類
        palette.setBrush(QPalette.Background, QtGui.QBrush(QtGui.QPixmap('img/bg3.png')))  # 設(shè)置背景圖片
        self.widget_checkBox.setPalette(palette)  # 設(shè)置調(diào)色板控件對應(yīng)的方法即可

        # 顯示車次類型文字
        self.label_type = QtWidgets.QLabel(self.widget_checkBox)
        self.label_type.setGeometry(QtCore.QRect(30, 9, 65, 16))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_type.setFont(font)
        self.label_type.setObjectName("label_type")

        # 選擇高鐵
        self.checkBox_G = QtWidgets.QCheckBox(self.widget_checkBox)
        self.checkBox_G.setGeometry(QtCore.QRect(100, 9, 70, 17))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.checkBox_G.setFont(font)
        self.checkBox_G.setObjectName("checkBox_GC")

        # 選擇動車
        self.checkBox_D = QtWidgets.QCheckBox(self.widget_checkBox)
        self.checkBox_D.setGeometry(QtCore.QRect(258, 9, 63, 17))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.checkBox_D.setFont(font)
        self.checkBox_D.setObjectName("checkBox_D")
        # 選擇直達(dá)
        self.checkBox_Z = QtWidgets.QCheckBox(self.widget_checkBox)
        self.checkBox_Z.setGeometry(QtCore.QRect(415, 9, 63, 17))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.checkBox_Z.setFont(font)
        self.checkBox_Z.setObjectName("checkBox_Z")
        # 選擇特快
        self.checkBox_T = QtWidgets.QCheckBox(self.widget_checkBox)
        self.checkBox_T.setGeometry(QtCore.QRect(572, 9, 63, 17))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.checkBox_T.setFont(font)
        self.checkBox_T.setObjectName("checkBox_T")
        # 選擇快速
        self.checkBox_K = QtWidgets.QCheckBox(self.widget_checkBox)
        self.checkBox_K.setGeometry(QtCore.QRect(730, 9, 63, 17))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.checkBox_K.setFont(font)
        self.checkBox_K.setObjectName("checkBox_K")

        # 通過label控件顯示火車信息圖片
        self.label_train_img = QtWidgets.QLabel(self.centralwidget)
        self.label_train_img.setGeometry(QtCore.QRect(0, 256, 960, 62))
        self.label_train_img.setObjectName("label_train_img")
        train_img = QPixmap('img/bg4.png')  # 打開火車信息位圖
        self.label_train_img.setPixmap(train_img)  # 設(shè)置調(diào)色板
        # 顯示車次信息的列表
        self.tableView = QtWidgets.QTableView(self.centralwidget)
        self.tableView.setGeometry(QtCore.QRect(0, 320, 960, 440))
        self.tableView.setObjectName("tableView")
        self.model = QStandardItemModel()# 創(chuàng)建存儲數(shù)據(jù)的模式
        # 根據(jù)空間自動改變列寬度并且不可修改列寬度
        self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # 設(shè)置表頭不可見
        self.tableView.horizontalHeader().setVisible(False)
        # 縱向表頭不可見
        self.tableView.verticalHeader().setVisible(False)
        # 設(shè)置表格內(nèi)容文字大小
        font = QtGui.QFont()
        font.setPointSize(10)
        self.tableView.setFont(font)
        # 設(shè)置表格內(nèi)容不可編輯
        self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # 垂直滾動條始終開啟
        self.tableView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        # 主窗體設(shè)置主Widget
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)  # 調(diào)用retranslateUi方法顯示窗體文字
        QtCore.QMetaObject.connectSlotsByName(MainWindow)  # 關(guān)聯(lián)信號槽

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "爬票"))
        self.checkBox_T.setText(_translate("MainWindow", "T-特快"))
        self.checkBox_K.setText(_translate("MainWindow", "K-快速"))
        self.checkBox_Z.setText(_translate("MainWindow", "Z-直達(dá)"))
        self.checkBox_D.setText(_translate("MainWindow", "D-動車"))
        self.checkBox_G.setText(_translate("MainWindow", "GC-高鐵"))
        self.label_type.setText(_translate("MainWindow", "車次類型:"))
        self.label.setText(_translate("MainWindow", "出發(fā)地:"))
        self.label_2.setText(_translate("MainWindow", "目的地:"))
        self.label_3.setText(_translate("MainWindow", "出發(fā)日:"))
        self.pushButton.setText(_translate("MainWindow", "查詢"))
def show_MainWindow():
    app = QtWidgets.QApplication(sys.argv)  # 首先必須實(shí)例化QApplication類,作為GUI主程序入口
    MainWindow = QtWidgets.QMainWindow()  # 實(shí)例化QtWidgets.QMainWindow類,創(chuàng)建自帶menu的窗體類型QMainWindow
    ui = Ui_MainWindow()  # 實(shí)例UI類
    ui.setupUi(MainWindow)  # 設(shè)置窗體UI
    MainWindow.show()  # 顯示窗體
    sys.exit(app.exec_())  # 當(dāng)來自操作系統(tǒng)的分發(fā)事件指派調(diào)用窗口時,
    # 應(yīng)用程序開啟主循環(huán)(mainloop)過程,
    # 當(dāng)窗口創(chuàng)建完成,需要結(jié)束主循環(huán)過程,
    # 這時候呼叫sys.exit()方法來,結(jié)束主循環(huán)過程退出,
    # 并且釋放內(nèi)存。為什么用app.exec_()而不是app.exec()?
    # 因?yàn)閑xec是python系統(tǒng)默認(rèn)關(guān)鍵字,為了以示區(qū)別,所以寫成exec_


if __name__ == "__main__":
    if isStations() == False:  # 判斷是否有所有車站的文件,沒有就下載,有就直接顯示窗體
        getStation()  # 下載所有車站文件
        show_MainWindow()  # 調(diào)用顯示窗體的方法
    else:
        show_MainWindow()  # 調(diào)用顯示窗體的方法

3、下載網(wǎng)站文件

在這之前我們的先去12306網(wǎng)站分析相關(guān)參數(shù)


下載網(wǎng)站文件

獲取完整的查票地址,注意每一個時期的地址是會發(fā)生改變的
創(chuàng)建用于下載網(wǎng)站文件的py文件,get_stations.py

import re
import  requests
import os

def getStation():
    # 發(fā)送請求獲取所有車站名稱,通過輸入的站名稱轉(zhuǎn)化查詢地址的參數(shù)
    url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9190'
    response = requests.get(url, verify=True)  # 請求并進(jìn)行驗(yàn)證
    stations = re.findall(u'([u4e00-u9fa5]+)|([A-Z]+)', response.text)  # 獲取需要的車站名稱
    stations = dict(stations)  # 轉(zhuǎn)換為dic
    stations = str(stations)  # 轉(zhuǎn)換為字符串類型否則無法寫入文件
    write(stations)           #調(diào)用寫入方法
def write(stations):
    file = open('stations.text', 'w', encoding='utf_8_sig')  # 以寫模式打開文件
    file.write(stations)  # 寫入數(shù)據(jù)
    file.close()
def read():
    file = open('stations.text', 'r', encoding='utf_8_sig')  # 以寫模式打開文件
    data = file.readline()                                  #讀取文件
    file.close()
    return data

def isStations():
    isStations = os.path.exists('stations.text')      #判斷車站文件是否存在
    return isStations

4、車票信息的請求與顯示

創(chuàng)建 query_request.py文件用于發(fā)現(xiàn)數(shù)據(jù)后的處理工作

from get_stations import *
import requests

'''5-7 目的地 3  車次 6  出發(fā)地 8  出發(fā)時間 9  到達(dá)時間 10 歷時 26 無坐 29 硬座
   24 軟座 28 硬臥 33 動臥 23 軟臥 21 高級軟臥 30 二等座 31 一等座 32 商務(wù)座特等座
'''
data = []  # 用于保存整理好的車次信息
type_data = []  # 保存車次分類后最后的數(shù)據(jù)
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36',
           'Cookie':'_uab_collina=162044599452968647580256; JSESSIONID=ABB3D0F36AA12C3E5DAD5CD1D3CFF031; '
                    'RAIL_EXPIRATION=1620786883959; RAIL_DEVICEID=hu-C8-xxpDNSCuX_BiPS1CGOlxAyoXu-dncsv32QDPvmjG'
                    'R9Ua0AUywoyJ6FDeqRWMoixIIL24hbMf9ucn2MrHcPWjgYFJ6y6Fon9ihvKvZV8SIiGDYmZTuR-S2OLu3wyezmWPPO'
                    'un2B-v2BR_Q0wEYkIrBLIE8j; _jc_save_fromStation=%u5317%u4EAC%2CBJP; _jc_save_toStation=%u4E0'
                    'A%u6D77%2CSHH; _jc_save_fromDate=2021-05-08; _jc_save_toDate=2021-05-08; _jc_save_wfdc_flag='
                    'dc; BIGipServerpassport=988283146.50215.0000; route=495c805987d0f5c8c84b14f60212447d; BIGipS'
                    'erverotn=417857802.50210.0000; BIGipServerportal=3084124426.17183.0000'}
def query(date, from_station, to_station):
    data.clear()  # 清空數(shù)據(jù)
    type_data.clear()  # 清空車次分類保存的數(shù)據(jù)
    # 查詢請求地址
    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)
    # 發(fā)送查詢請求
    response = requests.get(url=url,headers=headers)
    # # 將json數(shù)據(jù)轉(zhuǎn)換為字典類型,通過鍵值對取數(shù)據(jù)
    result = response.json()
    result = result['data']['result']
    # 判斷車站文件是否存在
    if isStations() == True:
        stations = eval(read())  # 讀取所有車站并轉(zhuǎn)換為dic類型
        if len(result) != 0:  # 判斷返回數(shù)據(jù)是否為空
            for i in result:
                # # 分割數(shù)據(jù)并添加到列表中
                tmp_list = i.split('|')
                # 因?yàn)椴樵兘Y(jié)果中出發(fā)站和到達(dá)站為站名的縮寫字母,所以需要在車站庫中找到對應(yīng)的車站名稱
                from_station = list(stations.keys())[list(stations.values()).index(tmp_list[6])]
                to_station = list(stations.keys())[list(stations.values()).index(tmp_list[7])]
                # 創(chuàng)建座位數(shù)組,由于返回的座位數(shù)據(jù)中含有空既“”,所以將空改成--這樣好識別
                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 = []
                # 循環(huán)將座位信息中的空既“”,改成--這樣好識別
                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:  # 循環(huán)所有火車數(shù)據(jù)
            i = g[0].startswith('G')  # 判斷車次首字母是不是高鐵
            if i:  # 如果是將該條信息添加到高鐵數(shù)據(jù)中
                type_data.append(g)


# 移除高鐵信息的方法
def r_g_vehicle():
    if len(data) != 0 and len(type_data) != 0:
        for g in data:
            i = g[0].startswith('G')
            if i:  # 移除高鐵信息
                type_data.remove(g)


# 獲取動車信息的方法
def d_vehicle():
    if len(data) != 0:
        for d in data:  # 循環(huán)所有火車數(shù)據(jù)
            i = d[0].startswith('D')  # 判斷車次首字母是不是動車
            if i == True:  # 如果是將該條信息添加到動車數(shù)據(jù)中
                type_data.append(d)


# 移除動車信息的方法
def r_d_vehicle():
    if len(data) != 0 and len(type_data) != 0:
        for d in data:
            i = d[0].startswith('D')
            if i == True:  # 移除動車信息
                type_data.remove(d)


# 獲取直達(dá)車信息的方法
def z_vehicle():
    if len(data) != 0:
        for z in data:  # 循環(huán)所有火車數(shù)據(jù)
            i = z[0].startswith('Z')  # 判斷車次首字母是不是直達(dá)
            if i == True:  # 如果是將該條信息添加到直達(dá)數(shù)據(jù)中
                type_data.append(z)


# 移除直達(dá)車信息的方法
def r_z_vehicle():
    if len(data) != 0 and len(type_data) != 0:
        for z in data:
            i = z[0].startswith('Z')
            if i == True:  # 移除直達(dá)車信息
                type_data.remove(z)


# 獲取特快車信息的方法
def t_vehicle():
    if len(data) != 0:
        for t in data:  # 循環(huán)所有火車數(shù)據(jù)
            i = t[0].startswith('T')  # 判斷車次首字母是不是特快
            if i == True:  # 如果是將該條信息添加到特快車數(shù)據(jù)中
                type_data.append(t)


# 移除特快車信息的方法
def r_t_vehicle():
    if len(data) != 0 and len(type_data) != 0:
        for t in data:
            i = t[0].startswith('T')
            if i == True:  # 移除特快車信息
                type_data.remove(t)


# 獲取快速車數(shù)據(jù)的方法
def k_vehicle():
    if len(data) != 0:
        for k in data:  # 循環(huán)所有火車數(shù)據(jù)
            i = k[0].startswith('K')  # 判斷車次首字母是不是快車
            if i == True:  # 如果是將該條信息添加到快車數(shù)據(jù)中
                type_data.append(k)


# 移除快速車數(shù)據(jù)的方法
def r_k_vehicle():
    if len(data) != 0 and len(type_data) != 0:
        for k in data:
            i = k[0].startswith('K')
            if i == True:  # 移除快車信息
                type_data.remove(k)

5、在主窗體中顯示查票信息

注意這些方法是寫在windows.py
(1)創(chuàng)建 get_time 和is_valid.date方法用判斷日期是否有效

def get_time():
    # 獲得當(dāng)前時間時間戳
    now = int(time.time())
    # 轉(zhuǎn)換為其它日期格式,如:"%Y-%m-%d %H:%M:%S"
    timeStruct = time.localtime(now)
    strTime = time.strftime("%Y-%m-%d", timeStruct)
    return strTime


def is_valid_date(str):
    '''判斷是否是一個有效的日期字符串'''
    try:
        time.strptime(str, "%Y-%m-%d")
        return True
    except:
        return False

(2)創(chuàng)建車次分類復(fù)選事件處理方法

 # 將所有車次分類復(fù)選框取消勾選
    def checkBox_default(self):
        self.checkBox_G.setChecked(False)
        self.checkBox_D.setChecked(False)
        self.checkBox_Z.setChecked(False)
        self.checkBox_T.setChecked(False)
        self.checkBox_K.setChecked(False)

    # 高鐵復(fù)選框事件處理
    def change_G(self, state):
        # 選中將高鐵信息添加到最后要顯示的數(shù)據(jù)當(dāng)中
        if state == QtCore.Qt.Checked:
            # 獲取高鐵信息
            g_vehicle()
            # 通過表格顯示該車型數(shù)據(jù)
            self.displayTable(len(type_data), 16, type_data)
        else:
            # 取消選中狀態(tài)將移除該數(shù)據(jù)
            r_g_vehicle()
            self.displayTable(len(type_data), 16, type_data)

    # 動車復(fù)選框事件處理
    def change_D(self, state):
        # 選中將動車信息添加到最后要顯示的數(shù)據(jù)當(dāng)中
        if state == QtCore.Qt.Checked:
            # 獲取動車信息
            d_vehicle()
            # 通過表格顯示該車型數(shù)據(jù)
            self.displayTable(len(type_data), 16, type_data)

        else:
            # 取消選中狀態(tài)將移除該數(shù)據(jù)
            r_d_vehicle()
            self.displayTable(len(type_data), 16, type_data)

    # 直達(dá)復(fù)選框事件處理
    def change_Z(self, state):
        # 選中將直達(dá)車信息添加到最后要顯示的數(shù)據(jù)當(dāng)中
        if state == QtCore.Qt.Checked:
            # 獲取直達(dá)車信息
            z_vehicle()
            self.displayTable(len(type_data), 16, type_data)
        else:
            # 取消選中狀態(tài)將移除該數(shù)據(jù)
            r_z_vehicle()
            self.displayTable(len(type_data), 16, type_data)

    # 特快復(fù)選框事件處理
    def change_T(self, state):
        # 選中將特快車信息添加到最后要顯示的數(shù)據(jù)當(dāng)中
        if state == QtCore.Qt.Checked:
            # 獲取特快車信息
            t_vehicle()
            self.displayTable(len(type_data), 16, type_data)
        else:
            # 取消選中狀態(tài)將移除該數(shù)據(jù)
            r_t_vehicle()
            self.displayTable(len(type_data), 16, type_data)

    # 快速復(fù)選框事件處理
    def change_K(self, state):
        # 選中將快車信息添加到最后要顯示的數(shù)據(jù)當(dāng)中
        if state == QtCore.Qt.Checked:
            # 獲取快速車信息
            k_vehicle()
            self.displayTable(len(type_data), 16, type_data)

        else:
            # 取消選中狀態(tài)將移除該數(shù)據(jù)
            r_k_vehicle()
            self.displayTable(len(type_data), 16, type_data)

(3)創(chuàng)建messageDialog與displayTable方法分別用于非法輸入的處理與車輛信息的顯示

# 顯示消息提示框,參數(shù)title為提示框標(biāo)題文字,message為提示信息
    def messageDialog(self, title, message):
        msg_box = QMessageBox(QMessageBox.Warning, title, message)
        msg_box.exec_()

    # 顯示車次信息的表格
    # train參數(shù)為共有多少趟列車,該參數(shù)作為表格的行。
    # info參數(shù)為每趟列車的具體信息,例如有座、無座臥鋪等。該參數(shù)作為表格的列
    def displayTable(self, train, info, data):
        self.model.clear()
        for row in range(train):
            for column in range(info):
                # 添加表格內(nèi)容
                item = QStandardItem(data[row][column])
                # 向表格存儲模式中添加表格具體信息
                self.model.setItem(row, column, item)
        # 設(shè)置表格存儲數(shù)據(jù)的模式
        self.tableView.setModel(self.model)

(4)創(chuàng)建on_click方法該方法用于查詢事件的處理

    # 查詢按鈕的單擊事件
    def on_click(self):
        get_from = self.textEdit.toPlainText()  # 獲取出發(fā)地
        get_to = self.textEdit_2.toPlainText()  # 獲取到達(dá)地
        get_date = self.textEdit_3.toPlainText()  # 獲取出發(fā)時間
        # 判斷車站文件是否存在
        if isStations() == True:
            stations = eval(read())  # 讀取所有車站并轉(zhuǎn)換為dic類型
            # 判斷所有參數(shù)是否為空,出發(fā)地、目的地、出發(fā)日期
            if get_from != "" and get_to != "" and get_date != "":
                # 判斷輸入的車站名稱是否存在,以及時間格式是否正確
                if get_from in stations and get_to in stations and is_valid_date(get_date):
                    # 獲取輸入的日期是當(dāng)前年初到現(xiàn)在一共過了多少天
                    inputYearDay = time.strptime(get_date, "%Y-%m-%d").tm_yday
                    # 獲取系統(tǒng)當(dāng)前日期是當(dāng)前年初到現(xiàn)在一共過了多少天
                    yearToday = time.localtime(time.time()).tm_yday
                    # 計算時間差,也就是輸入的日期減掉系統(tǒng)當(dāng)前的日期
                    timeDifference = inputYearDay - yearToday
                    # 判斷時間差為0時證明是查詢當(dāng)前的查票,
                    # 以及29天以后的車票。12306官方要求只能查詢30天以內(nèi)的車票
                    if timeDifference >= 0 and timeDifference <= 28:
                        from_station = stations[get_from]  # 在所有車站文件中找到對應(yīng)的參數(shù),出發(fā)地
                        to_station = stations[get_to]  # 目的地
                        data = query(get_date, from_station, to_station)  # 發(fā)送查詢請求,并獲取返回的信息
                        self.checkBox_default()
                        if len(data) != 0:  # 判斷返回的數(shù)據(jù)是否為空
                            # 如果不是空的數(shù)據(jù)就將車票信息顯示在表格中
                            self.displayTable(len(data), 16, data)
                        else:
                            self.messageDialog('警告', '沒有返回的網(wǎng)絡(luò)數(shù)據(jù)!')
                    else:
                        self.messageDialog('警告', '超出查詢?nèi)掌诘姆秶鷥?nèi),'
                                                 '不可查詢昨天的車票信息,以及29天以后的車票信息!')
                else:
                    self.messageDialog('警告', '輸入的站名不存在,或日期格式不正確!')
            else:
                self.messageDialog('警告', '請?zhí)顚戃囌久Q!')
        else:
            self.messageDialog('警告', '未下載車站查詢文件!')

(5)在retranslateUi方法中分別加入以下代碼

        self.textEdit_3.setText(get_time())  # 出發(fā)日顯示當(dāng)天日期
        self.pushButton.clicked.connect(self.on_click)  # 查詢按鈕指定單擊事件的方法
        self.checkBox_G.stateChanged.connect(self.change_G)  # 高鐵選中與取消事件
        self.checkBox_D.stateChanged.connect(self.change_D)  # 動車選中與取消事件
        self.checkBox_Z.stateChanged.connect(self.change_Z)  # 直達(dá)車選中與取消事件
        self.checkBox_T.stateChanged.connect(self.change_T)  # 特快車選中與取消事件
        self.checkBox_K.stateChanged.connect(self.change_K)  # 快車選中與取消事件

到此結(jié)束,以下是運(yùn)行結(jié)果

運(yùn)行結(jié)果

運(yùn)行結(jié)果

運(yùn)行結(jié)果

運(yùn)行結(jié)果

運(yùn)行結(jié)果

到此這篇python爬取車票信息并使用pyqt5實(shí)現(xiàn)GUI的文章就介紹到這了,更多python學(xué)習(xí)內(nèi)容請搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關(guān)文章。



0 人點(diǎn)贊