讓你的小爬蟲穿上新外衣,做一只界面友好型的爬蟲
在上一篇文章中,我們完成了一只能夠?qū)氩⒆x取Excel文件內(nèi)容,并進(jìn)行網(wǎng)頁自動(dòng)爬取,并將爬取的內(nèi)容保存下來的小爬蟲,已經(jīng)非常的能干了。但是這只小爬蟲缺少一件外衣(圖形界面),不能友好的進(jìn)行交互,那么這篇文章中,我們就來著手制作這個(gè)圖形界面。
圖形界面庫的選擇
Python支持多種圖形界面的第三方庫,包括wxWidgets、Qt、GTK。
我當(dāng)時(shí)剛剛尋找制作衣服材料(GUI)的時(shí)候也是眼花繚亂,嘗試過很多,比如Tkinter,但是試了一下后發(fā)現(xiàn)有點(diǎn)丑,不適合我的審美。最后我將目標(biāo)鎖定為Qt。
PyQt5是一套Python綁定Digia QT5應(yīng)用的框架。它可用于Python 2和3。本教程使用Python 3。Qt庫是最強(qiáng)大的GUI庫之一。PyQt5做為Python的一個(gè)模塊,它有620多個(gè)類和6000個(gè)函數(shù)和方法。這是一個(gè)跨平臺(tái)的工具包,它可以運(yùn)行在所有主要的操作系統(tǒng),包括UNIX,Windows,Mac OS。pyqt5是雙重許可。
PyQt5的安裝
這里我們?nèi)匀徽埳仙衿鱬ip登場。
pip install PyQt5
安裝完成以后就可以直接使用,不需要任何配置信息。
這里借用一下他人的代碼,來測試你的PyQt5是否能正常執(zhí)行。
import sys
#這里我們提供必要的引用?;究丶挥趐yqt5.qtwidgets模塊中。
from PyQt5.QtWidgets import QApplication, QWidget
if __name__ == '__main__':
#每一pyqt5應(yīng)用程序必須創(chuàng)建一個(gè)應(yīng)用程序?qū)ο?。sys.argv參數(shù)是一個(gè)列表,從命令行輸入?yún)?shù)。
app = QApplication(sys.argv)
#QWidget部件是pyqt5所有用戶界面對象的基類。他為QWidget提供默認(rèn)構(gòu)造函數(shù)。默認(rèn)構(gòu)造函數(shù)沒有父類。
w = QWidget()
#resize()方法調(diào)整窗口的大小。這離是250px寬150px高
w.resize(250, 150)
#move()方法移動(dòng)窗口在屏幕上的位置到x = 300,y = 300坐標(biāo)。
w.move(300, 300)
#設(shè)置窗口的標(biāo)題
w.setWindowTitle('Simple')
#顯示在屏幕上
w.show()
#系統(tǒng)exit()方法確保應(yīng)用程序干凈的退出
#的exec_()方法有下劃線。因?yàn)閳?zhí)行是一個(gè)Python關(guān)鍵詞。因此,exec_()代替
sys.exit(app.exec_())
運(yùn)行程序,顯示一個(gè)對話框,安裝成功。

接下來我百度了各種PyQt5的代碼寫法,試了下用手寫的方式來實(shí)現(xiàn)界面排版( PyQt5布局管理),但是發(fā)現(xiàn)這個(gè)難度有點(diǎn)大,類似于閉著眼睛打代碼,全靠腦補(bǔ),效率太低了。最后決定用軟件來幫助我實(shí)現(xiàn)界面布局。
一番搜尋,決定使用QtCreator來進(jìn)行界面的繪制。
QTCreator
QTCreator是跨平臺(tái)的QT IDE,提供圖形化的UI繪制工具。
首先,你的系統(tǒng)中必須準(zhǔn)備好Python環(huán)境,并且安裝對應(yīng)版本的PyQt5庫,再然后安裝對應(yīng)版本的QtCreator。
點(diǎn)擊跳轉(zhuǎn)到Python官方下載地址
點(diǎn)擊跳轉(zhuǎn)到各個(gè)版本PyQt5安裝包下載地址
點(diǎn)擊跳轉(zhuǎn)到QTCreator官方下載地址
在使用QTCreator的時(shí)候我繞了一個(gè)很大的彎路,看著教程各種配置了一番Python的使用環(huán)境,但是你只是用QTCreator設(shè)計(jì)一個(gè)圖形界面,而不需要在里面設(shè)計(jì)代碼(代碼部分放到VSCode中去寫)的話,就不需要配置,可以直接拿來使用。
下載安裝完QTCreator,打開,選擇文件→新建文件或項(xiàng)目,選擇Qt→Qt Designer Form。

選擇Main Window→路徑和文件名自己設(shè)置→下一步,最后點(diǎn)擊完成會(huì)生成一個(gè).ui的文件,就可以拖動(dòng)左邊的組件進(jìn)行界面的繪制了。

這里順帶說一下QT設(shè)計(jì)師界面類和Qt Designer Form的區(qū)別。當(dāng)時(shí)看著教程,里面說到這一步:選擇button組件進(jìn)行信號槽連接,進(jìn)入cpp文件中進(jìn)行代碼操作??墒俏以趺袋c(diǎn)都是報(bào)錯(cuò),后來才發(fā)現(xiàn)選擇Qt Designer Form只會(huì)產(chǎn)生一個(gè).ui的文件,而選擇QT設(shè)計(jì)師界面類,會(huì)生成3個(gè)文件,分別是.h、.cpp和.ui文件。

只有選擇了QT設(shè)計(jì)師界面類,點(diǎn)擊連接信號槽才能跳轉(zhuǎn)到.cpp文件中進(jìn)行代碼編寫。我們只做界面布局的話,只需要一個(gè).ui文件就夠了,因?yàn)榇a的編寫完全可以到更棒的VSCode中操作。
完成了這些我們就可以愉快的拖動(dòng)圖標(biāo)進(jìn)行界面布局了。這個(gè)是我設(shè)計(jì)的界面,看上去很普通,大家輕拍。(其實(shí)已經(jīng)是第三版界面了,前兩版特別是第一版簡直丑到慘不忍睹,只是為了功能的實(shí)現(xiàn)而去嘗試下設(shè)計(jì)的)

說到界面設(shè)計(jì),那我要給大家說一個(gè)我遇到的坑,就是這個(gè)QGroupBox組件。

乍一看這玩意我以為是透明的,沒在意層次,結(jié)果后面運(yùn)行的時(shí)候,在QGroupBox里的按鈕怎么按都按不下去,QLineEdit組件怎么點(diǎn)擊都無法輸入,還以為是我的環(huán)境配置出了問題,搗鼓了好久。最后發(fā)現(xiàn)是QGroupBox組件的問題。這個(gè)組件其實(shí)也是有厚度的,雖然是透明的給你一個(gè)假象,其實(shí)類似于css屬性中的z-index。所以需要用這個(gè)組件的時(shí)候,需要先放QGroupBox,然后再配置QGroupBox里面的其他組件,才不會(huì)引起看上去什么事兒都沒,但是實(shí)際上已經(jīng)被覆蓋的問題。
將.ui的界面文件轉(zhuǎn)換為.py文件
設(shè)計(jì)完界面后,我們需要把這個(gè).ui變成代碼,以方便我們之后的操作。
- 首先在cmd中打開.ui所在路徑
cd E:/QT_Creator/bin - 然后輸入
pyuic5 -o mainwindow.py mainwindow.ui回車.其中,-o 后的參數(shù)為輸出文件的名稱 -o 后第二個(gè)參數(shù)即為生成的ui文件的名稱
這樣就能得到一個(gè)名為mainwindow.py的文件,我們用VSCode打開,就可以對他進(jìn)行操作了。

這個(gè)時(shí)候在VSCode中按下F5會(huì)報(bào)錯(cuò),所以還需要配置幾個(gè)步驟。
- 增加幾個(gè)引用
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog,QMessageBox
import sys
- 添加主函數(shù)腳本
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
然后再次按下F5,成功運(yùn)行,彈出界面。
這個(gè)時(shí)候,我們要把按鈕和輸入框的改造下,使其能夠交互起來。
QPushButton的信號槽連接:
self.choose_file.clicked.connect(self.open_file),傳入的是點(diǎn)擊后執(zhí)行的方法。獲取QLineEdit里面的文本:
self.cookie_edit.text()。將文案輸出到QTextBrowser組件中顯示:
self.message_show.append('爬取全部文章成功\n')。判斷復(fù)選框是否選中
self.only_name.isChecked(),返回的是true/false。
運(yùn)行中我發(fā)現(xiàn),每次執(zhí)行的時(shí)候,QTextBrowser組件中的文案,不能像print()方法一樣,一行一行的輸出,每次都是要等到全部執(zhí)行完后,一次性輸出。這個(gè)不符合我設(shè)計(jì)QTextBrowser組件的初衷。于是我又去問了問怎么樣才能讓QTextBrowser組件中的文案一行一行的輸出。
最終多方嘗試后,解決了這個(gè)問題,就是加入這句代碼QApplication.processEvents(),可以將這句代碼放入循環(huán)中,就能做到界面的實(shí)時(shí)刷新了。
self.message_show.append('爬取文章鏈接成功\n')
QtWidgets.QApplication.processEvents() #界面實(shí)時(shí)刷新
在復(fù)雜操作的過程中頻繁調(diào)用QApplication.processEvents()。這個(gè)函數(shù)告訴Qt處理所有那些還沒有被處理的各類事件,然后將控制權(quán)返還給調(diào)用者。實(shí)際上QApplication.exec()就是一個(gè)不停調(diào)用processEvents()函數(shù)的while循環(huán)。
完成了這些的準(zhǔn)備后。將上篇文章中完成的小爬蟲稍加改造移植過來。按F5執(zhí)行一下試試。

有了很棒的交互,能夠?qū)σ恍┓欠ú僮髯龀雠袛嗖⑻崾?,而不?huì)直接保存,程序中斷響應(yīng)。最后填入正確的參數(shù),點(diǎn)擊開始爬取。

完美的獲取了我們所需要的數(shù)據(jù),而且能根據(jù)需求進(jìn)行范圍爬取。QTextBrowser組件也能根據(jù)爬取的進(jìn)度,一行一行的顯示。
后記
本篇文章,詳細(xì)的講了python的圖形界面庫PyQt5的使用、QTCreator的下載安裝使用以及.ui轉(zhuǎn)為.py的方法。截止到這第四篇的系列文章,我們的小爬蟲不僅能自己完成全部文章的爬取,而且還穿上了人機(jī)交互良好的新衣服。已經(jīng)變的非常優(yōu)秀了。但是還缺少最后一樣,這只小爬蟲目前還是非常依賴本地電腦的配置,要是放到其他電腦上,缺少了需要的環(huán)境,它就又一動(dòng)不動(dòng)了。所以在下篇文章,也是最后一篇文章中,我們要將這只小爬蟲,打包發(fā)布出來,使它可以在其他電腦上歡快自在的運(yùn)行。