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

线程锁

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

创建锁
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.mzph.cn/bicheng/16939.shtml

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

相关文章

Linux如何设置共享文件夹

打开虚拟机->菜单->虚拟机设置->选项->共享文件夹->总是启用。点击添加按钮->弹出添加向导->点击浏览按钮&#xff0c;从windows中选择一个文件夹&#xff0c;确定即可。

[Windows] GIF动画、动图制作神器 ScreenToGif(免费)

ScreenToGif 是开源免费的 Gif 动画录制工具&#xff0c;小巧原生单文件&#xff0c;功能很实用。它有录制屏幕、录制摄像头、录制画板、图像编辑器等功能&#xff0c;可以将屏幕任何区域及操作过程录制成 GIF 格式的动态图像。保存前还可对 GIF 图像编辑优化&#xff0c;支持自…

末日设计1.00

故事背景: 在不远的未来&#xff0c;世界陷入了末日危机。资源枯竭、社会秩序崩溃&#xff0c;幸存者们为了生存&#xff0c;不得不拿起武器争夺每一寸土地和每一口食物。在这个混乱的世界中&#xff0c;你是一名传奇狙击手&#xff0c;凭借超凡的射击技巧和生存智慧&#xff0…

研二学妹面试字节,竟倒在了ThreadLocal上,这是不要应届生还是不要女生啊?

一、写在开头 今天和一个之前研二的学妹聊天&#xff0c;聊及她上周面试字节的情况&#xff0c;着实感受到了Java后端现在找工作的压力啊&#xff0c;记得在18&#xff0c;19年的时候&#xff0c;研究生计算机专业的学生&#xff0c;背背八股文找个Java开发工作毫无问题&#x…

本地图形客户端查看git提交历史 使用 TortoiseGit

要在本地查看提交记录和修改历史&#xff0c;可以使用 TortoiseGit 和 Git-SCM。这两个工具都提供了强大的功能来管理和查看 Git 仓库中的提交记录和历史修改。 使用 TortoiseGit 查看提交记录和修改历史 查看提交记录&#xff08;Log&#xff09;&#xff1a; 右键点击项目文…

抖音里卖什么最赚钱?4个冷门的高利润商品,还有谁不知道!

哈喽~我的电商月月 做抖音小店的新手朋友&#xff0c;一定很想知道&#xff0c;在抖音里卖什么最赚钱&#xff1f; 很多人都会推荐&#xff0c;日常百货&#xff0c;小风扇&#xff0c;女装&#xff0c;宠物用品等等&#xff0c;这些商品确实很好做&#xff0c;你们可以试试 …

Euraka详解:实现微服务架构的关键组件

在当今互联网时代&#xff0c;微服务架构已经成为许多企业构建和部署应用程序的首选方法之一。而要在微服务架构中实现高可用性和灵活性&#xff0c;服务发现和注册是至关重要的一环。Eureka作为Netflix开源的服务发现组件&#xff0c;为实现这一目标提供了高效可靠的解决方案。…

备忘录可以统计字数吗?备忘录里在哪查看字数?

在这个信息爆炸的时代&#xff0c;很多人喜欢使用备忘录app来记录生活中的点点滴滴。备忘录不仅可以帮助我们记事、安排日程&#xff0c;还能提醒我们完成各种任务&#xff0c;是我们日常生活中不可或缺的小助手。 然而&#xff0c;在使用备忘录时&#xff0c;有时我们会遇到需…

不用BookStack的企业都在用什么知识库软件

现如今&#xff0c;越来越多的企业使用知识库软件对企业内部知识进行管理。BookStack作为一款功能强大的开源知识库软件&#xff0c;成为很多企业的首选。但是还是有一部分人群认为BookStack不适合他们的企业那么他们都是在用什么别的知识库软件呢&#xff1f;LookLook同学今天…

《python本机环境多版本切换》-两种方式以及具体使用--venv/pyenv+pycharm测试

阿丹&#xff1a; source myenv/bin/activate 在开发使用rasa的时候发现自己安装的python环境是3.12的&#xff0c;和rasa不兼容&#xff0c;所以实践一下更换多python环境。 使用虚拟环境 在Python中使用虚拟环境来切换Python版本是一个常见的做法&#xff0c;这可以帮助你…

Minikube部署单节点Kubernetes

1.1 Minikube部署单节点K8s Minikube是由Kubernetes社区维护的单机版的Kubernetes集群&#xff0c;支持macOS, Linux, andWindows等多种操作系统平台&#xff0c;使用最新的官方stable版本&#xff0c;并支持Kubernetes的大部分功能&#xff0c;从基础的容器编排管理&#xff0…

实用篇| huggingface网络不通

之前文章《Transformer原理》中介绍过,Transformers 是由 Hugging Face 开发的一个包&#xff0c;支持加载目前绝大部分的预训练模型。随着 BERT、GPT 等大规模语言模型的兴起&#xff0c;越来越多的公司和研究者采用 Transformers 库来构建应用。 Hugging Face是一家美国公司…

Easy IP + DNAT(服务器NAT转换)

第一章 Easy IP 1.1 一般家庭和企业使用的地址转换方式 直接使用出接口的地址做转换Easy IP适用于小规模居于网中的主机访问Internet的场景如&#xff1a;家庭、小型网吧、小型办公室中&#xff0c;这些地方内部主机不多&#xff0c;出接口可以通过拨号方式获取一个临时公网I…

2.Nginx上配置图片访问

在 Nginx 上配置图片访问涉及到在 Nginx 配置文件中添加相应的 location 块来处理图片请求。以下是一个基本的示例&#xff0c;演示如何配置 Nginx 以便在指定目录中存储和访问图片。 1.上传图片到服务器 首先&#xff0c;将你的图片上传到服务器的某个目录&#xff0c;例如 …

视频监控汇聚平台LntonCVS通过GB/T28181国标协议实现视频监控平台的级联方案

近年来&#xff0c;随着网络视频监控应用范围的拓展&#xff0c;越来越多的政府部门和跨区域行业单位对视频监控的需求已经不局限于本地联网监控。他们正在探索在原有的本地联网监控基础上&#xff0c;建设省级乃至全国范围内的跨区域监控联网&#xff0c;以全面打造数据共享平…

BUUCTF靶场[Reverse]内涵的文件、新年快乐

[reverse]内涵的文件 文件运行看一下 老规矩&#xff0c;拿到文件先用DIE查有没有壳 没有壳&#xff0c;且是一个32位的文件&#xff0c;用相对应的IDA打开 &#xff0c;有主函数&#xff08;mian&#xff09;&#xff0c;先点开 这里点开&#xff08;mian_0&#xff09;,发现…

Kotlin基础之基本语法

Kotlin 简介 Kotlin 是一种由 JetBrains 开发的静态类型编程语言&#xff0c;设计用于与 Java 虚拟机 (JVM) 兼容&#xff0c;同时也可用于 Android、JavaScript&#xff08;通过 Kotlin/JS&#xff09;和原生&#xff08;通过 Kotlin/Native&#xff09;开发。Kotlin 旨在提供…

【详细介绍WebKit的结构】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

springboot + es7.12.3 elasticsearchRestTemplate使用记录

private BoolQueryBuilder getQueryBuilder(QueryCollectWaterDataPageRequestVO requestVO) {BoolQueryBuilder queryBuilder QueryBuilders.boolQuery();if (!CollectionUtils.isEmpty(requestVO.getCompanyIds())) {//termsQuery 精确查找corpId字段为精确的多个值&#xf…

T-Sql 中断正在连接的数据库的客户端并移除数据库

USE master;-- 查找连接到数据库 OGS_PlugPower 的会话ID&#xff08;SPID&#xff09; DECLARE SessionID INT;SELECT SessionID session_id FROM sys.dm_exec_sessions WHERE database_id DB_ID(OGS_PlugPower);-- 使用会话ID&#xff08;SPID&#xff09;中断连接 IF Sess…