利用Python多線程實現(xiàn)圖片下載器
導(dǎo)語
之前有很多小伙伴說想學(xué)習(xí)一下多線程圖片下載器,雖然好像已經(jīng)過去很久了,不過還是上來安排一波吧。至于題目為什么說是構(gòu)建一個小型數(shù)據(jù)集,因為公眾號之后的文章應(yīng)該還會用到它來構(gòu)建一些簡單的圖像分類數(shù)據(jù)集,換句話說,后續(xù)一段時間,公眾號會主要寫一些深度學(xué)習(xí)機器學(xué)習(xí)相關(guān)的文章,下期文章揭曉具體內(nè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)模塊即可。
原理簡介
我看了下,發(fā)現(xiàn)大家基本都是從百度,必應(yīng)和谷歌來根據(jù)給定的關(guān)鍵字下載相關(guān)的圖片數(shù)據(jù)的,所以我們也選用這三個數(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ù)想要下載的圖片數(shù)量來構(gòu)造所有請求頁的鏈接如下:
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)然后再多線程請求所有構(gòu)造好的搜索鏈接:
# 多線程請求獲取所有圖片鏈接
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)造的所有請求頁鏈接search_urls全部被用完。這里我們用的最基本的python的threading庫,感覺python應(yīng)該還有很多更加好用的多線程庫,感興趣的小伙伴可以自己查查資料,不必拘泥于我寫的內(nèi)容。threading庫的話調(diào)用方便,只需要target指定目標函數(shù),args指定目標函數(shù)輸入的參數(shù),然后start一下就行,所以我圖省事就直接用它了。
類似地,我們也可以根據(jù)得到的image_urls寫個多線程的圖片下載器:
'''下載'''
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))具體的多線程搜索和下載圖片的寫法和百度的類似,大功告成啦。
效果展示
你只需要pip安裝一下,就可以直接在終端運行了。安裝命令如下:
pip install pyimagedl
使用方式如下:
Usage: imagedl [OPTIONS] Options: --version Show the version and exit. -k, --keyword TEXT 想要搜索下載的圖片關(guān)鍵字, 若不指定, 則進入imagedl終端版 -s, --savedir TEXT 下載的圖片的保存路徑 -t, --target TEXT 指定圖片搜索下載的平臺, 例如"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多線程實現(xiàn)圖片下載器的文章就介紹到這了,更多相關(guān)Python圖片下載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python Socket庫基礎(chǔ)方法與應(yīng)用詳解
這篇文章主要介紹了關(guān)于Python socket庫的詳細技術(shù)解析,包含基礎(chǔ)方法說明、工作原理剖析,以及多個應(yīng)用領(lǐng)域的完整實現(xiàn)代碼,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2025-04-04
Python數(shù)據(jù)可視化之Seaborn的使用詳解
Seaborn庫是python中基于matplotlib庫的可視化工具庫,通過sns我們可以更方便地繪制出更美觀的圖表。本文將分享python基于Seaborn庫的一系列繪圖操作,感興趣的可以了解一下2022-04-04
Pycharm生成可執(zhí)行文件.exe的實現(xiàn)方法
這篇文章主要介紹了Pycharm生成可執(zhí)行文件.exe的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Linux CentOS Python開發(fā)環(huán)境搭建教程
這篇文章主要介紹了Linux CentOS Python開發(fā)環(huán)境搭建方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-11-11
Python 刪除連續(xù)出現(xiàn)的指定字符的實例
今天小編就為大家分享一篇Python 刪除連續(xù)出現(xiàn)的指定字符的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06

