多线程爬虫快速上手

本文介绍了Python中多线程爬虫的实现,通过`threading`模块创建线程,探讨了线程同步问题,如锁机制和Queue线程安全队列的使用。讲解了在爬虫中如何运用生产者消费者模式提高效率,并讨论了GIL全局解释器锁对多线程的影响。
摘要由CSDN通过智能技术生成

多线程爬虫

在实现网页爬虫的时候,经常会因为代理问题掉线导致爬虫失败,还又很多时候下载的文件略大,比如下载图片,因为下载图片是一个耗时的操作。如果采用之前那种同步的方式下载。那效率肯会特别慢。这时候我们就可以考虑使用多线程的方式来下载图片。

我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理。

在这里只说明多线程爬虫,在多线程基础上可以使用多进程来进行爬虫。多线程多进程在python中的使用可以参考我的另一篇博客

多线程介绍:

多线程是为了同步完成多项任务,通过提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。
最简单的比喻多线程就像火车的每一节车厢,而进程则是火车。车厢离开火车是无法跑动的,同理火车也可以有多节车厢。多线程的出现就是为了提高效率。同时它的出现也带来了一些问题。更多介绍请参考:https://baike.baidu.com/item/多线程/1190404?fr=aladdin

threading模块介绍:

threading模块是python中专门提供用来做多线程编程的模块。threading模块中最常用的类是Thread

查看线程数:

使用threading.enumerate()函数便可以看到当前线程的数量。

查看当前线程的名字:

使用threading.current_thread()可以看到当前线程的信息。

创建Thread类并指定target来创建多线程

以下看一个简单的多线程程序:

import time
import threading


"""
传统的方式
def coding():
    for x in range(3):
        print("正在写代码....")
        time.sleep(1)

def drawing():
    for x in range(3):
        print("正在画图....")
        time.sleep(1)


def main():
    coding()
    drawing()


if __name__ == '__main__':
    main()
"""

"""
采用多线程的方式
"""
def coding():
    for x in range(3):
        print(threading.current_thread().name,"--正在写代码....")
        time.sleep(1)

def drawing():
    for x in range(3):
        print(threading.current_thread().name,"--正在画图....")
        time.sleep(1)


def main():
    print(threading.main_thread().name)
    threading.Thread(name="coding thread",target=coding).start() # 创建子线程coding thread
    threading.Thread(name="drawing thread",target=drawing).start() # 创建子线程drawing thread


if __name__ == '__main__':
    main()
    print("总共的线程数:",threading.enumerate())

继承自threading.Thread类来创建多线程:

为了让线程代码更好的封装。可以使用threading模块下的Thread类,继承自这个类,然后实现run方法,线程就会自动运行run方法中的代码。示例代码如下:

import threading
import time


class CodingThread(threading.Thread):
    # 需要重写run 方法
    def __init__(self,name):
        super().__init__()
        self.name = name
    def run(self):
        for x in range(3):
            print(threading.current_thread().name, "--正在写代码....")
            time.sleep(1)


class DrawingThread(threading.Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name
    def run(self):
        for x in range(3):
            print(threading.current_thread().name, "--正在画图....")
            time.sleep(1)


def main():
    print(threading.main_thread().name)
    t1 = CodingThread("coding-thread")
    t2 = DrawingThread("drawing-thread")

    t1.start()
    t2.start()

if __name__ == '__main__':
    main()
    print("总共的线程数:", threading.enumerate())

多线程共享全局变量的问题:

多线程都是在同一个进程中运行的。因此在进程中的全局变量所有线程都是可共享的。这就造成了一个问题,因为线程执行的顺序是无序的。有可能会造成数据错误。比如以下代码:

import threading
import time
"""
多线程引发线程安全问题之--全局变量共享问题
"""

tickets = 0

def product_tickets():
    global tickets
    """生产者线程"""
    for x in range(1000000):
        tickets += 1
        # print("车票+1")
    print("剩余票数:",tickets)

def consume_tickets():
    global tickets
    """消费者线程"""
    for x in range(1000000):
        tickets -=1
        # print(&
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值