爬虫- Day7-多线程

本文介绍了多线程的概念,将进程比喻为车间,线程比作工人,阐述了多线程能提高程序效率的原因。通过Python示例展示了如何创建和启动线程进行并发下载任务,并讲解了线程的阻塞概念,最后给出了一段实现同时下载20部电影的多线程代码作为实战应用。
摘要由CSDN通过智能技术生成

爬虫- Day7-多线程

  • 1.什么是进程 - 一个正在运行的应用程序就是一个进程

    每个进程均运行在其专门且受保护的内存空间中,当进程结束的时候,这个进程对应的内存空间会自动释放。

  • 2.线程

    线程是进程执行任务的基本单元。
    进程中的任务都在线程中执行的(如果一个进程中没有线程,那么这个进程对应的程序什么事情都做不了)。

    进程 - 车间(工厂), 提供厂房以及厂房中保存资源
    线程 - 车间工人
    默认情况下,一个进程中有一个线程。

  • 3.多线程 - 一个进程中有多个线程

    单线程特点:一个线程执行多个任务,只能串行(一个一个按顺序)执行。
    多线程特点:多个线程执行多个任务,可以并行(同时)执行。

    单线程 - 一个工厂中只有一个工人
    多线程 - 一个工厂中同时有多个工人,多线程的存在可以提高程序的效率。

    手机应用程序:3 ~ 5线程
    电脑应用程序:200 ~ 300个

  • 4.多线程的原理

    一个cpu同一时间只能处理一个线程,同一时间只有一个线程可以工作。
    多线程的原理: 多线程技术其实就是利用CPU空闲时间做其他事情。

  • 5.使用多线程

    import time
    from datetime import datetime
    from threading import Thread, current_thread
    
    # 1. 主线程和子线程
    # 一个进程默认只有一个线程,这个线程就是主线程,除了主线程以外的线程都是子线程。
    # 子线程需要由程序员自己创建
    # 什么时候需要子线程,什么时候就创建线程对象: Thread - 线程类
    
    
    def download(name):
        print(f'======{name}开始下载:{datetime.now()}======')
        print(current_thread())
        time.sleep(2)
        print(f'======{name}下载结束:{datetime.now()}======')
    
    
    if __name__ == '__main__':
        # 方案1:在主线程中直接下载三个电影
        # download('肖申克的救赎')
        # download('霸王别姬')
        # download('阿甘正传')
    
        # 方案2:在三个子线程中分别下载三个电影
        # 1)创建线程对象: Thread(*,target=函数, args=元组)
        # target: 需要在子线程中执行的任务(以函数的形式提供)
        # args: 元组中的元素就是在调用target对应的函数的时候的实参
        t1 = Thread(target=download, args=('肖申克的救赎',))
        t2 = Thread(target=download, args=('霸王别姬',))
        t3 = Thread(target=download, args=('阿甘正传',))
    
        # 2)启动线程  - 在子线程中调用target对应的函数,参数就传args中的数据
        # 线程对象.start()
        t1.start()
        t2.start()
        t3.start()
    
  • 6.阻塞

    # 练习:同时下载20部电影,电影1、电影2、电影3,....、电影20,要求所有电影都下载结束后打印 '全部下载完成!'
    ts = []
    for x in range(1, 21):
        name = f'电影{x}'
        t = Thread(target=download, args=(name,))
        t.start()
        ts.append(t)
    
    for t in ts:
        t.join()
    
    print('全部下载完成!')
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个简单的Python多线程爬虫示例: ```python import requests import threading from queue import Queue # 定义一个全局变量用来存储爬取到的数据 data = [] # 定义一个线程锁,防止多个线程同时写入数据导致数据错乱 lock = threading.Lock() # 定义一个队列,用来存储待爬取的URL url_queue = Queue() # 定义一个爬取线程类 class CrawlerThread(threading.Thread): def __init__(self, url_queue): super().__init__() self.url_queue = url_queue def run(self): while True: # 从队列中获取一个URL url = self.url_queue.get() try: # 发送请求并解析响应数据 response = requests.get(url) content = response.text # 对响应数据进行处理(此处省略) # ... # 将处理后的数据存入全局变量 with lock: data.append(processed_data) # 标记该URL已被处理 self.url_queue.task_done() except Exception as e: print(f"Error occurred while crawling {url}: {e}") # 如果发生错误,将该URL重新放回队列 self.url_queue.put(url) self.url_queue.task_done() # 定义一个入口函数 def main(): # 初始化待爬取的URL列表 urls = ["http://www.example.com/page{}".format(i) for i in range(1, 11)] # 将URL列表添加到队列中 for url in urls: url_queue.put(url) # 创建多个爬取线程并启动 for i in range(5): t = CrawlerThread(url_queue) t.start() # 阻塞主线程,直到所有URL都被处理完毕 url_queue.join() # 输出爬取结果 print(data) if __name__ == '__main__': main() ``` 以上示例中,我们定义了一个`CrawlerThread`类来表示爬取线程,定义了一个`url_queue`队列来存储待爬取的URL,定义了一个`data`列表来存储爬取到的数据,以及定义了一个`lock`线程锁来保证多个线程访问`data`时不会出现数据错乱的情况。 在`main`函数中,我们首先将待爬取的URL列表添加到`url_queue`队列中,然后创建多个`CrawlerThread`实例并启动它们。最后,我们使用`url_queue.join()`方法来阻塞主线程,直到所有的URL都被处理完毕。 在`CrawlerThread`类的`run`方法中,我们使用`self.url_queue.get()`方法从`url_queue`队列中获取一个URL,然后发送请求并解析响应数据。如果处理过程中出现错误,我们将该URL重新放回队列中,以便后续线程重新处理。如果处理成功,我们将处理后的数据存入`data`列表中,并使用`self.url_queue.task_done()`方法标记该URL已被处理完毕。 需要注意的是,在多线程爬虫中,如果爬取的网站对IP访问频率有限制,可能会导致IP被封禁的情况。因此,在实际应用中,我们需要合理设置线程数量和请求频率,以避免被封禁的情况发生。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值