Python多線程爬取王者榮耀COS小姐姐圖片集

多線程爬取數(shù)據(jù),主要是用Python的線程池ThreadPoolExecutor。
主要代碼如下:

# -*- coding:utf-8 -*-
import json
import requests
import os
from concurrent.futures import ThreadPoolExecutor


class Wzry_Cosplay_Spider(object):

    def __init__(self):
        """定義存儲(chǔ)目錄"""
        self.base_dir = './wzry_cosplay_pics/'
        """定義請(qǐng)求Header頭"""
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'}

    def get_pics(self):
        n = 1
        while True:
            """獲取圖片資源api地址"""
            url = f'http://gamehelper.gm825.com/wzry/gallery/list?pn={n}'
            try:
                r = requests.get(url, headers=self.headers)
                json_data = json.loads(r.text)
                pics_list = json_data.get('list')
                if len(pics_list) != 0:
                    for pic in pics_list:
                        pic_title = pic.get('title')
                        pic_imgs = pic.get('thumb_img')
                        """將標(biāo)題和圖片地址列表返回"""
                        yield pic_title, pic_imgs
                else:
                    break
                n += 1
            except:
                pass

    def download_pics(self, dirname, imgs):
        path = self.base_dir + dirname
        try:
            """遞歸創(chuàng)建文件夾"""
            os.makedirs(path)
        except:
            pass
        """循環(huán)下載圖片"""
        for img in imgs:
            filename = img.split('/')[-1]
            r = requests.get(img, headers=self.headers)
            with open(path + '/' + filename, 'wb') as f:
                f.write(r.content)
                print(f'----------------------------下載{filename}成功----------------------------')
        print(f"----------------------------{dirname}]下載完成----------------------------")


def main():
    """使用線程池,創(chuàng)建四個(gè)線程"""
    pool = ThreadPoolExecutor(max_workers=4)
    """獲取類對(duì)象"""
    wzry_cosplay_spider = Wzry_Cosplay_Spider()
    """調(diào)用對(duì)象方法獲取標(biāo)題和圖片地址列表"""
    for pic_title, pic_imgs in wzry_cosplay_spider.get_pics():
        """使用線程下載"""
        pool.submit(wzry_cosplay_spider.download_pics, pic_title, pic_imgs)
    """關(guān)閉線程池"""
    pool.shutdown()


if __name__ == '__main__':
    main()

爬取到的資源如下(小姐姐還是蠻養(yǎng)眼的):


source.jpg

ThreadPoolExecutor構(gòu)造實(shí)例的時(shí)候,傳入max_workers參數(shù)來設(shè)置線程池中最多能同時(shí)運(yùn)行的線程數(shù)目。使用submit函數(shù)來提交線程需要執(zhí)行的任務(wù)(函數(shù)名[wzry_cosplay_spider對(duì)象的get_pics函數(shù)]和參數(shù)[圖片標(biāo)題和下載地址列表])到線程池中,并返回該任務(wù)的句柄(類似于文件、畫圖),注意submit()不是阻塞的,而是立即返回。通過submit函數(shù)返回的任務(wù)句柄,還可以能夠使用done()方法判斷該任務(wù)是否結(jié)束。最后通過shutdown()函數(shù)來關(guān)閉線程池。

線程池介紹

線程池的基類是 concurrent.futures 模塊中的 Executor,Executor 提供了兩個(gè)子類,即 ThreadPoolExecutorProcessPoolExecutor,其中 ThreadPoolExecutor 用于創(chuàng)建線程池,而 ProcessPoolExecutor 用于創(chuàng)建進(jìn)程池。
如果使用線程池/進(jìn)程池來管理并發(fā)編程,那么只要將相應(yīng)的 task 函數(shù)提交給線程池/進(jìn)程池,剩下的事情就由線程池/進(jìn)程池來搞定。

Exectuor 提供了如下常用方法:

submit(fn, *args, **kwargs):fn函數(shù)提交給線程池。*args 代表傳給 fn 函數(shù)的參數(shù),*kwargs 代表以關(guān)鍵字參數(shù)的形式為 fn 函數(shù)傳入?yún)?shù)。

map(func, *iterables, timeout=None, chunksize=1):該函數(shù)類似于全局函數(shù) map(func, *iterables),只是該函數(shù)將會(huì)啟動(dòng)多個(gè)線程,以異步方式立即對(duì) iterables 執(zhí)行 map 處理。

shutdown(wait=True):關(guān)閉線程池。

程序?qū)?task 函數(shù)提交(submit)給線程池后,submit方法會(huì)返回一個(gè)Future 對(duì)象,Future類主要用于獲取線程任務(wù)函數(shù)的返回值。由于線程任務(wù)會(huì)在新線程中以異步方式執(zhí)行,因此,線程執(zhí)行的函數(shù)相當(dāng)于一個(gè)“將來完成”的任務(wù),所以Python使用 Future 來代表。

使用線程池來執(zhí)行線程任務(wù)的步驟如下:

1.調(diào)用 ThreadPoolExecutor 類的構(gòu)造器創(chuàng)建一個(gè)線程池。
2.定義一個(gè)普通函數(shù)作為線程任務(wù)。
3.調(diào)用 ThreadPoolExecutor 對(duì)象的 submit() 方法來提交線程任務(wù)。
4.當(dāng)不想提交任何任務(wù)時(shí),調(diào)用 ThreadPoolExecutor 對(duì)象的 shutdown() 方法來關(guān)閉線程池。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Python version 3.8.5 在Python中,并發(fā)并不是同一時(shí)刻有多個(gè)操作(thread/task)...
    Rethink閱讀 9,113評(píng)論 0 4
  • 系統(tǒng)啟動(dòng)一個(gè)新線程的成本是比較高的,因?yàn)樗婕芭c操作系統(tǒng)的交互。在這種情形下,使用線程池可以很好地提升性能,尤其是...
    絆大象的螞蟻閱讀 566評(píng)論 0 0
  • python的thread模塊是比較底層的模塊(可能不同的操作系統(tǒng)不一樣),python的threading模塊是...
    jxvl假裝閱讀 338評(píng)論 0 0
  • 線程 操作系統(tǒng)線程理論 線程概念的引入背景 進(jìn)程 之前我們已經(jīng)了解了操作系統(tǒng)中進(jìn)程的概念,程序并不能單獨(dú)運(yùn)行,只有...
    go以恒閱讀 1,796評(píng)論 0 6
  • 寫在前面:GIL鎖 關(guān)于GIL鎖:多線程在Python中并不一定是雞肋CPython解釋器存在GIL鎖,一次只允許...
    越大大雨天閱讀 947評(píng)論 0 0

友情鏈接更多精彩內(nèi)容