• 多线程爬取图片(生产者-消费者模式)


    通过生产者-消费者模式实现多线程爬取图片:

      1、生产者通过不断爬取网页中图片的url存入图片队列中

      2、消费者通过图片队列中的url爬取图片并下载到本地

      3、多线程的方式,爬取与下载同时进行,直到子线程结束,输出爬取时间

     1 #多线程下载图片
     2 #生产者-消费者模式
     3 import requests,queue,threading
     4 from lxml import etree
     5 from queue import Queue
     6 import os,time
     7 #生产者,将每个图片的url放入队列中
     8 class product(threading.Thread):
     9     headers = {
    10         "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
    11     }
    12     #初始化
    13     def __init__(self,page_url,img_url):
    14         super(product,self).__init__()
    15         self.page_url = page_url
    16         self.img_url = img_url
    17     #子线程运行
    18     def run(self):
    19         while True:
    20             #如果图片url爬去完毕,则跳出循环,结束子线程
    21             if self.page_url.empty():
    22                 break;
    23 
    24             #获取将爬取的页面url,并解析
    25             html = self.page_url.get()
    26             self.parse_html(html)
    27     #获取图片的url
    28     def parse_html(self,html):
    29         request = requests.get(html, headers=self.headers)
    30         html = etree.HTML(request.text)
    31         #解析html
    32         imgs = html.xpath("//div[@class='page-content text-center']//img[@class!='gif']", encodding='gbk')
    33         for img in imgs:
    34             href = img.get("data-original")
    35             name = img.get("alt")
    36             #获取后缀
    37             suffix = os.path.splitext(href)[1]
    38             filename = "img\" + name + suffix
    39             print(filename)
    40             #将爬取的图片url和图片名字加入图片队列中
    41             self.img_url.put((href,filename))
    42 #消费者,根据图片url爬取图片
    43 class consume(threading.Thread):
    44     def __init__(self,page_url,img_url):
    45         super(consume,self).__init__()
    46         self.page_url = page_url
    47         self.img_url = img_url
    48     def run(self):
    49         while True:
    50             #如果图片队列为空且页面队列为空,则推出循环
    51             if self.page_url.empty() and self.img_url.empty():
    52                 break
    53             href,filename = self.img_url.get()
    54             res = requests.get(href)
    55             with open(filename, 'wb') as fp:
    56                 fp.write(res.content)
    57 def main():
    58     #基本url
    59     base_url = "http://www.doutula.com/photo/list/?page={}"
    60     #设置页面队列为10,图片队列为200
    61     page_url = Queue(10)
    62     img_url = Queue(200)
    63     #把需要爬取的网页url放入队列中
    64     for i in range(1,10):
    65         url = base_url.format(i)
    66         page_url.put(url)
    67     #设置生产者,开始爬取每个网页的图片地址
    68     for i in range(8):
    69         t = product(page_url,img_url)
    70         t.start()
    71     #设置消费者,根据图片队列中的url爬取图片
    72     for j in range(8):
    73         tt = consume(page_url,img_url)
    74         tt.start()
    75         #设置消费者子线程运行完之后,才会推出main主线程
    76         tt.join()
    77 
    78 if __name__ == '__main__':
    79     times = time.time()
    80     tmain = threading.Thread(target=main)
    81     tmain.start()
    82     tmain.join()
    83     times1 = time.time()
    84     print(times1-times)
  • 相关阅读:
    5.14每日一题题解
    5.13 每日一题题解
    5.12 每日一题题解
    5.11 每日一题题解
    5.10每日一题题解
    【SPOJ -NSUBSTR】Substrings 【后缀自动机+dp】
    【POJ1509】Glass Beads 【后缀自动机】
    【codevs3160】 LCS 【后缀自动机】
    【HDU4734】F(x) 【数位dp】
    【hdu6148】Valley Numer【数位dp模板题】
  • 原文地址:https://www.cnblogs.com/liuhui5599/p/10225019.html
Copyright © 2020-2023  润新知