Python爬虫之多线程下载豆瓣Top250电影图片

简介: 爬虫项目介绍  本次爬虫项目将爬取豆瓣Top250电影的图片,其网址为:https://movie.douban.com/top250, 具体页面如下图所示:   本次爬虫项目将分别不使用多线程和使用多线程来完成,通过两者的对比,显示出多线程在爬虫项目中的巨大优势。

爬虫项目介绍

  本次爬虫项目将爬取豆瓣Top250电影的图片,其网址为:https://movie.douban.com/top250, 具体页面如下图所示:


豆瓣Top250电影

  本次爬虫项目将分别不使用多线程和使用多线程来完成,通过两者的对比,显示出多线程在爬虫项目中的巨大优势。本文所使用的多线程用到了concurrent.futures模块,该模块是Python中最广为使用的并发库,它可以非常方便地将任务并行化。在concurrent.futures模块中,共有两种并发模块,分别如下:

  • 多线程模式:ThreadPoolExecutor,适合 IO密集型任务;
  • 多进程模式:ProcessPoolExecutor,适合计算密集型任务。

具体的关于该模块的介绍可以参考其官方网址:https://docs.python.org/3/library/concurrent.futures.html
  本次爬虫项目将会用到concurrent.futures模块中的ThreadPoolExecutor类,多线程下载豆瓣Top250电影图片。下面将会给出本次爬虫项目分别不使用多线程和使用多线程的对比,以此来展示多线程在爬虫中的巨大优势。

不使用多线程

  首先,我们不使用多线程来下载豆瓣Top250电影图片,其完整的Python代码如下:

import time
import requests
import urllib.request
from bs4 import BeautifulSoup

# 该函数用于下载图片
# 传入函数: 网页的网址url
def download_picture(url):

    # 获取网页的源代码
    r = requests.get(url)
    # 利用BeautifulSoup将获取到的文本解析成HTML
    soup = BeautifulSoup(r.text, "lxml")
    # 获取网页中的电影图片
    content = soup.find('div', class_='article')
    images = content.find_all('img')
    # 获取电影图片的名称和下载地址
    picture_name_list = [image['alt'] for image in images]
    picture_link_list = [image['src'] for image in images]

    # 利用urllib.request..urlretrieve正式下载图片
    for picture_name, picture_link in zip(picture_name_list, picture_link_list):
        urllib.request.urlretrieve(picture_link, 'E://douban/%s.jpg' % picture_name)


def main():

    # 全部10个网页
    start_urls = ["https://movie.douban.com/top250"]
    for i in range(1, 10):
        start_urls.append("https://movie.douban.com/top250?start=%d&filter=" % (25 * i))

    # 统计该爬虫的消耗时间
    t1 = time.time()
    print('*' * 50)

    for url in start_urls:
        download_picture(url)
    t2 = time.time()

    print('不使用多线程,总共耗时:%s'%(t2-t1))
    print('*' * 50)

main()

其输出结果如下:

**************************************************
不使用多线程,总共耗时:79.93260931968689
**************************************************

去E盘中的douban文件夹查看,如下图:


下载的电影图片

  我们可以看到,在不使用多线程的情况下,这个爬虫总共耗时约80s,完成了豆瓣Top250电影图片的下载。

使用多线程

  接下来,我们使用多线程来下载豆瓣Top250电影图片,其完整的Python代码如下:

import time
import requests
import urllib.request
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED

# 该函数用于下载图片
# 传入函数: 网页的网址url
def download_picture(url):

    # 获取网页的源代码
    r = requests.get(url)
    # 利用BeautifulSoup将获取到的文本解析成HTML
    soup = BeautifulSoup(r.text, "lxml")
    # 获取网页中的电影图片
    content = soup.find('div', class_='article')
    images = content.find_all('img')
    # 获取电影图片的名称和下载地址
    picture_name_list = [image['alt'] for image in images]
    picture_link_list = [image['src'] for image in images]

    # 利用urllib.request..urlretrieve正式下载图片
    for picture_name, picture_link in zip(picture_name_list, picture_link_list):
        urllib.request.urlretrieve(picture_link, 'E://douban/%s.jpg' % picture_name)


def main():

    # 全部10个网页
    start_urls = ["https://movie.douban.com/top250"]
    for i in range(1, 10):
        start_urls.append("https://movie.douban.com/top250?start=%d&filter=" % (25 * i))

    # 统计该爬虫的消耗时间
    print('*' * 50)
    t3 = time.time()

    # 利用并发下载电影图片
    executor = ThreadPoolExecutor(max_workers=10)  # 可以自己调整max_workers,即线程的个数
    # submit()的参数: 第一个为函数, 之后为该函数的传入参数,允许有多个
    future_tasks = [executor.submit(download_picture, url) for url in start_urls]
    # 等待所有的线程完成,才进入后续的执行
    wait(future_tasks, return_when=ALL_COMPLETED)

    t4 = time.time()
    print('使用多线程,总共耗时:%s' % (t4 - t3))
    print('*' * 50)

main()

其输出结果如下:

**************************************************
使用多线程,总共耗时:9.361606121063232
**************************************************

再去E盘中的douban文件夹查看,发现同样也下载了250张电影图片。

总结

  通过上述两个爬虫程序的对比,我们不难发现,同样是下载豆瓣Top250电影,10个网页中的图片,在没有使用多线程的情况下,总共耗时约80s,而在使用多线程(10个线程)的情况下,总共耗时约9.5秒,效率整整提高了约8倍。这样的效率提升在爬虫中无疑是令人兴奋的。
  希望读者在看了本篇博客后,也能尝试着在自己的爬虫中使用多线程,说不定会有意外的惊喜哦~~因为,大名鼎鼎的Python爬虫框架Scrapy,也是使用多线程来提升爬虫速度的哦!

注意:本人现已开通两个微信公众号: 因为Python(微信号为:python_math)以及轻松学会Python爬虫(微信号为:easy_web_scrape), 欢迎大家关注哦~~

目录
相关文章
|
16天前
|
数据采集 存储 Java
高德地图爬虫实践:Java多线程并发处理策略
高德地图爬虫实践:Java多线程并发处理策略
|
1月前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
17天前
|
安全
python_threading多线程、queue安全队列
python_threading多线程、queue安全队列
20 2
|
3天前
|
数据采集 网络安全 UED
揭秘豆瓣网站爬虫:利用lua-resty-request库获取图片链接
本文探讨了如何使用Lua的lua-resty-request库和爬虫代理IP技术从豆瓣网站高效获取图片链接。通过定制请求头部和代理服务,可以应对反爬虫机制,提高爬虫的稳定性和匿名性。示例代码展示了一种方法,但实际应用需考虑版权和法律法规。
揭秘豆瓣网站爬虫:利用lua-resty-request库获取图片链接
|
4天前
|
消息中间件 程序员 调度
Python并发编程:利用多线程提升程序性能
本文探讨了Python中的并发编程技术,重点介绍了如何利用多线程提升程序性能。通过分析多线程的原理和实现方式,以及线程间的通信和同步方法,读者可以了解如何在Python中编写高效的并发程序,提升程序的执行效率和响应速度。
|
13天前
|
并行计算 安全 测试技术
Python多线程
【4月更文挑战第13天】对比多线程与多进程:多线程适合I/O密集型任务,轻量级但受GIL限制;多进程适用于CPU密集型任务,能实现真正并行。多线程直接共享内存,多进程独立内存,各有优劣。
9 0
|
13天前
|
数据采集 安全 Java
Python的多线程,守护线程,线程安全
Python的多线程,守护线程,线程安全
|
13天前
|
并行计算 数据处理 开发者
Python并发编程:解析异步IO与多线程
本文探讨了Python中的并发编程技术,着重比较了异步IO和多线程两种常见的并发模型。通过详细分析它们的特点、优劣势以及适用场景,帮助读者更好地理解并选择适合自己项目需求的并发编程方式。
|
13天前
|
调度 Python 容器
【python】-详解进程与线程
【python】-详解进程与线程
|
16天前
|
人工智能 安全 Java
Python 多线程编程实战:threading 模块的最佳实践
Python 多线程编程实战:threading 模块的最佳实践
128 5