今天,用Python來開發(fā)一個(gè)圖片搜索下載器著角。
之所以簡(jiǎn)陋事富,是因?yàn)楂@取不到最高清的原圖技俐,本篇僅僅提供思路。
由于網(wǎng)站使用JavaScript和ajax動(dòng)態(tài)加載技術(shù)统台,還有驗(yàn)證碼機(jī)制雕擂,對(duì)小白來說想要獲得原圖實(shí)在太難啦。
所以只能能獲取縮略圖贱勃,主要提供基本思路井赌。
選擇的是pixabay,挺有名的高品質(zhì)圖片網(wǎng)站贵扰,免費(fèi)的仇穗, 相信許多人對(duì)此并不陌生。
一拔鹰、目標(biāo):
1仪缸、實(shí)現(xiàn)輸入關(guān)鍵詞,自動(dòng)搜索到圖片
2列肢、獲取圖片鏈接
3、批量下載圖片宾茂,命名保存入文件
4瓷马、代碼優(yōu)化,不中段跨晴、無重復(fù)欧聘,并且可指定下載范圍
二、步驟:
1端盆、首先觀察分析怀骤。
點(diǎn)擊進(jìn)入官網(wǎng),好家伙和百度一樣的瀑布流模式焕妙,查看源碼發(fā)現(xiàn)關(guān)鍵字‘a(chǎn)jax'蒋伦,隱隱感覺會(huì)比較難辦。
果不其然焚鹊,要點(diǎn)擊頁(yè)面才能看到縮略圖痕届,還要點(diǎn)擊圖片才能下載。審查元素里面并不是原圖的鏈接,源碼中也沒有研叫,按照一般思路并不能獲取原圖(可能要用到PhantomJS锤窑、Selenium等)。
可是我還沒有學(xué)到PhantonJ和Selenium呀嚷炉,所以先拿縮略圖試水啦(不過比官網(wǎng)最小的那一個(gè)下載模式要大一些)渊啰。分析/2013/10/16/14/45/是時(shí)間,flower為關(guān)鍵詞申屹,結(jié)合源碼分析196360應(yīng)該是每一個(gè)圖的特殊代號(hào)虽抄。
接著就是用正則匹配出時(shí)間、特殊代號(hào)独柑,再構(gòu)造出如上的地址就是我們要找的鏈接了B蹩摺(當(dāng)初還以為是原圖,實(shí)在是忌栅。车酣。。)
2索绪、具體步驟
1)匹配圖片數(shù)量的正則
pattern=re.compile('<input name="pagi.*?>.*?/ (.*?) .*?', re.S)
2)匹配時(shí)間湖员、代號(hào)正則
pattern=re.compile('<img srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?', re.S)
pattern1=re.compile('<img srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?', re.S)
pattern2=re.compile('data-lazy-srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?', re.S)
剛開始時(shí)用的是最先這個(gè),結(jié)果只能返回16個(gè)圖瑞驱。
百思不得解娘摔,還去看了下別的網(wǎng)站,準(zhǔn)備放棄之際唤反,查看源碼發(fā)現(xiàn)凳寺,不得了正好與這帶下劃線鏈接的16個(gè)項(xiàng)吻合,而后面的圖片項(xiàng)發(fā)現(xiàn)皆帶有'data-lazy'彤侍。
也就是說肠缨,前16和后16根本采用不是一個(gè)模式啊盏阶!
這可能也是為了反惡意爬蟲吧晒奕,總之厲害了我的哥_。
后面就簡(jiǎn)單名斟,分別匹配正則并討論脑慧。
3)創(chuàng)建目錄,保存入文件和之間如出一轍砰盐,不再贅述闷袒。
4)下載保存一頁(yè)圖片時(shí)detailURL分情況討論。i<=16和 i>16的情況楞卡。
5)接下來對(duì)多頁(yè)進(jìn)行循環(huán)霜运,發(fā)現(xiàn)第1頁(yè)和第2頁(yè)之后的url又不相同啦脾歇,具體分析之后,構(gòu)造如下
url2='https://pixabay.com/zh/photos/orientation=&image_type=&cat=&colors=&q='+str(self.keyword)+'&order=popular&pagi='+str(page)
url2='http://pixabay.com/zh/photos/?image_type=&cat=&min_width=&min_height=&q='+str(self.keyword)+'&order=popular'
6)最后優(yōu)化環(huán)節(jié):
檢查鏈接錯(cuò)誤減少下載中斷
去掉圖片下載重復(fù)(即每一次重新開始就不用重新下載之前的內(nèi)容)
設(shè)計(jì)交互(raw_input)淘捡、優(yōu)化注釋
最后還是覺得太low又改了一下藕各,可以選擇下載頁(yè)數(shù)(下多少頁(yè)呀),及起始頁(yè)數(shù)(從哪開始)焦除。經(jīng)驗(yàn)發(fā)現(xiàn)一頁(yè)100張激况。這回方便了,不用每次從頭開始了膘魄。
嘿嘿乌逐,這就是一個(gè)下載器的基本思路啦~
三、代碼
雖然很簡(jiǎn)陋创葡,(為了方便查詢)記錄整個(gè)過程代碼如下浙踢,不喜勿噴哇~:
# -*-coding:utf-8 -*-
__author__='WYY'
__date__='2017.03.17'
#爬蟲實(shí)戰(zhàn)小項(xiàng)目:pixabay 圖片下載器
import re
import os
import requests
import urllib2
import time
class Spider():
#初始化參數(shù)
def __init__(self):
self.keyword=raw_input(u'歡迎使用pixabay 圖片搜索下載神器\n請(qǐng)輸入搜索關(guān)鍵詞(英文):')
self.siteURL='http://pixabay.com/zh/photos/? image_type=&cat=&min_width=&min_height=&q='+str(self.keyword)+'&order=popular'
#獲取詳情頁(yè)源碼
def getSource(self,url):
result=requests.get(url).text.encode('utf-8')
return result
#獲取圖片頁(yè)數(shù)
def getPageNum(self):
result=self.getSource(self.siteURL)
pattern=re.compile('<input name="pagi.*?>.*?/ (.*?) .*?', re.S)
items=re.search(pattern,result)
if items.group(1)>=1:
print u'\n這個(gè)主題共有圖片', items.group(1), u'頁(yè)'
else:
print u'\n哎呀,木有您想要的圖呢灿渴。洛波。。'
return items.group(1)
#匹配正則1
def getItem1(self,url):
result=self.getSource(url)
pattern1=re.compile('<img srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?', re.S)
items=re.findall(pattern1, result)
return items
#匹配正則2
def getItem2(self,url):
result=self.getSource(url)
pattern2=re.compile('data-lazy-srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?', re.S)
items=re.findall(pattern2,result)
return items
#保存圖片入文件
def saveImage(self,detailURL,name):
try:
picture=urllib2.urlopen(detailURL)
fileName=name+'.jpg'
string='F:\Desktop\code\pixabay\%s\%s' % (self.path, fileName)
E=os.path.exists(string)
if not E:
f=open(string, 'wb')
f.write(picture.read())
f.close()
else:
print u'圖片已經(jīng)存在骚露,跳過蹬挤!'
return False
except (urllib2.HTTPError,urllib2.URLError), e:
print e.reason
return None
#創(chuàng)建目錄
def makeDir(self, path):
self.path=path.strip()
E=os.path.exists(os.path.join('F:\Desktop\code\pixabay', self.path))
if not E:
# 創(chuàng)建新目錄,若想將內(nèi)容保存至別的路徑(非系統(tǒng)默認(rèn)),需要更環(huán)境變量
# 更改環(huán)境變量用os.chdir()
os.makedirs(os.path.join('F:\Desktop\code\pixabay',self.path))
os.chdir(os.path.join('F:\Desktop\code\pixabay',self.path))
print u'成功創(chuàng)建名為', self.path, u'的文件夾'
return self.path
else:
print u'名為', self.path, u'的文件夾已經(jīng)存在...'
return False
#對(duì)一頁(yè)的操作
def saveOnePage(self,url):
i=1
items=self.getItem1(url)
for item in items:
detailURL='https://cdn.pixabay.com/photo'+str(item[0])+'-'+str(item[1])+ '_960_720.jpg'
print u'\n', u'正在下載并保存圖片', i, detailURL
self.saveImage(detailURL, name='Num'+str(i))
time.sleep(0.5)
i+=1
if i>16:
items=self.getItem2(url)
i=17
for item in items:
detailURL = 'https://cdn.pixabay.com/photo'+str(item[0])+'-'+str(item[1])+'_960_720.jpg'
print u'\n', u'正在下載并保存圖片', i, detailURL
self.saveImage(detailURL,name='Num'+str(i))
time.sleep(0.5)
i += 1
#對(duì)多頁(yè)圖片的操作
def saveMorePage(self):
numbers=self.getPageNum()
Num=int(raw_input(u'一頁(yè)共100張圖棘幸,\n請(qǐng)輸入要下載的頁(yè)數(shù)(默認(rèn)頁(yè)數(shù)大于等于1):'))
Start=int(raw_input(u'請(qǐng)輸入下載起始頁(yè)數(shù):'))
if numbers>=1:
for page in range(Start,Start+Num):
if page==1:
print u'\n',u'正在獲取第1頁(yè)的內(nèi)容......'
self.url1=self.siteURL
self.makeDir(path=self.keyword + 'page' + str(page))
self.saveOnePage(url=self.url1)
else:
print u'\n',u'正在獲取第',page, u'頁(yè)的內(nèi)容'
self.url2='https://pixabay.com/zh/photos/?orientation=&image_type=&cat=&colors=&q='+str(self.keyword)+'&order=popular&pagi='+str(page)
self.makeDir(path=self.keyword + 'page' + str(page))
self.saveOnePage(url=self.url2)
else:
return False
print u'\n',u'圓滿成功!!!'
spider=Spider()
spider.saveMorePage()
四焰扳、結(jié)果
第一頁(yè)
最后一頁(yè)
實(shí)現(xiàn)去重
就是這樣啦,成功實(shí)現(xiàn)自動(dòng)搜索和批量下載误续,硬傷就是—不是原圖岸趾贰(雖然如果要求不高的話,勉強(qiáng)充個(gè)數(shù)還是可以的)
不說了女嘲,我去學(xué)selenium+PhantomJS了畜份。