自学内容网 自学内容网

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 编写一个多线程网页爬虫。希望你能通过这篇文章,快速入门多线程编程,让自己的爬虫项目跑得更快!如果你有任何问题或疑问,欢迎在评论区留言,我们一起讨论,互相进步!


原文地址:https://blog.csdn.net/qq_65009672/article/details/143860332

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!