利用Requests+PyQt5+Pyinstaller实现简单的B站画册爬取程序

原因:自己在求职的过程中看到某些岗位需求上写着会独立设计,编码,打包…想着自己从没有做过exe文件,所以借着B站画册容易爬的优点就来简单写一个小爬虫程序,走个流程先。

使用的包有:
1、PyQt5 图形化界面
2、requests 一个很好用的功能强大的请求包
3、fake_useragent 随机生成请求头中的User-Agent的值
4、jsonpath 本次爬取的是接口数据,所以使用jsonpath进行解析
5、Pyinstall 使用它进行程序的打包

1. 设计爬虫:

首先我们要点击B站的画友,里面会有很多up上传的图片
B站相簿
随便点击一个进去,用Chrome浏览器的开发着工具,找到当前URL的详细信息。
URL信息
尝试着requests直接爬页面,然后加了Cookie,加了refere,加了UA之后是没用的,页面显示的是相簿的首页,之后就开始找json数据了
在这里插入图片描述
幸运的是,画册的json链接是可以直接拿到数据的,所以只需要传入对应的doc_id,就可以拿到图片的信息了。
在这里插入图片描述
开始编码:

dir_name = 'B站画册'   
file_name = '6月杂志扫图'
net_id = 79619485

import requests
from fake_useragent import UserAgent
import jsonpath as jsonpath
import json
import os

# 请求头, api接口
ua= UserAgent()
url = f'https://api.vc.bilibili.com/link_draw/v1/doc/detail?doc_id={net_id}'
header = {
    'User-Agent': ua.random,
    'Accept-Encoding': '',
}

# jsonpath 解析api
res = requests.get(url,header).text
res = json.loads(res)
pic = jsonpath.jsonpath(res, '$..img_src')

# 创建文件夹
if not os.path.lexists(dir_name):
    os.mkdir(dir_name)
    
# 组合文件路径
pic_path = os.path.join(os.path.abspath('.'),dir_name)

for i,p in enumerate(pic):
    with open(os.path.join(pic_path, pic_name+f'_{i+1}.jpg'),'wb') as f:
        print(f'正在进行下载.... 当前下载的是第{i+1}张,总共{len(pic)}张')
        res = requests.get(p).content
        f.write(res)
print('下载完成')

这样一个简单的爬虫就写好了。

2. 编写图形化界面:

利用PyQt5,我们可以快速打造一个UI界面,可以根据这篇博客安装,QTdesigner和PyUIC建议都弄好 -> PyQt5安装
可能Qtdesigner工具的路径会有问题,所以附上我的
在这里插入图片描述
PyUIC就是当前python里面的pyuic.exe

– 安装好后,打开Tools -> External Tools -> QTdesigner就可以设计UI界面了
在这里插入图片描述

其中的窗口组件:
label:画册ID、图片名称、下载进度
textEdit:输入窗口
toolButton: 选择文件路径
line: 中间那条线
progressBar:进度条
pushButton: 开始

其中各组件的位置可以自行调整。
保存后会生成一个.ui 文件,只需要右键 -> External Tools -> PyUIC,之后就可以生成一个.py 文件,这个py文件就是PyQt的代码。
在这里插入图片描述
之后我们给它写逻辑代码,绑定事件,再将爬虫组合进来。
这里参考了 PyQT下载进度条 这篇文章,使用线程、信号传递进度情况。

class mwindow(QWidget, Ui_BiliBili):
    def __init__(self):
        super(mwindow, self).__init__()
        self.setupUi(self)
        self.setWindowIcon(QIcon('./icon.ico')) # 图标
    def action_scrapy(self):
        # 这里的textEdit, textEdit_2...组件都是PyQT文件里的,要根据具体名称设定
        # 获取画册id
        pic_id = self.textEdit.toPlainText()
        # 获取图片名称
        pic_name = self.textEdit_2.toPlainText()
        # 获取图片名称
        pic_path = self.textEdit_3.toPlainText()

        if pic_id and pic_name and pic_path:
            # 创建下载线程
            self.downloadThread = downloadThread(pic_id, pic_name, pic_path)
            self.downloadThread.download_proess_signal.connect(self.set_progressbar_value)
            self.downloadThread.start()
        else:
            QtWidgets.QMessageBox.warning(self, '提示', '请输入正确的信息')

    def choice_file(self):
        file_path = QFileDialog.getExistingDirectory(self, "选择文件夹", "/")
        self.textEdit_3.setText(file_path)

    def set_progressbar_value(self, value):
        self.progressBar.setValue(value)

        if value == 100:
            QMessageBox.information(self, "提示", "下载成功!")
            return



class downloadThread(QThread):
	# 信号
    download_proess_signal = pyqtSignal(int)                        #创建信号

    def __init__(self, net_id, pic_name, file_path):
        super(downloadThread, self).__init__()
        self.net_id = net_id
        self.pic_name = pic_name
        self.file_path = file_path


    def run(self):
        try:
            ua = UserAgent()
            url = f'https://api.vc.bilibili.com/link_draw/v1/doc/detail?doc_id={self.net_id}'
            header = {
                'User-Agent': ua.random,
                'Accept-Encoding': '',
            }

            # jsonpath 解析api
            res = requests.get(url, header).text
            res = json.loads(res)
            pic = jsonpath.jsonpath(res, '$..img_src')


            for i, p in enumerate(pic):
                with open(os.path.join(self.file_path, self.pic_name) + f'_{i + 1}.jpg', 'wb') as f:
                    print(f'正在进行下载.... 当前下载的是第{i + 1}张,总共{len(pic)}张')
                    # 发送信号
                    self.download_proess_signal.emit(int(((i + 1) / len(pic)) * 100))  

                    res = requests.get(p).content
                    f.write(res)
            print('下载完成')
        except Exception as e:
            print(e)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = mwindow()
    # 开始按钮
    w.pushButton.clicked.connect(w.action_scrapy)
    # 选择文件路径
    w.toolButton.clicked.connect(w.choice_file)
    w.show()
    # 完全退出
    sys.exit(app.exec_())

效果图:
在这里插入图片描述

3. 程序打包:

事已至此,整个程序设计已经可以运行了,然后我们使用Pyinstaller来进行打包。
注意: 程序中的第三方库需要从python的site-packages中单独拿到当前文件夹,否则打包后程序会出现model找不到的情况无法运行。我再打包的过程中一些文件还是出现了路径错误,我就很奇怪,最后的解决办法是将所有代码放到一个 .py 文件中,整合代码和包后就可以了
在这里插入图片描述
我将这三个包放到 packages 文件夹中, 文件列表如下
在这里插入图片描述

打包命令:
pyinstaller -F -w -i blbl.ico bilibili.py
-F:是直接生成单独的exe文件,不附带各种依赖文件的。
-c:生成的exe文件打开方式为控制台打开。
-w:这个和上面的 -c 对应,如果你的程序是有ui的,那就用这个 -w。这样不会出现控制台,直接是你的ui。
-I:给你的exe文件添加一个图标,后面要紧接着你想要的ico文件。

生成的文件在dist中,到此就结束了。
github链接:https://github.com/EricSell/PlayGround/tree/bili_pic

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值