Python爬虫多线程实战:基于Queue队列的并发抓取详解
本文详解Python爬虫中多线程的使用,重点介绍如何利用标准库Queue解决线程间数据共享与交换的安全性问题。通过糗百图片抓取的实战案例,展示如何构建URL队列、启动多线程并发请求,并控制线程数量以优化抓取速度,确保数据一致性与程序稳定性。
Python Queue模块基础与多线程数据共享
Queue模块简介
Queue是Python的标准库之一,通常被称为队列模块。开发者可以直接使用import语句进行引用。需要注意的是,在Python 2.x版本中,该模块名为Queue(首字母大写),而在Python 3.x及更高版本中,直接引用queue即可。
在Python多线程编程中,多个线程默认共享内存数据。当多个线程同时读写或交换数据时,若缺乏同步机制,极易引发数据竞争,导致数据不安全或状态不一致。Queue模块的出现正是为了解决这一问题,它提供了线程安全的队列操作,能够完美处理多线程环境下的数据交换,确保数据传递的安全性和一致性。
多线程并发抓取实战:糗百图片示例
#多线程实战栗子(糗百)
#用一个队列Queue对象,
#先产生所有url,put进队列;
#开启多线程,把queue队列作为参数传入
#主函数中读取url
import requests
from queue import Queue
import re,os,threading,time
# 构造所有ip地址并添加进queue队列
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}
urlQueue = Queue()
[urlQueue.put('http://www.qiumeimei.com/image/page/{}'.format(i)) for i in range(1,14)]
def get_image(urlQueue):
while True:
try:
# 不阻塞的读取队列数据
url = urlQueue.get_nowait()
# i = urlQueue.qsize()
except Exception as e:
break
print('Current Thread Name %s, Url: %s ' % (threading.currentThread().name, url))
try:
res = requests.get(url, headers=headers)
url_infos = re.findall('data-lazy-src="(.*?)"', res.text, re.S)
for url_info in url_infos:
if os.path.exists(img_path + url_info[-20:]):
print('图片已存在')
else:
image = requests.get(url_info, headers=headers)
with open(img_path + url_info[-20:], 'wb') as fp:
time.sleep(1)
fp.write(image.content)
print('正在下载:' + url_info)
except Exception as e:
print(e)
if __name__ == '__main__':
startTime = time.time()
# 定义图片存储路径
img_path = './img/'
if not os.path.exists(img_path):
os.mkdir(img_path)
threads = []
# 可以调节线程数, 进而控制抓取速度
threadNum = 4
for i in range(0, threadNum):
t = threading.Thread(target=get_image, args=(urlQueue,))
threads.append(t)
for t in threads:
t.start()
for t in threads:
# 多线程多join的情况下,依次执行各线程的join方法, 这样可以确保主线程最后退出, 且各个线程间没有阻塞
t.join()
endTime = time.time()
print('Done, Time cost: %s ' % (endTime - startTime))
核心要点总结
上述内容详细介绍了Python爬虫中多线程结合Queue队列的使用方法与原理。希望这篇详解能帮助大家更好地掌握并发抓取技术。如果在使用过程中有任何疑问,欢迎留言交流,小编会及时回复。感谢大家对本站的支持!若觉得本文对您有帮助,欢迎转载,请注明出处,谢谢!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









