前言
本篇教程适合对Python爬虫和Python软件制作感兴趣的小伙伴阅读,看完本篇教程,你将能更深入了解PyQt5与实际功能的整合方式。
如果你只需要软件点击链接获取=>幽络源爬图器
1.设计界面
首先在pycharm中创建一个新目录,这里我建立的目录名为爬图片,然后按如图打开Qt设计器( 如果你的ExternalTools没有QtDesigner和PyUIC则说明没有为PyCharm配置QT相关工具,可按照此教程先配置=>
)我们直接拖拽出一个简单的软件界面,注意:在ComboBox中我添加了百度图片、必应图片、搜狗图片、360图片,因为我们要做一个能够爬取各大搜索引擎的图片爬取器,而且我这里给PushButton控件重命名为btn_catch
界面拖拽完成后,使用快捷键ctlr+s保存到当前目录,会出现一个untitled.ui文件,同样的对此文件右键然后ExternalTools->PyUIC,就会产生一个untitled.py文件,此文件中含有两个函数setupUi和retranslateUi,我们这里将其重命名为Window.py,毕竟是个GUI窗口嘛,如图
2.启动界面
新建文件Main.py,然后复制如下代码,一定要看注释,否则最后打包软件到时候会出问题
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
#这个Window.py文件在名为'爬图片'的目录,我们不要用'from 爬图片 import Window'的方式引入,否则后面打包的软件会报错找不到目录(当然你也可以打包目录,但这里为了方便,去掉目录,简化打包命令)
import Window
if __name__=='__main__':
app=QApplication(sys.argv)
mainWindow=QMainWindow()
ui=Window.Ui_MainWindow() #这里的Window便是我们Window.py文件的名字
ui.setupUi(mainWindow)
mainWindow.show()
sys.exit(app.exec_())
然后启动Main.py,看看是否能启动界面,若成功,则显示如图(若失败则大概率是你的QT库有问题,可卸载重装pyQT,若还不行则降低python版本为3.10及以下,我之前就是这样)
3.完善控件
在正式写爬图片的功能前,我们还需要对此窗口文件添加相关控件的功能,比如ListView控件(就是大白框)、PushButton(就是按钮)、Progress(就是进度条),因为在爬取图片时会和这些控件进行交互。
第一:初始化ListView
我们直接在Window.py文件的函数setupUi最下面加入如下代码即可,如图
# ListView要展示的数据存放区
self.messageList = []
# ListView的数据模型对象初始化
self.listMode = QStringListModel()
# 将数据放入模型中,此时数据为空
self.listMode.setStringList(self.messageList)
# 使listview生效
self.listView.setModel(self.listMode)
然后创建一个专门用来操作ListView的函数(这里专业术语叫做插槽函数),如图:
# 定义一个操作ListView的插槽函数
def controListView(self, msg):
# 追加数据
self.messageList.append(msg + "\n")
# 更新模型
self.listMode.setStringList(self.messageList)
if msg=="爬取结束":
self.btn_catch.setEnabled(True)
第二:初始化进度条
同样的在setupUi函数最后加入如下代码,如图
#pv作为给进度条传值的中间变量
self.pv = 0
#设定进度条最小值
self.progressBar.setMinimum(0)
#设置当前进度条的值
self.progressBar.setValue(self.pv)
然后为进度条也添加个插槽函数,如图:
#定义一个操作进度条的插槽函数
def controlProgress(self,addVal,MaxVal):
self.pv += addVal #进度条变量自加
self.progressBar.setMaximum(MaxVal) #设置进度条最大值
self.progressBar.setValue(self.pv) #设置进度条的值
第三:初始化按钮
我这里的按钮在设计界面时,为按钮重命名为了btn_catch(默认是叫做pushButton)
在Window.py添加一个函数供按钮调用,然后在setupUi最后添加如下代码与函数绑定,如图:
#按钮点击后
self.btn_catch.clicked.connect(self.btn_click)
#按钮点击后执行的函数
def btn_click(self):
#获取ComboBox中当前的选项
chosseItem=self.comboBox_source.currentText()
#如果选项为百度图片
if chosseItem=="百度图片":
pass
4.功能分析
控件功能初始化好了,然后是写爬图片的功能了,既然要爬图片,那我们就先搞个爬取百度图片的QT线程,为什么要用线程呢?因为这GUI界面你不用其他线程去处理耗时的功能,放在和GUI界面一个主线程中就会卡住。
分析:爬取图片说白了就是请求百度图片网页获取图片链接并下载图片,那么这个线程应当接收参数关键字和图片数量,当然百度图片这里我们按照轮次去爬,他一轮约30张,至于为什么按照轮次可以看这里分析爬取百度图片:
,所以这里需接收两个参数 关键词keyword、轮次rangeCount
5.爬图功能
新建QT线程文件名为BaiDuThread.py,填写如下代码
import json
import os.path
import time
import requests
from PyQt5.QtCore import QThread, pyqtSignal
class BaiDuThread(QThread):
#消息信号,用于传递消息给ListView控件
msgSign=pyqtSignal(str)
#进度条信号
progressSign=pyqtSignal(int,int)
def __init__(self,keyword,rangeCount):
super(BaiDuThread, self).__init__()
self.keyword = keyword
self.rangeCount = rangeCount
def run(self):
keyword=self.keyword #关键词
rangeCount=self.rangeCount #轮次
if not os.path.exists(keyword):
os.mkdir(keyword)
#为了简单,这里直接将轮次作为进度条最大值
MaxVal=rangeCount
self.progressSign.emit(0,MaxVal)
self.msgSign.emit("正在从百度搜索引擎爬取和"+keyword+"相关的图片")
for count in range(rangeCount):
pn = count * 30
url = "https://images.baidu.com/search/acjson?tn=resultjson_com&logid=11514788725054802565&ipn=rj&ct=201326592&is=&fp=result&fr=&word=" + str(keyword) + "&queryWord=" + str(
keyword) + "&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=&expermode=&nojc=&isAsync=&pn=" + str(
pn) + "&rn=30&gsm=1e&1717479169689="
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36'}
res = requests.get(url, headers=headers)
if len(res.json()["data"]) == 1:
self.msgSign.emit("无图片可获取了,爬取结束")
break
json_data = res.json()["data"] # 获取json数据
json_str = json.dumps(json_data, indent=2) # json转json字符串
list_data = json.loads(json_str) # json字符串转list/dict
for obj in list_data:
try:
pic_url = obj["thumbURL"] # 图像链接
except:
continue
r = requests.get(pic_url, headers=headers)
with open(str(keyword) + "\\" + str(time.time()) + ".jpg", mode="wb") as f:
f.write(r.content)
self.progressSign.emit(1,MaxVal)
self.msgSign.emit("爬取结束")
6.完善按钮
回到Window.py文件,我们继续完善btn_click函数为如下:
# 按钮点击后执行的函数
def btn_click(self):
self.progressBar.setValue(0)
self.pv = 0
# 获取ComboBox中当前的选项
chosseItem = self.comboBox_source.currentText()
# 获取关键字
keyword = self.lineEdit_keyword.text()
if keyword=="":
self.controListView("关键字不可为空")
return
# 获取轮次
if not self.lineEdit_count.text().isdigit():
self.controListView("轮次必须为正整数")
return
rangeCount = int(self.lineEdit_count.text())
# 如果选项为百度图片
if chosseItem == "百度图片":
self.btn_catch.setEnabled(False)
self.baiduThread=BaiDuThread(keyword,rangeCount)
self.baiduThread.msgSign.connect(lambda msg:self.controListView(msg)) #连接消息信号
self.baiduThread.progressSign.connect(lambda addVal,maxVal:self.controlProgress(addVal,maxVal)) #连接进度条信号
self.baiduThread.start()
7.测试功能
到此处,爬百度图片的功能就集成到GUI界面了,打开Main.py,开始使用,结果如下
8.打包软件
最后是打包为软件,其实一条命令即可,没网上那些低质量教程说的那么复杂。
打包前先检查每个文件最上边引入其他文件时是否有带目录名,若带目录名将其去掉即,如图我的Window.py中就带有”爬图片”目录名字,去掉后再打包(当然你也可以打包目录,但这里为了方便,去掉目录,简化打包命令)
方式1:直接打包
在当前目录下CMD的控制台直接执行命令打包为exe:
如果你是在PyCharm控制台打包则需要加上”.\”:
打包完后在目录会生成个dist目录,里边便是软件,如图:
方式2:虚拟环境打包
原因:python打包会把所有自己下载的包都加入进去,会造成软件体积很大,如下图是笔者昨天未使用虚拟环境打包后的软件,打包时我说时间怎么这么久,出门一趟回来一看2.5个G.,给👴整麻了
1.新建Python项目创建虚拟环境,如图点点点就完事:
2.对虚拟环境目录右键打开控制台,用命令pip list查看当前虚拟环境的库的数量(看环境是否正常),如图
3.新的虚拟环境肯定是缺少你项目需要的包,下载就完事,最后打包命令和直接打包是一样的,如图可以看到虚拟环境打包后体积就不再冗余了
9.总结
总结:本教程将实际功能与PyQt5进行整合,希望本篇教程对初学PyQt5的同学有帮助,虽然本教程只提供了百度图片的爬取教程,但其他搜索引擎的爬取方式大同小异,可自行下来添加功能。
暂无评论内容