多线程爬虫
在实现网页爬虫的时候,经常会因为代理问题掉线导致爬虫失败,还又很多时候下载的文件略大,比如下载图片,因为下载图片是一个耗时的操作。如果采用之前那种同步的方式下载。那效率肯会特别慢。这时候我们就可以考虑使用多线程的方式来下载图片。
我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理。
在这里只说明多线程爬虫,在多线程基础上可以使用多进程来进行爬虫。多线程多进程在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(&