爬虫学习--15.进程与线程(2)

news2024/9/22 19:37:17

线程锁

当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制 某个线程要更改共享数据时,先将其锁定,此时资源的状态为"锁定",其他线程不能改变,只到该线程释放资源,将资源的状态变成"非锁定",其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

创建锁
mutex = threading.Lock()
​
锁定
mutex.acquire()
​
解锁
mutex.release()

Queue线程

在线程中,访问一些全局变量,加锁是一个经常的过程。如果你是想把一些数据存储到某个队列中,那么Python内置了一个线程安全的模块叫做queue模块。Python中的queue模块中提供了同步的、线程安全的队列类,包括FIFO(先进先出)队列Queue,LIFO(后入先出)队列LifoQueue。这些队列都实现了锁原语(可以理解为原子操作,即要么不做,要么都做完),能够在多线程中直接使用。可以使用队列来实现线程间的同步。

初始化Queue(maxsize):创建一个先进先出的队列。
empty():判断队列是否为空。
full():判断队列是否满了。
get():从队列中取最后一个数据。
put():将一个数据放到队列中。

生产者与消费者模式

生产者和消费者模式是多线程开发中常见的一种模式。通过生产者和消费者模式,可以让代码达到高内聚低耦合的目标,线程管理更加方便,程序分工更加明确。 生产者的线程专门用来生产一些数据,然后存放到容器中(中间变量)。消费者在从这个中间的容器中取出数据进行消费

使用单线程下载表情包

 

import re
import requests
from urllib.request import urlretrieve
from lxml import etree
"""
将http://www.godoutu.com/face/hot/page/1.html下10页数据的表情包全部抓取
print(45*1801)  8w多条数据 
图片数据 二进制  
保存   
with open  wb模式  
urllib
找到图片的路径  图片名字  
"""
for i in range(1,2):
    url = f'http://www.godoutu.com/face/hot/page/{i}.html'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    response.encoding = 'utf-8'
    html = response.text
    # print(html)
    # xpath对象
    element = etree.HTML(html)
    alldiv = element.xpath('//div[@class="ui segment imghover"]/div[@class="tagbqppdiv"]')
    # print(alldiv,len(alldiv))
    for j in alldiv:
        everyhref = j.xpath('./a/img/@data-original')[0]
        # print(everyhref)
        title = j.xpath('./a/@title')[0]  # 必须要是合法的
        # print(title)
        newtitle = re.sub('[\/:*?<>|]','',title)
        # print(type(newtitle),type(everyhref))
        # 保存 jpg  gif
        if str(everyhref).endswith('jpg'):
            urlretrieve(everyhref,f'images/{newtitle}.jpg')
            print(f'{newtitle}.jpg下载成功!')
        else:
            urlretrieve(everyhref, f'images/{newtitle}.gif')
            print(f'{newtitle}.gif下载成功!')

使用生产者与消费者模式下载表情包

 

import threading
import time
import re
import requests
from lxml import etree
from queue import Queue
from urllib.request import urlretrieve

# 生产者模型
class Producer(threading.Thread):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36'
    }

    def __init__(self, page_queue,img_queue ):  # RuntimeError: thread.__init__() not called
        # 在自写的类中的init中,先初始化Thread
        threading.Thread.__init__(self)  # 或则 super().__init__()
        self.page_queue = page_queue
        self.img_queue = img_queue

    def run(self):
        while True:  # 让我们创建的三个生产者一直工作
            if self.page_queue.empty():
                break
            else:
                url = self.page_queue.get()
                print(url)
            # 获取到了url就可以去解析数据了
            self.Parse_html(url)
    def Parse_html(self,url):
        # 上锁
        lock.acquire()
        # 发请求,获取响应
        res = requests.get(url, headers=self.headers)
        text = res.text
        # 随机延迟
        # time.sleep(random.random())
        # 解析数据,拿真的图片地址
        element = etree.HTML(text)

        # 将获取的所有img标签放到列表里面
        alldiv = element.xpath('//div[@class="ui segment imghover"]/div[@class="tagbqppdiv"]')

        # 解锁
        lock.release()
        # 取出每一个图片的地址
        for j in alldiv:
            everyhref = j.xpath('./a/img/@data-original')[0]
            print(everyhref)
            title = j.xpath('./a/@title')[0]  # 必须要是合法的
            print(title)
            newtitle = re.sub('[\/:*?<>|]', '', title)
            # 将获取到的img_url和title数据存放在另一个队列种然后再交给消费者进行处理
            self.img_queue.put((everyhref,newtitle)) # 用元组打包作为整体进行处理
            # 检测我获取的数据量是否正确
        print(self.img_queue.qsize())

# 消费者模型
class Consumer(threading.Thread):
    def __init__(self, img_queue):  # RuntimeError: thread.__init__() not called
        # 在自写的类中的init中,先初始化Thread
        threading.Thread.__init__(self)  # 或则 super().__init__()
        self.img_queue = img_queue

    def run(self):
        while True:  # 让我们创建的三个生产者一直工作
            if self.img_queue.empty():
                break
            else:
                img_data = self.img_queue.get()  # 元组类型数据
            # 解包
            img_url, filename = img_data
            # 下载操作
            if str(img_url).endswith('jpg'):
                urlretrieve(img_url, f'imagesss/{filename}.jpg')
                print(f'{filename}.jpg下载成功!')
            else:
                urlretrieve(img_url, f'imagesss/{filename}.gif')
                print(f'{filename}.gif下载成功!')

# 程序主入口

if __name__ == '__main__':
    # 创建一把锁
    lock = threading.Lock()

    # 1 将所有的url存放在队列中
    page_queue = Queue()  # 创建一个队列 然后通过put方法存放进去

    #  创建一个存放数据的队列
    img_queue = Queue()  # 同样将这个队列通过init初始化传到生产者模型中

    for i in range(1, 11):
        url = f'http://www.godoutu.com/face/hot/page/{i}.html'
        page_queue.put(url)

    p_list = []
    # 2 创建生产者对象  三个
    for i in range(3):
        t = Producer(page_queue,img_queue)  # 将队列传给生产者处理 那再创建对象进行传参的过程中我们需要进行接收 init
        t.start()  # 开启多线程   执行的是run方法
        p_list.append(t)

    for p in p_list:
        p.join()

    # 创建三个消费者
    for j in range(3):
        t = Consumer(img_queue)
        t.start()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1702075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PXI总线测试模块-6939 矢量信号发生器

频率范围&#xff1a;250kHz&#xff5e;6GHz 6939 矢量信号发生器 6939矢量信号发生器提供频率范围250kHz~6GHz的多制式信号&#xff0c;单边带相位噪声优于-120dBc/Hz10kHz&#xff08;载波1GHz&#xff09;、EVM优于1.0%&#xff0c;能够实现高纯连续波输出、模拟调制信号输…

贝叶斯:共轭先验(conjugacy)

共轭先验与共轭分布 在贝叶斯统计中&#xff0c;如果后验分布与先验分布属于同类&#xff0c;则先验分布与后验分布被称为共轭分布&#xff0c;而先验分布被称为似然函数的共轭先验。&#xff08;要求后验分布与先验分布是同类分布&#xff0c;不要求似然函数分布相同。&#…

Linux系统编程——基础IO与文件描述符(管理已打开的内存文件)

目录 一&#xff0c;文件预备 二&#xff0c;C语言文件操作函数 2.1 默认打开的三个流 2.2 写文件 2.3 读文件 2.4 再次理解当前路径 三&#xff0c;Linux操作文件系统调用 3.1 open()和close() 3.1.1 第一个参数 3.1.2 *第二个参数 3.1.3 第三个参数 3.2 write(…

深度解析 Spring 源码:探秘 CGLIB 代理的奥秘

文章目录 一、CGLIB 代理简介1.1 CGLIB 代理的基本原理和特点1.2 分析 CGLIB 如何通过字节码技术创建代理类 二、深入分析 CglibAopProxy 类的结构2.1 CglibAopProxy 类结构2.2 CglibAopProxy 类源码 三、CGLIB 代理对象的创建过程3.1 配置 Enhancer 生成代理对象3.2 探讨如何通…

如何解包 Python 恶意可执行文件

使用 Python 编写的程序通常以源码的形式发布&#xff0c;也可以将所有依赖都打包到一个可执行文件中。那么如何解包 Python 恶意可执行文件呢&#xff1f; 打包 打包与加壳不同&#xff0c;打包 Python 程序的目的是创建一个可以在操作系统上独立运行的可执行文件。使用例如 …

光伏开发是用什么工具提高效率?

随着全球对可再生能源的日益重视&#xff0c;光伏产业作为其中的佼佼者&#xff0c;已经取得了长足的发展。然而&#xff0c;如何提高光伏开发的效率&#xff0c;降低成本&#xff0c;成为了业内关注的焦点。本文将探讨光伏开发过程中所使用的工具&#xff0c;以及这些工具如何…

C#多维数组不同读取方式的性能差异

背景 近来在优化一个图像显示程序&#xff0c;图像数据存储于一个3维数组data[x,y,z]中&#xff0c;三维数组为一张张图片数据的叠加而来&#xff0c;其中x为图片的张数&#xff0c;y为图片行&#xff0c;Z为图片的列&#xff0c;也就是说这个三维数组存储的为一系列图片的数据…

监管端..

文章目录 1. 登录流程2. 日志AOP 1. 登录流程 使用账号&#xff08;手机号&#xff09;、密码、验证码。登录就是获取token的&#xff0c;输入的账号密码用RSA加密&#xff08;非对称&#xff09; 首先输入账号密码&#xff0c;在发送手机验证码时候先校验账号密码有没有输入…

Python筑基之旅专栏(导航)

目录 一、Python筑基之旅专栏博文清单及链接 二、推荐阅读 一、Python筑基之旅专栏博文清单及链接 01、溯源及发展 02、变量和数据类型 03、搭建Python开发环境及库 04、两个重要函数/列表/元组 05、字符串(一) 06、字符串(二) 07、字符串(三) 08、字典 09、集合 10…

MySQL--存储引擎

一、存储引擎介绍 1.介绍 存储引擎相当于Linux的文件系统&#xff0c;以插件的模式存在&#xff0c;是作用在表的一种属性 2.MySQL中的存储引擎类型 InnoDB、MyISAM、CSV、Memory 3.InnoDB核心特性的介绍 聚簇索引、事务、MVCC多版本并发控制、行级锁、外键、AHI、主从复制特…

springboot+vue2+elementui实现时间段查询

1.前端代码 使用elementui的时间段选择器&#xff1a; <el-date-picker v-model"queryPage.itemTime" type"daterange"value-format"yyyy-MM-dd" class"filter-item" range-separator"至" start-placeholder"创建…

(2024,基于熵的激活函数动态优化,具有边界条件的最差激活函数,修正正则化 ReLU)寻找更优激活函数

A Method on Searching Better Activation Functions 公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 3. 动机 4. 方法论 4.1 问题设定 4.1.1 贝叶斯错误率和信息熵 4.1.2 激活…

关于linux磁盘告警问题

案例&#xff1a;我们在执行df命令时&#xff0c;查看到磁盘利用率很高&#xff0c;但是到相对应的目录执行du -sh *来找大文件时进行删除时&#xff0c;发现各个目录相加并不大&#xff0c;如下图&#xff1a; 使用df命令查看到根(/)目录使用到33G&#xff0c;而du命令显示只使…

IBM db2数据库初体验(有图有真相保姆级教程)

前提摘要: 直接安装的是windows 系统版本, 没有安装可视化操作数据库的工具, 直接使用windows中类似cmd窗口输入命令进行操作 1. 安装好windows版本后, 鼠标单击windows最左下角的windows图标, 找到IBM DB2文件夹--> 选择单击展开下拉款--> 单击选中DB2命令窗口, 会出现…

在没有dubbo-admin情况下如何判断zk中注册的dubbo服务是否注册成功

通常我们都是通过dubbo-admin来查看dubbo服务是否注册成功&#xff0c;那么如果没有部署dubbo-admind的情况下&#xff0c;我们如何来判断dubbo服务是否注册成功&#xff1a; 一、首先我们进入到zookeeper bin目录下使用以下指令连接到zk: ./zkCli.sh -server ip:port ip&…

强大的医院绩效考核管理系统源码,支持行业内所有绩效方案,且每步核算都可自主进行方案的新建、调整。

医院绩效考核管理系统是采用B/S架构模式设计、使用JAVA语言开发、后台使用MySql数据库进行管理的一整套计算机应用软件源码。 系统和his系统进行对接&#xff0c;按照设定周期&#xff0c;从his系统获取医院科室和医生、护士、其他人员工作量&#xff0c;对没有录入信息化系统…

从Python代码到pip包:打包Python项目

大家好&#xff0c;在软件开发的世界中&#xff0c;共享和重用代码是至关重要的。Python社区为我们提供了丰富的资源&#xff0c;使得我们能够轻松地与他人分享我们的工作&#xff0c;并从他人的工作中受益。将代码打包成pip包&#xff08;Python包管理器&#xff09;是一种常见…

函数调用时长的关键点:揭秘参数位置的秘密

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、默认参数的秘密 示例代码 二、关键字参数与位置参数的舞蹈 示例代码 总结 一、默认参…

如何编辑 PDF 中的文本

使用 PDF 格式时最常见的挑战之一是弄清楚如何编辑 PDF 文档中的现有文本。该问题不仅影响新手&#xff0c;还影响多年来处理各种文档的专业人士。 PDF 格式专为处理数字纸张而设计。它以原始形式保留所有数据&#xff0c;例如表格、图章和签名。对于需要安全可靠地分发文档的…

香橙派 Kunpeng Pro 上手初体验

香橙派 Kunpeng Pro 上手初体验 目录 香橙派 Kunpeng Pro 上手初体验1.前言2.开箱3.开发板资源介绍硬件规格参数外观规格参数4.系统环境搭建系统镜像烧录ssh连接5.简单测试6.总结 1.前言 我很荣幸能收到了来自CSDN的测评邀请&#xff0c;让我有机会对香橙派最新推出的Kunpeng …