做個簡陋的Pixabay圖片下載器

今天,用Python來開發一個 圖片搜索下載器

之所以簡陋,是因為獲取不到最高清的原圖,本篇僅僅提供思路。

由於網站使用JavaScript和ajax動態載入技術,還有驗證碼機制,對小白來說想要獲得原圖實在太難啦。所以只能能獲取縮略圖,主要提供基本思路。

選擇的是pixabay,挺有名的高品質圖片網站,免費的, 相信許多人對此並不陌生。

一、目標

1、實現輸入關鍵詞,自動搜索到圖片

2、獲取圖片鏈接

3、批量下載圖片,命名保存入文件

4、代碼優化,不中段、無重複,並且可指定下載範圍

二、步驟

1、首先觀察分析

點擊進入官網,好傢夥和百度一樣的瀑布流模式,查看源碼發現關鍵字『ajax,感覺比較難辦。

果不其然,要點擊頁面才看到縮略圖,還要點擊圖片才能下載。審查元素里並不是原圖的鏈接,源碼中也沒有,按一般思路不能獲取原圖(可能要用到PhantomJS、Selenium等)。

可是我還沒有學到PhantonJ和Selenium呀,所以先拿縮略圖試水啦(不過比官網最小的那一個下載模式要大一些)。分析/2013/10/16/14/45/是時間,flower為關鍵詞,結合源碼分析196360應該是每一個圖的特殊代號。

接著就是用正則匹配出時間、特殊代號,再構造出如上的地址就是我們要找的鏈接了!(當初還以為是原圖,實在是。。。)

2、具體步驟

1)匹配圖片數量的正則

pattern=re.compile(<input name="pagi.*?>.*?/ (.*?) .*?, re.S)n

2)匹配時間、代號正則

pattern=re.compile(<img srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?, re.S)npattern1=re.compile(<img srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?, re.S)npattern2=re.compile(data-lazy-srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?, re.S)n

剛開始時用的是最先那一個,結果只能返回16個圖。

百思不得解,還去看了下別的網站,準備放棄之際,查看源碼發現,不得了正好與這帶下劃線鏈接的16個項吻合,而後面的圖片項發現皆帶有data-lazy

也就是說,前16和後16根本採用不是一個模式啊!這可能也是為了反惡意爬蟲吧,總之厲害了我的哥^_^。

後面就簡單,分別匹配正則並討論。

3)創建目錄,保存入文件和之間如出一轍,不再贅述。

4)下載保存一頁圖片時detailURL分情況討論。i<=16和 i>16的情況。

5)接下來對多頁進行循環,發現第1頁和第2頁之後的url又不相同啦,

具體分析之後,構造如下

url2=Orientation=&Amp;Image_Type=&Amp;Cat=&Amp;Colors=&Amp;Q='+Str(Self.Keyword)+'&Amp;Order=Popular&Amp;Pagi='+Str(Page - Pixabay的免費圖片)

url2=http://pixabay.com/zh/photos/?image_type=&cat=&min_width_=&min_height=&q=+str(self.keyword)+&order=popular

6)最後優化環節:

檢查鏈接錯誤減少下載中斷

去掉圖片下載重複(即每一次重新開始就不用重新下載之前的內容)

設計交互(raw_input)、優化注釋

最後還是覺得太low又改了一下,可以選擇下載頁數(下多少頁呀),及起始頁數(從哪開始)。經驗發現一頁100張。這回方便了,不用每次從頭開始了。

嘿嘿,這就是一個下載器的基本思路啦~

三、代碼

雖然很簡陋,(為了方便查詢)記錄整個過程代碼如下,不喜勿噴哇~

# -*-coding:utf-8 -*-n__author__=WYYn__date__=2017.03.17nn#爬蟲實戰小項目:pixabay 圖片下載器nimport renimport osnimport requestsnimport urllib2nimport timennclass Spider():n #初始化參數n def __init__(self):n self.keyword=raw_input(u歡迎使用pixabay 圖片搜索下載神器n請輸入搜索關鍵詞(英文):)n self.siteURL=http://pixabay.com/zh/photos/? image_type=&cat=&min_width_=&min_height=&q=+str(self.keyword)+&order=popularnn #獲取詳情頁源碼n def getSource(self,url):n result=requests.get(url).text.encode(utf-8)n return resultnn #獲取圖片頁數n def getPageNum(self):n result=self.getSource(self.siteURL)n pattern=re.compile(<input name="pagi.*?>.*?/ (.*?) .*?, re.S)n items=re.search(pattern,result)n if items.group(1)>=1:n print un這個主題共有圖片, items.group(1), u頁n else:n print un哎呀,木有您想要的圖呢。。。n return items.group(1)nn #匹配正則1n def getItem1(self,url):n result=self.getSource(url)n pattern1=re.compile(<img srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?, re.S)n items=re.findall(pattern1, result)n return itemsnn #匹配正則2n def getItem2(self,url):n result=self.getSource(url)n pattern2=re.compile(data-lazy-srcset="https://cdn.pixabay.com/photo(.*?)-(.*?)__340.*?, re.S)n items=re.findall(pattern2,result)n return itemsnn #保存圖片入文件n def saveImage(self,detailURL,name):n try:n picture=urllib2.urlopen(detailURL)n fileName=name+.jpgn string=F:Desktopcodepixabay%s%s % (self.path, fileName)n E=os.path.exists(string)n if not E:n f=open(string, wb)n f.write(picture.read())n f.close()n else:n print u圖片已經存在,跳過!n return Falsen except (urllib2.HTTPError,urllib2.URLError), e:n print e.reasonn return Nonennn #創建目錄n def makeDir(self, path):n self.path=path.strip()n E=os.path.exists(os.path.join(F:Desktopcodepixabay, self.path))n if not E:n # 創建新目錄,若想將內容保存至別的路徑(非系統默認),需要更環境變數n # 更改環境變數用os.chdir()n os.makedirs(os.path.join(F:Desktopcodepixabay,self.path))n os.chdir(os.path.join(F:Desktopcodepixabay,self.path))n print u成功創建名為, self.path, u的文件夾n return self.pathn else:n print u名為, self.path, u的文件夾已經存在...n return Falsenn #對一頁的操作n def saveOnePage(self,url):n i=1n items=self.getItem1(url)n for item in items:n detailURL=https://cdn.pixabay.com/photo+str(item[0])+-+str(item[1])+ _960_720.jpgn print un, u正在下載並保存圖片, i, detailURLn self.saveImage(detailURL, name=Num+str(i))n time.sleep(0.5)n i+=1n if i>16:n items=self.getItem2(url)n i=17n for item in items:n detailURL = https://cdn.pixabay.com/photo+str(item[0])+-+str(item[1])+_960_720.jpgn print un, u正在下載並保存圖片, i, detailURLn self.saveImage(detailURL,name=Num+str(i))n time.sleep(0.5)n i += 1nn #對多頁圖片的操作n def saveMorePage(self):n numbers=self.getPageNum()n Num=int(raw_input(u一頁共100張圖,n請輸入要下載的頁數(默認頁數大於等於1):))n Start=int(raw_input(u請輸入下載起始頁數:))n if numbers>=1:n for page in range(Start,Start+Num):n if page==1:n print un,u正在獲取第1頁的內容......n self.url1=self.siteURLn self.makeDir(path=self.keyword + page + str(page))n self.saveOnePage(url=self.url1)n else:n print un,u正在獲取第,page, u頁的內容n self.url2=https://pixabay.com/zh/photos/?orientation=&image_type=&cat=&colors=&q=+str(self.keyword)+&order=popular&pagi=+str(page)n self.makeDir(path=self.keyword + page + str(page))n self.saveOnePage(url=self.url2)nn else:n return Falsenn print un,u圓滿成功!!!nnspider=Spider()nspider.saveMorePage()n

四、結果

第一頁

最後一頁

實現了去重

再看一下文件變成這樣:

成功實現自動搜索和批量下載,硬傷就是—不是原圖啊(雖然如果要求不高的話,勉強充個數還是可以的)

五、總結

總結一下一個圖片下載器基本的要求:

1、輸入關鍵詞,能成功匹配並下載到圖片

2、可以任意選擇下載的頁數,以及起始頁數

3、實現去重

4、減少下載中斷

本篇就是這樣了~


推薦閱讀:

我為什麼不做培訓
我在想,究竟是什麼讓編程「隔行如隔山」

TAG:Python | 爬虫 | 自学编程 |