爬取斗图啦表情包笔记2
使用生产者和消费者模式进行多线程和队列结合爬取
爬取斗图啦表情包笔记2
使用生产者和消费者模式进行多线程和队列结合爬取
重点知识:
1、使用queue队列put(),get()
2、使用threading线程生产与消费模式
import requests
from lxml import etree
from urllib import request
import os
import re
from queue import Queue
import threading
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36'
}
class Product(threading.Thread):
def __init__(self,page_queue,img_queue,*args,**kwargs):
super(Product, self).__init__(*args,**kwargs)
self.page_queue=page_queue
self.img_queue=img_queue
def run(self):
while True:
if self.page_queue.empty():
break
#get():从队列中取到最后一个数据。
url=self.page_queue.get()
self.parse_index(url)
def parse_index(self,url):
resp=requests.get(url,headers=headers)
html=resp.text
e=etree.HTML(html)
imgs=e.xpath('//div[@class="page-content text-center"]//img')
for img in imgs:
#获取图片路径
img_url = img.get('data-original')
#获取图片名字
alt=img.get('alt')
# 替换不规则符号
# alt=re.sub(r'[\??\.。!!\*]', '', alt)
#获取图片后缀 img_url路径下的下标1
suffix=os.path.splitext(img_url)[1]
filename=alt+suffix
#赋值成元组
self.img_queue.put((img_url,filename))
class Customer(threading.Thread):
def __init__(self, page_queue, img_queue, *args, **kwargs):
super(Customer, self).__init__(*args, **kwargs)
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():
break
#解包元组
img_url,filename=self.img_queue.get()
# 保存图片到本地
request.urlretrieve(img_url, 'image/' + filename)
print('正在下载%s'%filename)
def main():
#创建队列
page_queue=Queue(100)
img_queue=Queue(1000)
for i in range(1,100):
url='https://www.doutula.com/photo/list/?page=%d'%i
#put():将一个数据放到队列中。
page_queue.put(url)
#创建线程
for x in range(5):
t1=Product(page_queue,img_queue)
t1.start()
for x in range(6):
t2=Customer(page_queue,img_queue)
t2.start()
if __name__ == '__main__':
main()