斗图啦+多线程(队列)

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)

  

原文地址:https://www.cnblogs.com/hum0ro/p/9601808.html