• 【爬虫】多线程爬取图片


    多线程爬虫概述

      在当今信息爆炸的时代,网络爬虫(Web Scraper)已成为获取和分析网络数据的重要工具。而多线程爬虫,作为一种提高数据采集效率的技术,更是在处理大规模数据时显得尤为重要。本文将介绍多线程爬虫的基本概念、设计原则以及如何应用于图片爬取任务。
      多线程爬虫是一种利用多线程技术来提高爬虫效率的网络爬虫。与传统的单线程爬虫相比,多线程爬虫可以同时执行多个任务,显著提高数据采集的速度。

    1.1 多线程的优势

    ①多线程允许同时执行多个HTTP请求,减少了等待时间。
    ②更充分地利用服务器和网络资源。
    ③某个线程的失败不会影响其他线程的执行。

    1.2 多线程的挑战

    ① 需要合理管理线程间的共享资源。
    ② 确保代码在多线程环境下依然能够正确执行。
    ③ 过多的线程可能导致资源竞争和上下文切换开销增大。

    设计多线程爬虫

    1.1 项目设计

    ① 设计合理的并发级别,保证合理运用网站资源,但又不会出发反爬虫机制。
    ② 使用线程池进行线程管理,提高资源的利用率。
    ③ 使用任务队列来存储待爬取的URL,线程从队列中获取任务进行处理。
    ④ 确保对网络请求和数据处理过程中可能出现的异常进行捕获和处理。
    ⑤ 生产者和消费者模式分离。

      生产者

    class Procuder(threading.Thread):
    	"""
    	生产者
    	爬取页面,获取图片地址加入到图片队列中
    	"""
    
    	def __init__(self, name, page_queue, img_queue, *args, **kwargs):
    		super(Procuder, self).__init__(*args, **kwargs)
    		self.name = name
    		self.page_queue = page_queue
    		self.img_queue = img_queue
    
    	def run(self):
    		while True:
    			if self.page_queue.empty():
    				print(self.name + '任务完成~')
    				break
    			# 1.获取每一页的url
    			page_url = self.page_queue.get()
    
    			# 2.爬取页面的数据
    			self.spider_page(page_url)
    
    			# 3.休眠0.5秒
    			time.sleep(0.5)
    
    	def spider_page(self, url):
    		"""
    		爬取每一页
    		:param url: 每一页的地址
    		:return:
    		"""
    		response = requests.get(url, headers=HEADERS)
    		text_raw = response.text
    
    		# 1.使用etree
    		html_raw = etree.HTML(text_raw)
    
    		# 2.使用xpath解析数据
    		# 注意:过滤掉gif标签图片
    		imgs = html_raw.xpath('//div[@class="page-content text-center"]//img[@class!="gif"]')
    
    		# 3.获取图片的实际连接并下载到本地
    		for img in imgs:
    			# 3.1 图片的实际地址
    			img_url = img.get('data-original')
    
    			# 3.2 图片名称替换特殊符号
    			alt = re.sub(r'[\??\.,。!!\*]', '', img.get('alt'))
    
    			# 3.3 提取图片的后缀,组装成文件的名字
    			img_name = alt + os.path.splitext(img_url)[-1]
    
    			# 3.4 把爬取到【图片地址+图片名称】以【元组】的形式加入到队列图片队列中
    			self.img_queue.put((img_url, img_name))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

      消费者

    class Consumer(threading.Thread):
    	"""
    	消费者
    	获取图片的地址下载到本地
    	"""
    
    	def __init__(self, name, page_queue, img_queue, *args, **kwargs):
    		super(Consumer, self).__init__(*args, **kwargs)
    		self.name = name
    		self.page_queue = page_queue
    		self.img_queue = img_queue
    
    	def run(self):
    		while True:
    
    			if self.img_queue.empty() and self.page_queue.empty():
    				print(self.name + '任务完成~')
    				break
    
    			# 1.解包,获取图片的地址 + 图片的名称
    			img_url, img_name = self.img_queue.get()
    
    			# 2.使用urlretrieve()函数下载图片到本地
    			request.urlretrieve(img_url, './imgs/%s' % img_name)
    
    			print(img_name + "下载完成")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    1.2 项目流程

      多线程技术可以显著提高爬虫的效率,特别是在网络IO密集型任务中,如图片下载。当一个线程等待网络响应时,其他线程可以继续执行,这样可以充分利用网络资源和CPU资源,提高爬取速度。

    1. 初始化队列。
    	# 1.页面的队列
    	page_queue = Queue(100)
    
    	# 2.表情图片的队列
    	img_queue = Queue(1000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 爬取页面地址
    	# 3.爬取页面的地址
    	for x in range(1, 10):
    		url = 'http://www.doutula.com/photo/list/?page=%d' % x
    
    		#  存入到页面地址队列中
    		page_queue.put(url)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 生产者和消费者模式分离,多线程爬取图片
    	for x in range(5):
    		t = Procuder(name='生产线程-%d' % x, page_queue=page_queue, img_queue=img_queue)
    		t.start()
    
    	for x in range(5):
    		t = Consumer(name='消费线程-%d' % x, page_queue=page_queue, img_queue=img_queue)
    		t.start()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.3注意事项

    ① 在进行网络爬虫操作时,必须遵守相关法律法规,尊重目标网站的robots.txt文件。
    ② 设置合理的用户代理,模拟正常用户访问。
    ③ 合理设置请求频率,避免给服务器带来过大压力。

    总结

      多线程爬虫通过提高并发度,可以大幅提升数据采集的效率,尤其适用于图片等静态资源的爬取。然而,设计和实现多线程爬虫需要考虑线程安全、资源管理和异常处理等多个方面。在实践中,开发者应注重效率与规范的平衡,确保爬虫的合法合规运行。

    在这里插入图片描述

  • 相关阅读:
    独有且优质,这些Mac软件绝了
    AUTOSAR CAN主动与被动唤醒分析
    告别卡顿,迎接流畅!你的mac电脑清洁利器CleanMyMac一键轻松解决所有问题!
    Windows 11 增长停滞,或与过高的硬件需求有关
    网络工程师怎么才算开窍
    SpringMVC基础篇(二)
    OpenStack集群部署——Keystone部署(二)
    Scala基础【入门及安装】
    【Java进阶篇】第一章 面向对象
    IDM的实用功能
  • 原文地址:https://blog.csdn.net/freezing_00/article/details/137775515