Pythonマルチスレッドは闘図表情パックを這い出す

2898 ワード

一、使用技術:
  • Lxml:解析ページ
  • Requestsライブラリ:Webページ情報を取得
  • re:不正な文字を置換
  • os:処理ファイル名
  • Queue:安全なマルチスレッド
  • を実現
  • urllib:ダウンロードして取得した画像
  • 二、設計構想:
    ここでは生産者消費者モデルを用いてマルチスレッドを設計し,消費者はページを解析して1つのページ上のすべての画像のurlを得ることを担当し,消費者は画像をローカルにダウンロードしてIO操作を行うことを担当し,ここでは5人の消費者と5人の生産者を設計した.
    三、Demo:
    import requests
    from lxml import etree
    import os
    import re
    from urllib import request
    from queue import Queue
    import threading
    HEADRES = {
        'User-Agent':
            'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Mobile Safari/537.36'
    }
    class Producers(threading.Thread):
        def __init__(self, page_queue, img_queue, *args, **kwargs):
            super(Producers, self).__init__(*args, **kwargs)
            self.pq = page_queue
            self.iq = img_queue
        def run(self):
            while True:
                if self.pq.empty():
                    break
                url = self.pq.get()
                self.parse_page(url)
        def getHtml(self, url):
            r = requests.get(url, headers=HEADRES)
            r.encoding = r.apparent_encoding
            return r.text
        def parse_page(self, url):
            text = self.getHtml(url)
            html = etree.HTML(text)
            imgs = html.xpath('//div[@class="page-content text-center"]//img[@class!="gif"]')
            imgurls = []
            alts = []
            for img in imgs:
                img_url = img.get('data-original')
                alt = img.get('alt')
                if img_url not in imgurls:
                    imgurls.append(img_url)  #      url                  
                if alt not in alts:
                    alts.append(alt)
            for value in zip(imgurls, alts):
                imgurl, alt = value
                alt1 = re.sub(r'[\??\.,。!!*]', '', alt)  # windows           re   
                suffix = os.path.splitext(imgurl)[1]
                filename = alt1 + suffix
                self.iq.put((imgurl, filename))
    class Customer(threading.Thread):
        def __init__(self, page_queue, img_queue, *args, **kwargs):
            super(Customer, self).__init__(*args, **kwargs)
            self.pq = page_queue
            self.iq = img_queue
        def run(self):
            while True:
             if self.pq.empty() and self.iq.empty():
                 break
             imgurl, filename  = self.iq.get()
             request.urlretrieve(imgurl, 'images/' + filename)
             print(filename+'    ')
    if __name__ == '__main__':
        page_queue = Queue(100)
        img_queue = Queue(1000)
        for i in range(1, 50):
         url = 'http://www.doutula.com/photo/list/?page='+str(i)
         page_queue.put(url)
        for x in range(5):
            t = Producers(page_queue, img_queue)
            t.start()
        for x in range(5):
            t = Customer(page_queue, img_queue)
            t.start()

    単一スレッドの登り速度と比較でき,性能の向上が顕著に観察された.