一个pyqt5+scrapy爬虫的图片采集器

演示

一个pyqt5+scrapy爬虫的图片采集器

爬虫

网站

如图,选取彼岸桌面的分类栏,点击不同类别查看url有何不同,因为这类网站的骨架html基本都是不变的,变的是数据请求参数。

美女类别图片url:http://www.netbian.com/meinv

体育类别图片url:http://www.netbian.com/tiyu

可以发现,只有后面的路由部分不同,还是汉语拼音。因此只要写其中一个爬虫,其余类别更换url路由即可实现。

scrapy简介

其实这个框架可能用于高级爬虫,在这里不太适用,简单来说就是一个引擎能够调动管道、调度器、下载器、爬虫来协同配合工作。管道用于处理爬虫(spider)提取的实体。主要的功能是持久化实体、验证实体的有效性、清除不需要的信息;调度器,说白了把它假设成为一个URL(抓取网页的网址或者说是链接)的优先队列,由它来决定下一个要抓取的网址是 什么,同时去除重复的网址(不做无用功)。用户可以自己的需求定制调度器;下载器,是所有组件中负担最大的,它用于高速地下载网络上的资源。Scrapy的下载器代码不会太复杂,但效率高,主要的原因是Scrapy下载器是建立在twisted这个高效的异步模型上的(其实整个框架都在建立在这个模型上的);爬虫,是用户最关心的部份。用户定制自己的爬虫(通过定制正则表达式等语法),用于从特定的网页中提取自己需要的信息,即所谓的实体(Item)。 用户也可以从中提取出链接,让Scrapy继续抓取下一个页面。

代码目录结构

那么我的代码目录结构如下:

get_data:用于爬虫

items:定义类和属性,存储数据字段

middlewares:引擎

pipelines:存储数据

settings:负责进行框架的配置,比如爬虫名、机器协议、User-Agent均在此处配置

文件夹体育、汽车等负责存储不同类别的图片

run.py:启动scrapy爬虫,代替命令行进行启动。

爬虫代码

import scrapy
from lxml import etree
from xc.items import XcItem
headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36' }
class GetDataSpider(scrapy.Spider):
    n = 0
    name = 'get_data'
    allowed_domains = ['http://www.netbian.com/']
    start_urls = ['http://www.netbian.com/fengjing/']
    def start_requests(self):
        base_url = "http://www.netbian.com/fengjing/"
        for page in range(1,11):
            print(f"正在爬取第{page}页")
            url = base_url + 'index_'+str(page)+'.htm'
            yield scrapy.Request(url, callback=self.parse)
    def parse(self, response):
        import parsel
        import requests
        import re
        from bs4 import BeautifulSoup
        soup = BeautifulSoup(response.text, "html.parser")
        quotes = soup.find("div", class_='list').find_all("li")
        for i in quotes:
            url = str(i.find("img")).split('src="')[1].split(".jpg")[0] + ".jpg"
            response = requests.get(url, headers=headers)
            f = open('./风景/图'+url[-10:-3]+'.gif', 'wb')
            f.write(response.content)
            f.close()

这是get_data爬虫文件,体育.py与之代码相同,仅仅不同的是url,也就是说这个是爬风景图片,体育.py负责爬体育图片。

代码中的import关键字用于导入相关的库,

scrapy: Scrapy框架。
lxml: 用于解析HTML的库。
parsel: 用于解析HTML的库。
requests: 用于发送HTTP请求的库。
re: 用于正则表达式的库。
bs4: 用于解析HTML的库。

Xcitem 是从items导入的存储爬取下来的数据的类。

headers: 一个包含User-Agent的headers,用于模拟浏览器访问,防止被反爬虫策略识别。
Spider: GetDataSpider类继承了scrapy.Spider。name = 'get_data' 为Spider定义了一个名字,用于在Scrapy中标识和启动这个Spider。allowed_domains = ['http://www.netbian.com/'] 指定了只允许爬取 http://www.netbian.com/ 这个域名下的网页。start_urls 指定了Spider的起始URL,即从这里开始爬取。

定义start_requests方法: 这个方法用于为Spider生成请求。这里,它使用了一个循环,从1到10页(共10页),为每一页生成一个URL,并调用parse方法来解析网页内容。

定义parse方法: 这是Scrapy的核心方法,用于解析网页内容。这里,它使用parsel库来解析HTML,并使用BeautifulSoup来找到每个图片的URL。然后,它使用requests库来下载图片,并使用lxml库将其保存到本地。

注意: 在parse方法中,还有一些额外的代码,用于处理图片的下载和保存。这些代码不是Scrapy的核心部分,但它们是用于实现图片抓取和保存的必要步骤。还有类代码外的headers也不属于在这个位置,为了方便起见,我全在这写了。各位看官不要学习本人菜鸡做法。

总之,这部分代码实现了请求网页,再用bs4从网页中解析出每个图片的url并且下载到预先创建好的文件夹中。

pyqt

注册登录窗口

总的来说,这个代码创建了一个登录/注册的界面,包括用户名、密码输入框和两个按钮(登录和注册)。当用户点击登录按钮时,程序会尝试从文件accounts.txt中读取用户名和密码,并与输入的进行匹配。如果匹配成功,则显示登录成功的提示框并切换到操作页面。当用户点击注册按钮时,程序会将输入的用户名和密码追加到accounts.txt文件中,并显示注册成功的提示框。代码如下:

class LoginPage(QWidget):
    def __init__(self, parent=None):
        super(LoginPage, self).__init__(parent)
        self.setWindowTitle("登录/注册")
        self.setGeometry(600, 600, 600, 440)
        self.setWindowIcon(QIcon('web.png'))
        self.initUI()
        self.setLayout(QVBoxLayout())
        self.label_username = QLabel('用户名:')
        self.line_username = QLineEdit()
        self.label_password = QLabel('密码:')
        self.line_password = QLineEdit()
        self.button_login = QPushButton('登录')
        self.button_login.clicked.connect(self.login)
        self.button_register = QPushButton('注册')
        self.button_register.clicked.connect(self.register)
        self.layout().addWidget(self.label_username)
        self.layout().addWidget(self.line_username)
        self.layout().addWidget(self.label_password)
        self.layout().addWidget(self.line_password)
        self.layout().addWidget(self.button_login)
        self.layout().addWidget(self.button_register)
    @pyqtSlot()
    def login(self):
        username = self.line_username.text()
        password = self.line_password.text()
        with open('accounts.txt', 'r') as f:
            lines = f.readlines()
            for line in lines:
                if line.strip() == f'{username}:{password}':
                    QMessageBox.information(self, "登录成功", "欢迎," + username)
                    self.parent().setCurrentIndex(1)  # 切换到操作页面
                    return
        QMessageBox.information(self, "登录失败", "账号或密码错误")
    @pyqtSlot()
    def register(self):
        username = self.line_username.text()
        password = self.line_password.text()
        with open('accounts.txt', 'a') as f:
            f.write(f'{username}:{password}\n')
        QMessageBox.information(self, "注册成功", "注册成功,请牢记您的账号和密码")

LoginPage类: 这是一个继承自QWidget的类,用于创建登录页面。

初始化方法:
self.setWindowTitle("登录/注册"): 设置窗口标题为"登录/注册"。
self.setGeometry(600, 600, 600, 440): 设置窗口的位置和大小。
self.setWindowIcon(QIcon('web.png')): 设置窗口的图标。
self.initUI(): 调用initUI方法初始化UI。
self.setLayout(QVBoxLayout()): 设置窗口的布局为垂直布局。

initUI方法:
self.label_username = QLabel('用户名:'): 创建一个标签,显示"用户名:"。
self.line_username = QLineEdit(): 创建一个单行编辑框,用于输入用户名。
self.label_password = QLabel('密码:'): 创建一个标签,显示"密码:"。
self.line_password = QLineEdit(): 创建一个单行编辑框,用于输入密码。这个编辑框使用了QLineEdit的密文模式。
self.button_login = QPushButton('登录'): 创建一个按钮,显示"登录"。
self.button_login.clicked.connect(self.login): 当这个按钮被点击时,调用login方法。
self.button_register = QPushButton('注册'): 创建一个按钮,显示"注册"。
self.button_register.clicked.connect(self.register): 当这个按钮被点击时,调用register方法。
self.layout().addWidget(self.label_username): 将"用户名:"标签添加到布局中。
self.layout().addWidget(self.line_username): 将用户名编辑框添加到布局中。
self.layout().addWidget(self.label_password): 将"密码:"标签添加到布局中。
self.layout().addWidget(self.line_password): 将密码编辑框添加到布局中。
self.layout().addWidget(self.button_login): 将"登录"按钮添加到布局中。
self.layout().addWidget(self.button_register): 将"注册"按钮添加到布局中。

login方法: 这是QPushButton的槽函数,当"登录"按钮被点击时被调用。
username = self.line_username.text(): 获取用户名编辑框中的文本。
password = self.line_password.text(): 获取密码编辑框中的文本。
with open('accounts.txt', 'r'): 使用with语句打开文件,以只读模式打开'accounts.txt'文件。
lines = f.readlines(): 读取文件的所有行,并存储在lines列表中。
for line in lines:: 循环遍历文件的每一行。
if line.strip() == f'{username}:{password}':: 如果当前行的内容(去掉两端的空白字符)等于{username}:{password},则表示登录成功。
QMessageBox.information(self, "登录成功", "欢迎," + username): 显示一个提示框,显示"登录成功"和欢迎信息。
self.parent().setCurrentIndex(1): 切换到操作页面。

register方法: 这是QPushButton的槽函数,当"注册"按钮被点击时被调用。
username = self.line_username.text(): 获取用户名编辑框中的文本。
password = self.line_password.text(): 获取密码编辑框中的文本。
with open('accounts.txt', 'a'): 使用with语句打开文件,以追加模式打开'accounts.txt'文件。
f.write(f'{username}:{password}\n'): 将用户名和密码追加到文件中。
QMessageBox.information(self, "注册成功", "注册成功,请牢记您的账号和密码"): 显示一个提示框,显示"注册成功"和提示信息。

主要操作窗口

class MainWindow(QStackedWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle('Main Window')
        self.login_page = LoginPage(self)
        self.operation_page = QWidget()
        self.operation_page.setWindowTitle("注册/登录")
        self.operation_page.setGeometry(600, 600, 600, 440)
        # self.setWindowIcon(QIcon('web.png'))
        layout = QVBoxLayout()
        self.operation_page.setLayout(layout)
        self.operation_page.label = QLabel('请选择分类:')
        self.operation_page.comboBox = QComboBox()
        self.operation_page.comboBox.addItem('风景')
        self.operation_page.comboBox.addItem('体育')
        self.operation_page.comboBox.addItem('美女')
        self.operation_page.comboBox.addItem('影视')
        self.operation_page.comboBox.addItem('汽车')
        self.operation_page.comboBox.addItem('游戏')
        self.operation_page.button = QPushButton('爬取图片')
        self.operation_page.button.clicked.connect(self.get_images)
        self.operation_page.layout().addWidget(self.operation_page.label)
        self.operation_page.layout().addWidget(self.operation_page.comboBox)
        self.operation_page.layout().addWidget(self.operation_page.button)
        self.operation_label = QLabel('Welcome to the operation page!')
        layout.addWidget(self.operation_label)
        self.addWidget(self.login_page)
        self.addWidget(self.operation_page)
        self.setCurrentIndex(0)  # 初始显示登录页面
    def get_images(self):
        index = self.operation_page.comboBox.currentIndex()
        category = self.operation_page.comboBox.itemText(index)
        QMessageBox.information(self.operation_page, "提示", f"开始爬取 {category} 图片")
        # 这里调用你的爬虫函数,例如:
        self.select(category)
        self.setCurrentIndex(1)  # 初始显示登录页面
        QMessageBox.information(self.operation_page, "提示", f"爬取 {category} 图片结束")
    def select(self, category):
        args = "scrapy crawl "+category
        args =args.split()
        print(args)
        cmdline.execute(args)

这段代码定义了一个名为 MainWindow 的类,它继承自 QStackedWidget 类。QStackedWidget 是一个容器窗口,可以存放多个子窗口,但一次只能显示一个子窗口。这段代码实现了一个简单的图形用户界面(GUI)应用,包括两个页面:登录页面和操作页面。
登录页面(LoginPage):上节
操作页面(operation_page):
包含一个下拉列表框(QComboBox),用户可以从几个分类选项中选择一个。
有一个按钮(QPushButton),名为“爬取图片”。当用户点击这个按钮时,会调用 get_images 函数。
还有一个标签(QLabel),显示“欢迎来到操作页面!”。
get_images 函数是当用户点击“爬取图片”按钮时调用的。它首先获取下拉列表框中当前选中的分类,然后显示一个提示框告诉用户正在爬取该分类的图片。之后调用 self.select(category) 函数,该函数会执行一个命令行爬虫(使用 scrapy 库),爬取指定分类的图片。最后显示另一个提示框告诉用户图片爬取结束。
select 函数接收一个分类参数,并使用 cmdline.execute 函数执行一个命令行爬虫,爬取指定分类的图片。也就是我们选择什么分类,执行哪一个分类对应的爬虫。

运行退出

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

总目的是创建一个 QApplication 实例,显示 MainWindow 窗口,并进入应用程序的主事件循环。当用户关闭 MainWindow 窗口时,程序将退出

写在最后

如果有兄弟有需要,私信免费获取源码。

  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值