【Python_requests学习笔记(九)】基于requests和threading模块实现多线程爬虫

2023-11-17

基于requests和threading模块实现多线程爬虫

前言

此篇文章中介绍基于 requests 和 threading 模块实现多线程爬虫,并以 抓取Cocos中文社区中:热门主题下的帖子名称及id数据 为例进行讲解;因主要介绍如何使用多线程,所以爬取网页数据的方法可以参考:【Python_requests学习笔记(七)】基于requests模块 实现动态加载数据的爬取,下面直接进入正文。

正文

直接以代码为例进行讲解

1、程序实现

  1. 初始化函数
        def __init__(self):
            self.url = "https://forum.cocos.org/top.json?page={}&per_page=50"  # url地址
            self.q = Queue()  # 创建队列
            self.lock = Lock()  # 创建线程锁
    
    a、创建队列,是为了存放需要爬取网页的 url 地址;
    b、创建线程锁,是为了防止多个线程在同时操作队列时,即 self.q 出现异常。
    
  2. 队列函数
    def url_in(self):
        """
        function:  url地址入队列函数
              in:  None
             out:  None
          return:  int >0 ok, <0 some wrong
          others:  url Queue Func
        """
        for page in range(10):  # 爬取10页
            url = self.url.format(page)  # 创建所有需要抓取的url地址
            self.q.put(url)  # 入队列
  1. 多线程事件函数
    def pares_html(self):
        """
        function:  线程的事件函数:获取url,请求,解析,处理数据
              in:  None
             out:  None
          return:  int >0 ok, <0 some wrong
          others:  The Event Function Of The Thread
        """
        while True:
            self.lock.acquire()  # 上锁
            if not self.q.empty():  # 判断队列是否为空
                url = self.q.get()  # 出队列
                self.lock.release()  # 释放锁
                headers = {"User-Agent": UserAgent().random}  # 构造随机请求头
                html = requests.get(url=url, headers=headers).json()  # 获取响应内容
                item = {}  # 定义一个空字典
                for dic in html["topic_list"]["topics"]:
                    item["id"] = dic["id"]
                    item["名称"] = dic["title"]
                    print(item)
                print("**********")
            else:  # 当队列为空时,已经上锁未释放,所以需要释放锁
                self.lock.release()  # 释放锁
                break
a、while循环是为了元素出队列的操作,当队列为空时,说明需要爬取的网页已经爬取完成,即可终止循环;
b、上锁和释放锁在元素出队列前后,每进行一次循环前要上锁,防止两个线程同时操作队列,当元素出队列后立即释放锁,让其他线程从队列中取 ur l地址;
c、注意:当队列为空时也需要释放锁,不然会造成堵塞。
  1. 程序入口函数
    def run(self):
        """
        function:  程序入口函数
              in:  None
             out:  None
          return:  None
          others:  Program Entry Func
        """
        self.url_in()  # 先让url地址入队列
        t_list = []  # 创建多线程
        for i in range(1):  # 创建3个线程
            t = Thread(target=self.pares_html)  # 线程实例化
            t_list.append(t)
            t.start()  # 线程开启
        for t in t_list:
            t.join()  # 线程同步
创建线程实例后,要开启线程。

2、完整代码

import time
import requests
from queue import Queue
from threading import Thread, Lock
from fake_useragent import UserAgent


class CocosSpiderThread:
    """
    基于requests和threading实现多线程爬虫:
    多线程爬取Cocos中文社区中:热门主题下的帖子名称及id数据
    """

    def __init__(self):
        self.url = "https://forum.cocos.org/top.json?page={}&per_page=50"  # url地址
        self.q = Queue()  # 创建队列
        self.lock = Lock()  # 创建线程锁

    def url_in(self):
        """
        function:  url地址入队列函数
              in:  None
             out:  None
          return:  int >0 ok, <0 some wrong
          others:  url Queue Func
        """
        for page in range(10):  # 爬取10页
            url = self.url.format(page)  # 创建所有需要抓取的url地址
            self.q.put(url)  # 入队列

    def pares_html(self):
        """
        function:  线程的事件函数:获取url,请求,解析,处理数据
              in:  None
             out:  None
          return:  int >0 ok, <0 some wrong
          others:  The Event Function Of The Thread
        """
        while True:
            self.lock.acquire()  # 上锁
            if not self.q.empty():  # 判断队列是否为空
                url = self.q.get()  # 出队列
                self.lock.release()  # 释放锁
                headers = {"User-Agent": UserAgent().random}  # 构造随机请求头
                html = requests.get(url=url, headers=headers).json()  # 获取响应内容
                item = {}  # 定义一个空字典
                for dic in html["topic_list"]["topics"]:
                    item["id"] = dic["id"]
                    item["名称"] = dic["title"]
                    print(item)
                print("**********")
            else:  # 当队列为空时,已经上锁未释放,所以需要释放锁
                self.lock.release()  # 释放锁
                break

    def run(self):
        """
        function:  程序入口函数
              in:  None
             out:  None
          return:  None
          others:  Program Entry Func
        """
        self.url_in()  # 先让url地址入队列
        t_list = []  # 创建多线程
        for i in range(3):  # 创建3个线程
            t = Thread(target=self.pares_html)  # 线程实例化
            t_list.append(t)
            t.start()  # 线程开启
        for t in t_list:
            t.join()  # 线程同步


if __name__ == '__main__':
    start_time = time.time()  # 记录开始时间
    spider = CocosSpiderThread()
    spider.run()
    end_time = time.time()  # 记录结束时间
    print("time:%.2fs" % (end_time - start_time))  # 打印总用时

3、实现效果

3个线程爬取:用时1.60s
在这里插入图片描述
1个线程爬取:用时3.98s
在这里插入图片描述
可以看到爬取的时间是有所缩短的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Python_requests学习笔记(九)】基于requests和threading模块实现多线程爬虫 的相关文章

随机推荐

  • java.io.IOException: read failed, socket might closed or timeout, read ret: -1

    好吧 重要的事情说三遍 连接蓝牙前关闭蓝牙搜索 连接蓝牙前关闭蓝牙搜索 连接蓝牙前关闭蓝牙搜索
  • 补码加减运算及判断溢出方法

    一 补码加减运算 二 判断溢出方法 1 符号位判溢出方法 对于加减运算 两个异号数相加或者两个同号数相减 结果的绝对值一定比任何一个数的绝对值要小 不会发生上溢出 两个异号数相减或者两个同号数相加的绝对值肯定比任何一个数要大 可能发生溢出
  • UE4的视频播放(Media Player)

    1 视频播放Begining 首先将需要播放的视频拖入 创建Media Player和Media Texture 创建Material 将材质改为User Interface 在UI界面 创建Image 将这个材质装入 在人物Pawn界面添
  • FriendlyDesktop系统烧写,SOM-RK3399/NanoPC T4烧录系统

    SOM RK3399 SOM RK3399 V2 NanoPC T4的系统是通用的 由于Type C烧写有蛮大的概率会识别不成功 实测 所以建议使用SD卡脱机烧写 友善之臂提供了几种系统支持 android7 8 10 FriendlyCo
  • Redis概述与安装

    Redis简介 首先 简单了解一下NoSQL Not only sql 不要错误的理解为 没有SQL 而是不仅仅是SQL NoSQL工具也是一种简易的数据库 它主要是基于内存的数据库 并提供一定的持久化功能 现在有很多这种技术如 memca
  • VS2022·初尝试评测(非专业测评)

    阅文时长 0 59分钟 字数统计 956 8字符 主要内容 1 引言 背景 2 载入界面 UI图标等细节 3 加载项目时间对比 4 编译项目时间对比 5 声明与参考资料 VS2022 初尝试评测 非专业测评 编写人 SCscHero
  • Python3快速入门(六)——Python3面向对象

    Python3快速入门 六 Python3面向对象 一 面向对象技术简介 1 面向对象简介 面向对象编程 Object Oriented Programing OOP 是一种编程思想 OOP把对象当成程序的一个基本单元 一个对象包含数据和操
  • springboot配置RabbitMQ时,本地正常,远程连接RabbitMQ却无法生成Queue,Exchange

    RabbitMQ 在springboot中 无法正确操作远程服务器的问题 问题描述 如果你已经确定你的IP正确 端口号也是5672 账号没有使用默认的guest账号 但是还是没有连接上远程的RabbitMQ 可能是你的springboot配
  • int8,FLOPS,FLOPs,TOPS 等具体含义

    1 定义 算力的计量单位FLOPS Floating point operations per second FLOPS表示每秒浮点的运算次数 具体使用时 FLOPS前面还会有一个字母常量 例如TFLOPS PFLOPS 这个字母T P代表
  • 翻页特效原理

    http www open open com lib view 1326265166952 实现真实的翻页效果 为了能在翻页的过程中看到下一页的内容 在翻页之前必须准备两张页面 一张是当前页 另一张是下一页 翻页的过程就是对这两张页面的剪切
  • SAGE(SAGEMATH)密码学基本使用方法

    求逆元 inv inverse mod 30 1373 print 30 inv 1373 1 扩展欧几里得算法 d u v xgcd 20 30 print d 0 u 1 v 2 format d u v d 10 u 1 v 1 孙子
  • win10系统显示打印机未连接到服务器,解决win10提示“Windows无法连接到打印机”的方法...

    打印机是我们办公室中必备的设备 如今各种打印方式也是层出不穷 最近有用户在使用win10系统进行打印的时候遇到了这样的提示信息 windows 无法连接到打印机 在更详细的信息提示界面中已经告诉我们是由于本地打印店额后台服务程序没有启用导致
  • void、void 的使用

    void的使用 1 对函数返回值的限定 函数无返回值 void test int a int num a 2 void 限定函数的返回值为任意类型的指针 void test int a 5 int p a return p 3 对函数参数的
  • ASCII unicode utf8 编码、解码的那些事

    ASCII unicode gbk utf8 编码 解码的那些事 对应编码这块一直处于一种懵懵懂懂的状态 有的时候去查了资料 当下理解了 过一段时间又遗忘了 今天又重新查阅了一番资料 记录一下所感所悟 阮一峰老师 关于编码的总结 1 ASC
  • 【学一点儿前端】box-sizing以及flex:1的解释

    box sizing box sizing 是一种用于控制CSS盒子模型行为的CSS属性 它的作用是指定元素的宽度和高度的计算方式 以确定元素的总尺寸 具体来说 box sizing 可以有两个可能的取值 1 content box 默认值
  • hive加载数据权限报错

    前提 上传数据至hdfs 的 user root 下 创建了hive的orc表 准备load数据 创建了临时的ordertmp的textfile格式表 后面用insert overwrite进目标表 执行load data 从 user r
  • 2020-06-07

    Arcgis engine实现栅格运算功能 有大佬能帮助一下吗 arcgis是10 2版本的 环境是vs2015
  • linux的-Mtime 命令

    我在写shell脚本的时候 定时删除一些文件的时候 也经常用得到 mtime这个参数 所以打算好好看看 把它弄明白一下 man find里的解释 mtime n File s data was last modified n 24 hour
  • java ee 运行环境_EE质量检查:为我们的网站开发和运行自动测试

    java ee 运行环境 Introduction 介绍 This article is the last of three articles that explain why and how the Experts Exchange QA
  • 【Python_requests学习笔记(九)】基于requests和threading模块实现多线程爬虫

    基于requests和threading模块实现多线程爬虫 前言 此篇文章中介绍基于 requests 和 threading 模块实现多线程爬虫 并以 抓取Cocos中文社区中 热门主题下的帖子名称及id数据 为例进行讲解 因主要介绍如何