利用Python多線程實(shí)現(xiàn)圖片下載器
導(dǎo)語(yǔ)
之前有很多小伙伴說(shuō)想學(xué)習(xí)一下多線程圖片下載器,雖然好像已經(jīng)過(guò)去很久了,不過(guò)還是上來(lái)安排一波吧。至于題目為什么說(shuō)是構(gòu)建一個(gè)小型數(shù)據(jù)集,因?yàn)楣娞?hào)之后的文章應(yīng)該還會(huì)用到它來(lái)構(gòu)建一些簡(jiǎn)單的圖像分類(lèi)數(shù)據(jù)集,換句話說(shuō),后續(xù)一段時(shí)間,公眾號(hào)會(huì)主要寫(xiě)一些深度學(xué)習(xí)機(jī)器學(xué)習(xí)相關(guān)的文章,下期文章揭曉具體內(nèi)容。
廢話不多說(shuō),讓我們愉快地開(kāi)始近期最后一篇爬蟲(chóng)文章~
開(kāi)發(fā)工具
Python版本:3.7.8
相關(guān)模塊:
requests模塊;
alive-progress模塊;
pyfreeproxy模塊;
user_agent模塊;
beautifulsoup4模塊;
lxml模塊;
以及一些python自帶的模塊。
環(huán)境搭建
安裝Python并添加到環(huán)境變量,pip安裝需要的相關(guān)模塊即可。
原理簡(jiǎn)介
我看了下,發(fā)現(xiàn)大家基本都是從百度,必應(yīng)和谷歌來(lái)根據(jù)給定的關(guān)鍵字下載相關(guān)的圖片數(shù)據(jù)的,所以我們也選用這三個(gè)數(shù)據(jù)源。具體而言,百度的圖片搜索接口如下:
'https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&lm=7&fp=result&ie=utf-8&oe=utf-8&st=-1&word={}&queryWord={}&face=0&pn={}&rn={}'
為了可以多線程地進(jìn)行圖片搜索,我們先根據(jù)想要下載的圖片數(shù)量來(lái)構(gòu)造所有請(qǐng)求頁(yè)的鏈接如下:
search_urls, pagesize = [], 30 for pn in range(math.ceil(search_limits * 1.2 / pagesize)): search_url = base_url.format(quote(keyword), quote(keyword), pn * pagesize, pagesize) search_urls.append(search_url)
然后再多線程請(qǐng)求所有構(gòu)造好的搜索鏈接:
# 多線程請(qǐng)求獲取所有圖片鏈接 def searchapi(self, search_urls, image_urls, bar): while len(search_urls) > 0: search_url = search_urls.pop(0) response = self.get(search_url) if response is None: bar() continue response.encoding = 'utf-8' response_json = json.loads(response.text.replace(r"\'", ""), encoding='utf-8', strict=False) for item in response_json['data']: if 'objURL' in item.keys(): image_urls.add(self.parseurl(item['objURL'])) elif 'replaceUrl' in item.keys() and len(item['replaceUrl']) == 2: image_urls.add(item['replaceUrl'][1]['ObjURL']) bar() task_pool, image_urls = [], set() with alive_bar(min(len(search_urls), search_limits)) as bar: for idx in range(num_threadings): task = threading.Thread( target=searchapi, args=(self, search_urls, image_urls, bar) ) task_pool.append(task) task.start() for task in task_pool: task.join()
線程結(jié)束的條件為我們構(gòu)造的所有請(qǐng)求頁(yè)鏈接search_urls全部被用完。這里我們用的最基本的python的threading庫(kù),感覺(jué)python應(yīng)該還有很多更加好用的多線程庫(kù),感興趣的小伙伴可以自己查查資料,不必拘泥于我寫(xiě)的內(nèi)容。threading庫(kù)的話調(diào)用方便,只需要target指定目標(biāo)函數(shù),args指定目標(biāo)函數(shù)輸入的參數(shù),然后start一下就行,所以我圖省事就直接用它了。
類(lèi)似地,我們也可以根據(jù)得到的image_urls寫(xiě)個(gè)多線程的圖片下載器:
'''下載''' def download(self, keyword, search_limits=1000, num_threadings=5, savedir='outputs'): touchdir(savedir) # 獲得image_urls self.logging(f'Start to search images from {self.source_name}') image_urls = self.search(keyword, search_limits, num_threadings) # 多線程下載圖片 self.logging(f'Start to download images from {self.source_name}') def downloadapi(self, savepaths, image_urls, bar): assert len(savepaths) == len(image_urls) while len(image_urls) > 0: savepath, image_url = savepaths.pop(0), image_urls.pop(0) response = self.get(image_url) if response is None: bar() continue with open(savepath, 'wb') as fp: fp.write(response.content) filetype = imghdr.what(savepath) if filetype in ['jpg', 'jpeg', 'png', 'bmp', 'gif']: savepath_correct = f'{savepath}.{filetype}' shutil.move(savepath, savepath_correct) else: os.remove(savepath) bar() task_pool, savepaths = [], [] for idx in range(len(image_urls)): savename = f'image_{str(idx).zfill(8)}' savepaths.append(os.path.join(savedir, savename)) with alive_bar(len(image_urls)) as bar: for idx in range(num_threadings): task = threading.Thread( target=downloadapi, args=(self, savepaths, image_urls, bar) ) task_pool.append(task) task.start() for task in task_pool: task.join()
然后必應(yīng)的圖片搜索接口如下:
# 構(gòu)建所有urls base_url = 'https://cn.bing.com/images/async?q={}&first={}&count={}&cw=1536&ch=240&relp={}&tsc=ImageBasicHover&datsrc=I&layout=RowBased&mmasync=1&dgState=x*1063_y*768_h*186_c*5_i*71_r*10&IG=D6A4AD486F3A49F1BE164BC50750D641&SFX=3&iid=images.5555' search_urls, pagesize = [], 35 for pn in range(math.ceil(search_limits * 1.2 / pagesize)): search_url = base_url.format(quote(keyword), pn * pagesize, pagesize, pagesize) search_urls.append(search_url)
谷歌的圖片搜索接口如下:
# 構(gòu)建所有urls base_url = 'https://www.google.com/search?' search_urls, pagesize = [], 20 for pn in range(math.ceil(search_limits * 1.2 / pagesize)): params = { 'q': keyword, 'ijn': pn, 'start': pn * pagesize, 'tbs': '', 'tbm': 'isch', } search_urls.append(base_url + urlencode(params))
具體的多線程搜索和下載圖片的寫(xiě)法和百度的類(lèi)似,大功告成啦。
效果展示
你只需要pip安裝一下,就可以直接在終端運(yùn)行了。安裝命令如下:
pip install pyimagedl
使用方式如下:
Usage: imagedl [OPTIONS] Options: --version Show the version and exit. -k, --keyword TEXT 想要搜索下載的圖片關(guān)鍵字, 若不指定, 則進(jìn)入imagedl終端版 -s, --savedir TEXT 下載的圖片的保存路徑 -t, --target TEXT 指定圖片搜索下載的平臺(tái), 例如"baidu" -l, --limits INTEGER 下載的圖片數(shù)量 -n, --nthreadings INTEGER 使用的線程數(shù)量 --help Show this message and exit.
例如,在終端輸入:
imagedl -k 狗狗 -s dogs -t baidu -l 1000
到此這篇關(guān)于利用Python多線程實(shí)現(xiàn)圖片下載器的文章就介紹到這了,更多相關(guān)Python圖片下載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python Socket庫(kù)基礎(chǔ)方法與應(yīng)用詳解
這篇文章主要介紹了關(guān)于Python socket庫(kù)的詳細(xì)技術(shù)解析,包含基礎(chǔ)方法說(shuō)明、工作原理剖析,以及多個(gè)應(yīng)用領(lǐng)域的完整實(shí)現(xiàn)代碼,對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2025-04-04Python數(shù)據(jù)可視化之Seaborn的使用詳解
Seaborn庫(kù)是python中基于matplotlib庫(kù)的可視化工具庫(kù),通過(guò)sns我們可以更方便地繪制出更美觀的圖表。本文將分享python基于Seaborn庫(kù)的一系列繪圖操作,感興趣的可以了解一下2022-04-04Pycharm生成可執(zhí)行文件.exe的實(shí)現(xiàn)方法
這篇文章主要介紹了Pycharm生成可執(zhí)行文件.exe的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Linux CentOS Python開(kāi)發(fā)環(huán)境搭建教程
這篇文章主要介紹了Linux CentOS Python開(kāi)發(fā)環(huán)境搭建方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11Python 刪除連續(xù)出現(xiàn)的指定字符的實(shí)例
今天小編就為大家分享一篇Python 刪除連續(xù)出現(xiàn)的指定字符的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06