PyQt5整合爬虫制作图片爬取器-幽络源

PyQt5整合爬虫制作图片爬取器-幽络源

前言

本篇教程适合对Python爬虫和Python软件制作感兴趣的小伙伴阅读,看完本篇教程,你将能更深入了解PyQt5与实际功能的整合方式。

如果你只需要软件点击链接获取=>幽络源爬图器

1.设计界面

首先在pycharm中创建一个新目录,这里我建立的目录名为爬图片,然后按如图打开Qt设计器 如果你的ExternalTools没有QtDesigner和PyUIC则说明没有为PyCharm配置QT相关工具,可按照此教程先配置=>PyQT5篇 -1.环境配置与初步使用(图文超详细)_tool settings里的working directory-CSDN博客

56bee48bd3618dac7fc11542e0dd3667

我们直接拖拽出一个简单的软件界面,注意:在ComboBox中我添加了百度图片、必应图片、搜狗图片、360图片,因为我们要做一个能够爬取各大搜索引擎的图片爬取器,而且我这里给PushButton控件重命名为btn_catch

8520a8e35705db1e9fe833f0dc2f0028

界面拖拽完成后,使用快捷键ctlr+s保存到当前目录,会出现一个untitled.ui文件,同样的对此文件右键然后ExternalTools->PyUIC,就会产生一个untitled.py文件,此文件中含有两个函数setupUi和retranslateUi,我们这里将其重命名为Window.py,毕竟是个GUI窗口嘛,如图

3626c853a382bea4ab2d5efd278a7e1d

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及以下,我之前就是这样)

QQ_1727582215752

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)

QQ_1727579249802

然后创建一个专门用来操作ListView的函数(这里专业术语叫做插槽函数),如图:

# 定义一个操作ListView的插槽函数
def controListView(self, msg):
    # 追加数据
    self.messageList.append(msg + "\n")
    # 更新模型
    self.listMode.setStringList(self.messageList)
    if msg=="爬取结束":
        self.btn_catch.setEnabled(True)

QQ_1727580783679

第二:初始化进度条

同样的在setupUi函数最后加入如下代码,如图

#pv作为给进度条传值的中间变量
self.pv = 0
#设定进度条最小值
self.progressBar.setMinimum(0)
#设置当前进度条的值
self.progressBar.setValue(self.pv)

QQ_1727579516284

然后为进度条也添加个插槽函数,如图:

#定义一个操作进度条的插槽函数
def controlProgress(self,addVal,MaxVal):
    self.pv += addVal #进度条变量自加
    self.progressBar.setMaximum(MaxVal) #设置进度条最大值
    self.progressBar.setValue(self.pv) #设置进度条的值

QQ_1727580998555

第三:初始化按钮

我这里的按钮在设计界面时,为按钮重命名为了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

QQ_1727580064074

4.功能分析

控件功能初始化好了,然后是写爬图片的功能了,既然要爬图片,那我们就先搞个爬取百度图片的QT线程,为什么要用线程呢?因为这GUI界面你不用其他线程去处理耗时的功能,放在和GUI界面一个主线程中就会卡住。
分析:爬取图片说白了就是请求百度图片网页获取图片链接并下载图片,那么这个线程应当接收参数关键字和图片数量,当然百度图片这里我们按照轮次去爬,他一轮约30张,至于为什么按照轮次可以看这里分析爬取百度图片:

Python爬取百度图片(包括分析原理)
,所以这里需接收两个参数 关键词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=&copyright=&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,开始使用,结果如下

QQ_1727583067082

8.打包软件

最后是打包为软件,其实一条命令即可,没网上那些低质量教程说的那么复杂。
打包前先检查每个文件最上边引入其他文件时是否有带目录名,若带目录名将其去掉即,如图我的Window.py中就带有”爬图片”目录名字,去掉后再打包(当然你也可以打包目录,但这里为了方便,去掉目录,简化打包命令)

71f2a5e26eb39da39662d133112ef62e

方式1:直接打包

在当前目录下CMD的控制台直接执行命令打包为exe:

pyinstaller -F -w Main.py -p Window.py -p BaiDuThread.py

图片[12]-PyQt5整合爬虫制作图片爬取器:设计界面、功能实现与打包教程 - 幽络源

如果你是在PyCharm控制台打包则需要加上”.\”:

pyinstaller -F -w .\Main.py -p .\BaiDuThread.py -p .\Window.py

图片[12]-PyQt5整合爬虫制作图片爬取器:设计界面、功能实现与打包教程 - 幽络源

打包完后在目录会生成个dist目录,里边便是软件,如图:

QQ_1727583614324

方式2:虚拟环境打包

原因:python打包会把所有自己下载的包都加入进去,会造成软件体积很大,如下图是笔者昨天未使用虚拟环境打包后的软件,打包时我说时间怎么这么久,出门一趟回来一看2.5个G.,给👴整麻了

2b5ab926e7ddaf6b958cd248818b37a0

1.新建Python项目创建虚拟环境,如图点点点就完事:

1

2.对虚拟环境目录右键打开控制台,用命令pip list查看当前虚拟环境的库的数量(看环境是否正常),如图

2

3

3.新的虚拟环境肯定是缺少你项目需要的包,下载就完事,最后打包命令和直接打包是一样的,如图可以看到虚拟环境打包后体积就不再冗余了

5b71fe711b4357ea7acb9633f7d2da00

10024e4c2d18d2d14f69c276167920ab

9.总结

总结:本教程将实际功能与PyQt5进行整合,希望本篇教程对初学PyQt5的同学有帮助,虽然本教程只提供了百度图片的爬取教程,但其他搜索引擎的爬取方式大同小异,可自行下来添加功能。

© 版权声明
THE END
喜欢就支持一下吧
分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称

    暂无评论内容