Python多线程爬虫入门:让你的爬虫跑得更快

一、前言

在互联网时代,数据是最有价值的资源之一。而网页爬虫是获取数据的一种非常重要的工具。在这篇文章中,我们将学习如何用 Python 编写一个多线程网页爬虫,适合小白快速上手!

二、多线程进程

单线程串行:一步一步做事情

单线程程序一次只能执行一个任务。所有任务按顺序执行,下一个任务必须等待当前任务完成。这种方式实现简单,但效率较低,尤其是在处理需要等待(如 I/O 操作)的时候。

多线程并发:同时做多件事

多线程允许程序同时执行多个任务。对于 I/O 密集型任务(如文件读写、网络请求等),多线程可以大幅提高效率,因为线程在等待 I/O 完成时可以切换到其他任务。
多进程并行:每个任务单独运行在一个进程中

多进程类似于多线程,但每个任务运行在独立的进程中,拥有自己的内存空间。多进程适用于 CPU 密集型任务(如计算密集型操作),因为多个进程可以充分利用多核 CPU 的能力。

三、python多线程的使用

1、python创建多线程的方法

使用 threading.Thread 创建线程,这是最基本的方式,直接创建 Thread 对象并启动线程。

import  threading  # 导入线程模块,用于创建和管理线程
import time  # 导入时间模块,用于添加延迟

# 定义两个线程要执行的函数
def print_hello():
    for _ in range(10):
        print("hello")
        time.sleep(0.2) # 休眠0.2秒,模拟延迟,确保线程交替执行

def print_world():
    for _ in range(10):
        print("world")
        time.sleep(0.1) # 休眠0.1秒,模拟延迟,确保线程交替执行

# 创建线程对象
hello = threading.Thread(target=print_hello)
world = threading.Thread(target=print_world)

# 启动线程
hello.start()
world.start()

# 等待线程执行完毕
hello.join()
world.join()

四、改写爬虫程序,变成多线程爬取

1、写一个爬虫程序,爬取博客园的网页

import threading  # 导入线程模块,用于创建和管理线程
import time  # 导入时间模块,用于延迟操作
import requests  # 导入requests库,用于发送HTTP请求

# 创建一个包含50个URL的列表,URL是通过格式化字符串生成的
# 这些URL指向博客园的不同页面
urls = [f"https://www.cnblogs.com/#p{page}" for page in range(1, 50+1)]

# 定义一个函数,接受一个URL作为参数,爬取该URL的内容
def craw(url):
    r = requests.get(url)  # 发送GET请求到指定的URL
    print(url, len(r.text))  # 打印URL以及响应内容的长度(即页面的字符数)

# 调用craw函数,爬取第一个URL,打印该页面的内容长度
craw(urls[0])

 2、接下来我们写我们的线程函数,首先写单线程的函数

def single_thread():# 定义一个函数 single_thread,用于单线程爬取多个 URL
    print("single_thread begin")
    for url in urls:# 遍历 urls 列表中的每个 URL,调用 craw 函数进行爬取
        craw(url)
    print("single_thread end")

# 调用 single_thread 函数,开始执行单线程爬取任务
single_thread()

 3、继续写我们的多线程函数

def multi_thread():# 定义一个函数 multi_thread,用于通过多线程爬取多个 URL
    print("多线程 开始")
    threads = []

    for url in urls:# 遍历 urls 列表中的每个 URL,创建一个线程并将其添加到 threads 列表
        threads.append(threading.Thread(target=craw, args=(url,)))
    # 启动所有线程
    for thread in threads:
        thread.start()
    # 等待所有线程完成
    for thread in threads:
        thread.join()

    print("多线程 结束")
# 调用 multi_thread 函数,开始执行多线程爬取任务
multi_thread()

4、速度对比

在单线程与多线程中,爬取相同的内容的时间肯定是不同的,此时我们就可以使用time模块来进行计时,分别统计单线程爬取的时间与多线程爬取的时间进行对比

if __name__ == '__main__':   # 判断是否是直接运行当前脚本。如果是,下面的代码将执行。如果是作为模块导入,则不会执行。
    start = time.time()  # 记录当前时间(单线程开始前的时间),用于计算单线程执行时间
    single_thread()  # 调用 single_thread 函数,开始执行单线程任务
    end = time.time()  # 记录当前时间(单线程结束后的时间)
    print(f"单线程需要时间{end - start}second")  # 打印单线程执行时间,end - start 计算出程序执行所需的时间

    start = time.time()
    multi_thread()
    end = time.time()
    print(f"多线程需要时间{end - start}second")

时间对比:

 

经过对比,我们可以发现,使用多线程的爬虫速度比单线程快了20多倍!当然,具体性能提升的幅度也取决于任务的类型和网络条件,但可以肯定的是,掌握多线程爬虫将让你在爬取大量网页时事半功倍。

多线程不是万能的,它适用于 I/O 密集型任务,对于 CPU 密集型的计算任务,可能多进程更合适。但是在爬虫的场景下,多线程无疑是提高效率的好帮手。

五、代码编写实现生产者消费者爬虫

继续使用上节课的代码来进行,首先改写我们的craw函数,让函数返回获取到的url文本,代码如下:

import threading  # 导入线程模块,用于实现并发操作
import time  # 导入时间模块,便于控制程序的执行时间
import requests  # 导入requests库,用于发送HTTP请求获取网页内容
from bs4 import BeautifulSoup  # 导入BeautifulSoup库,用于解析HTML网页

# 生成需要爬取的多个URL地址,创建一个包含50个页面的URL列表
urls = [f"https://www.cnblogs.com/#p{page}" for page in range(1, 50+1)]

# 生产者函数:发送HTTP请求并获取网页的HTML内容
def craw(url):
    r = requests.get(url)  # 发送GET请求获取网页内容
    return r.text  # 返回网页的HTML源码

# 消费者函数:解析HTML网页,提取所需的链接信息
def parse(html):
    soup = BeautifulSoup(html, "html.parser")  # 使用BeautifulSoup解析HTML内容
    links = soup.find_all("a", class_="post-item-title")  # 查找所有class为'post-item-title'的<a>标签
    # 返回包含链接和链接文字的元组列表
    return [(link["href"], link.get_text()) for link in links]

# 主程序入口
if __name__ == '__main__':
    # 调用craw函数获取网页内容,并将内容传给parse函数进行解析,输出每一个链接及其文字
    for result in parse(craw(urls[2])):
        print(result)

六、结语

今天我们通过一个简单的例子,学习了如何用 Python 编写一个多线程网页爬虫。希望你能通过这篇文章,快速入门多线程编程,让自己的爬虫项目跑得更快!如果你有任何问题或疑问,欢迎在评论区留言,我们一起讨论,互相进步!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Web Speech API实现语音识别与合成技术

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Web Speech API实现语音识别与合成技术 使用Web Speech API实现语音识别与合成技术 使用Web Speech API实现语音识别与合成技…

NavVis VLX3的精度怎么去进行验证?【上海沪敖3D】

01、精度评价现状 三维捕捉行业还没有建立一个用于估算或验证移动激光扫描系统精度的统一标准。因此&#xff0c;需要高精度交付成果的专业人士很难相信设备所标注的精度规格&#xff0c;也就很难知道基于SLAM的移动激光扫描系统是否适合当前的项目。 NavVis将通过展示一种严格…

爬虫开发工具与环境搭建——环境配置

第二章&#xff1a;爬虫开发工具与环境搭建 第二节&#xff1a;环境配置 在进行爬虫开发之前&#xff0c;首先需要配置好开发环境。一个良好的开发环境不仅能提高开发效率&#xff0c;还能避免因环境不一致带来的问题。以下是环境配置的详细步骤&#xff0c;涵盖了Python开发…

如何用Excel批量提取文件夹内所有文件名?两种简单方法推荐

在日常办公中&#xff0c;我们有时需要将文件夹中的所有文件名整理在Excel表格中&#xff0c;方便管理和查阅。手动复制文件名既费时又易出错&#xff0c;因此本文将介绍两种利用Excel自动提取文件夹中所有文件名的方法&#xff0c;帮助你快速整理文件信息。 方法一&#xff1…

gvim添加至右键、永久修改配置、放大缩小快捷键、ctrl + c ctrl +v 直接复制粘贴、右键和还原以前版本(V)冲突

一、将 vim 添加至右键 进入安装目录找到 vim91\install.exe 管理员权限执行 Install will do for you:1 Install .bat files to use Vim at the command line:2 Overwrite C:\Windows\vim.bat3 Overwrite C:\Windows\gvim.bat4 Overwrite C:\Windows\evim.bat…

机器学习day5-随机森林和线性代数1最小二乘法

十 集成学习方法之随机森林 集成学习的基本思想就是将多个分类器组合&#xff0c;从而实现一个预测效果更好的集成分类器。大致可以分为&#xff1a;Bagging&#xff0c;Boosting 和 Stacking 三大类型。 &#xff08;1&#xff09;每次有放回地从训练集中取出 n 个训练样本&…

SpringCloud框架学习(第三部分:Resilience4j 与 Micrometer)

目录 九、CircuitBreaker断路器 1.前言&#xff08;Hystrix&#xff09; 2.服务雪崩 3.Circuit Breaker 4. Resilience4j 5.案例实战 &#xff08;1&#xff09;熔断&#xff08;服务熔断 服务降级&#xff09; Ⅰ. 按照 COUNT_BASED&#xff08;计数的滑动窗口&#xf…

使用WebVTT和Track API增强HTML5视频的可访问性和互动性

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用WebVTT和Track API增强HTML5视频的可访问性和互动性 使用WebVTT和Track API增强HTML5视频的可访问性和互动性 使用WebVTT和T…

vue2中引入cesium全步骤

1.npm 下载cesium建议指定版本下载&#xff0c;最新版本有兼容性问题 npm install cesium1.95.0 2.在node_models中找到cesium将此文件下的Cesium文件复制出来放在项目的静态资源public中或者static中&#xff0c;获取去github上去下载zip包放在本地也可以 3.在index.html中引…

VTK知识学习(9)-空间变换

1、前言 在三维空间里定义的三维模型&#xff0c;最后显示时都是投影到二维平面&#xff0c;比如在屏幕上显示。 三维到二维的投影包括透视投影&#xff08;Perspective Projection&#xff09;和正交投影&#xff08;Orthogonale Projection&#xff09;。正交投影也叫平行投…

Python学习从0到1 day29 Python 高阶技巧 ⑦ 正则表达式

目录 一、正则表达式 二、正则表达式的三个基础方法 1.match 从头匹配 2.search&#xff08;匹配规则&#xff0c;被匹配字符串&#xff09; 3.findall&#xff08;匹配规则&#xff0c;被匹配字符串&#xff09; 三、元字符匹配 单字符匹配&#xff1a; 注&#xff1a; 示例&a…

日常ctf

15&#xff0c; [MoeCTF 2021]Web安全入门指北—小饼干 直接改就行了 16&#xff0c; [MoeCTF 2021]2048 传入参数就获取到flag了 /flag.php?score500000000 17&#xff0c; [SWPUCTF 2022 新生赛]funny_web 账户密码是 NSS 2122693401 登录进去查看源码 考intval缺陷&…

【MySql】实验十六 综合练习:图书管理系统数据库结构

文章目录 创建图书管理系统数据库结构一、创建数据表1.1 book表1.2 reader表1.3 borrow表 二、插入示例数据2.1 向book表插入数据2.2 向reader表插入数据2.3 向borrow表插入数据 三、查询操作3.1 根据语义为借书表borrow的bno列和 rno列建立外键3.2 查询张小海编写的“数据库原…

通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

目录 通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制 一、引言 二、语义搜索与 MongoDB Atlas 的背景 三、MongoDB Atlas 的向量搜索功能 1. 向量搜索的实现方式 2. 典型操作示例 四、RAG 在 MongoDB Atlas 的应用 1、RAG是什么 2、RAG 的实现过程 3、RA…

51单片机基础01 单片机最小系统

目录 一、什么是51单片机 二、51单片机的引脚介绍 1、VCC GND 2、XTAL1 2 3、RST 4、EA 5、PSEN 6、ALE 7、RXD、TXD 8、INT0、INT1 9、T0、T1 10、MOSI、MISO、SCK 11、WR、RD 12、通用IO P0 13、通用IO P1 14、通用IO P2 三、51单片机的最小系统 1、供电与…

【原创】如何备份和还原Ubuntu系统,非常详细!!

前言 我在虚拟机装了一个xfce4的Ubuntu桌面版&#xff0c;外加输入法、IDEA等&#xff0c;我想将这个虚拟机里的系统直接搬到物理机中&#xff0c;那我可以省的再重新装一遍、配置xfce4桌面、修改一堆快捷键还有配置idea了&#xff0c;那直接说干就干。 本教程基于Ubuntu24.0…

萤石设备视频接入平台EasyCVR私有化视频平台视频监控系统的需求及不同场景摄像机的选择

在现代社会&#xff0c;随着安全意识的提高和技术的进步&#xff0c;安防监控视频系统已成为保障人们生活和财产安全的重要工具。EasyCVR安防监控视频系统&#xff0c;以其先进的网络传输技术和强大的功能&#xff0c;为各种规模的项目提供了一个高效、可靠的监控解决方案。以下…

基于yolov8、yolov5的行人检测识别系统(含UI界面、训练好的模型、Python代码、数据集)

摘要&#xff1a;行人检测在交通管理、智能监控和公共安全中起着至关重要的作用&#xff0c;不仅能帮助相关部门实时监控人群动态&#xff0c;还为自动化监控系统提供了可靠的数据支撑。本文介绍了一款基于YOLOv8、YOLOv5等深度学习框架的行人检测模型&#xff0c;该模型使用了…

Django5 2024全栈开发指南(二):Django项目配置详解

目录 一、基本配置信息二、资源文件配置2.1 资源路由——STATIC_URL2.2 资源集合——STATICFILES_DIRS2.3 资源部署——STATIC_ROOT2.2.4 媒体资源——MEDIA 三、模板配置四、数据库配置4.1 mysqlclient连接MySQL4.2 pymysql连接MySQL4.3 多个数据库的连接方式4.4 使用配置文件…

2、 家庭网络发展现状

上一篇我们讲了了解家庭网络历史(https://blog.csdn.net/xld_hung/article/details/143639618?spm1001.2014.3001.5502),感兴趣的同学可以看对应的文章&#xff0c;本章我们主要讲家庭网络发展现状。 关于家庭网络发展现状&#xff0c;我们会从国内大户型和小户型的网络说起&…