斗图啦+多线程(队列)
import threading
import requests
from lxml import etree
import time
import os
from queue import Queue #引入队列消除线程执行过程的无序性 和上锁解锁机制一样 的作用
#先用os模块创建一个文件夹
name = os.getcwd()
file = name + os.sep + '斗图啦'
if not os.path.exists(file): # 如果存在文件不存在创建
os.mkdir(file) # 在当前目录下创建一个文件夹
class Producer(threading.Thread):#生产者函数,用来保存生产的队列,继承多线程模块
def __init__(self,page_queue,img_queue,*args,**kwargs):
#*args,**kwargs是python中的可变参数。*args表示任何多个无名参数,它是一个tuple,表示可接受任何位置的参数;**kwargs表示关键字参数,它是一个dict
self.header = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4094.1 Safari/537.36',
'Referer': 'http://www.doutula.com/photo/list/',
}
super(Producer,self).__init__(*args,**kwargs)
self.img_queue=img_queue
self.page_queue=page_queue
def page(self,url):
print(url)
response=requests.get(url,headers=self.header).text
html = etree.HTML(response) # 初始化源代码,只能对字符串处理
# print(type(html))
images = html.xpath('//div[@class="page-content text-center"]//img[@class != "gif"]')
for imgs in images:
name = imgs.get('alt')
img_url = imgs.get('data-original') # 也可以用数组的方式 因为xpath返回的是列表格式的数据
self.img_queue.put((name,img_url)) #添加到队列中 向后插入数据
print('该涨图片地址插入成功!')
def run(self):
#提取出队列中的pagr_url .get()方法在队列中是删除第一个参数并返回
while True:
if self.page_queue.empty(): #当表为空时候 就跳出循环
break
url=self.page_queue.get()
#没提取一页的网址 传入到解析的函数中,进行解析
self.page(url)
class Consumer(threading.Thread): #消费者
def __init__(self,page_queue,img_queue,*args, **kwargs):
self.header = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4094.1 Safari/537.36',
'Referer': 'http://www.doutula.com/photo/list/',
}
super(Consumer, self).__init__(*args, **kwargs)
self.page_queue=page_queue
self.img_queue = img_queue
def run(self):
# print(self.img_queue.get())
while True:
if self.img_queue.empty() and self.page_queue.empty(): #当图片地址和页数地址表为空时候 就跳出循环
break
name,img_url= self.img_queue.get()
name=name.replace('?','') #3文件名带?会有问题
with open(file+os.sep+name+'.jpg','wb') as f:
img = requests.get(img_url, headers=self.header).content
# img = requests.get(img_url,headers=self.header).content #用requests请求图片的url 让以.content保存他
f.write(img)
f.close()
print('%s保存成功!'%name)
def main(page):
#创建一个保存页面的page_queue队列 和保存img_queue的元组(name,img_url)的队列
page_queue=Queue(page)
img_queue=Queue(100)
for i in range(1,page+1):
url = 'http://www.doutula.com/photo/list/?page='+str(i)
page_queue.put(url)
for x in range(5): #创建5个生产者线程
producer=Producer(page_queue,img_queue)
#线程的开始运行
producer.start()
for y in range(5): #创建5个消费者线程
consumer=Consumer(page_queue,img_queue)
consumer.start()
if __name__=='__main__':
main(8)