Python爬取圖蟲網站照片
圖蟲是一個攝影師的聚集地,裡面包括很多主題的攝影照片,今天就跟大家分享一下,如何爬爬爬蟲。
其實,爬蟲就是讓計算機做人本該做的事。例如,你想要下載今天新華網的所有新聞,你可以一篇一篇複製保存在計算機中,也可以寫一段代碼,讓計算機下載所有新聞,這就是爬蟲。
今天我們要下載照片。
一、感謝本人的爬蟲技術是從慕課網學來的,所以把鏈接給大家,有時間的可以看視頻教程,沒時間的就看本文章嘍~~~【慕課網 -爬蟲教程(http://www.imooc.com/learn/563)】
另外,我還要感謝圖蟲攝影師【攝影師小欣欣(https://tuchong.com/424887/albums/)】
二、分析爬蟲技術
(圖片來自視頻教程)根據上圖,爬蟲的核心就是中心的方框部分。這裡分為三部分:URL管理器、網頁下載器、網頁解析器。
說的通俗一點就是:
1. URL管理器:我要爬取哪些網站。
2. 網頁下載器:既然要爬取網站數據,總得獲取到網頁內容吧,這就需要下載網頁。
3. 網頁解析器:網頁有了,那就找到數據吧。網頁涵蓋數據這麼多,怎麼快速找到需要的數據?怎麼定位呢?
三、爬蟲
例如:圖蟲網
(1)我們先看看官網是什麼樣子的
(7)在(6)中我們可以獲取到照片的鏈接。其實,在第(5)步 顯示相冊所有作品的時候還有一種方法(此方法僅限此網站,因為這是網站設計的原因),當我們在(4)中點擊相冊的時候,會看到如下GET請求。
返回的是照片鏈接數據,這樣,我們就可以方便的獲取相冊中所有照片數據了。
鏈接中唯一變化的就是那串數字,而數字正好是相冊的ID,這正是我們可以解析出來的,並且能提供的,剩下的工作就是在JSON中解析照片鏈接。
請看流程圖
根據上面圖片的顯示流程我們就可以下載一個攝影師的所有照片了。另外,我們可以發現鏈接中的數字是有規律的:
- 424887是攝影師的ID;所以每一個攝影師都是自己的ID
- 507698是【小紅帽的相冊ID】;459373是【隨雪而來的相冊ID】......
- 同理每個照片也有對應的ID,再次不列出
等等我們在總結一下,逆向思考一下:
- 如果想要下載照片
- 只需要知道照片鏈接
- 只需要知道對應的相冊鏈接
- 只需要知道攝影師主頁相冊鏈接
我們根據攝影師的主頁相冊鏈接,下載,解析得到所有的相冊ID;利用相冊ID通過GET請求獲得每個相冊的照片鏈接;下載圖片。
那我們就開始下載攝影師所有照片吧!
四、代碼
1.主函數
#coding:utf8Created on 2017-4-9@author: 理工男Happy哥哥@link: https://www.zhihu.com/people/li-gong-nan-happyge-ge/activitiesfrom tuchong import url_manager, html_parser, html_outputer, html_downloaderclass SpiderMain(object): def __init__(self): self.urls = url_manager.UrlManager() self.downloader = html_downloader.HtmlDownloader() self.parser = html_parser.HtmlParser() self.outputer = html_outputer.HtmlOutputer() def craw(self, root_url, user_nick): html_cont = self.downloader.download(root_url) new_urls = self.parser.parse_albums_urls(root_url, user_nick, html_cont) count = 1 for link in new_urls: self.urls.add_new_url(link) while self.urls.has_new_url(): try: new_url = self.urls.get_new_url() html_cont = self.downloader.download(new_url) print "craw %d : %s"%(count , new_url) new_data = self.parser.parse_image(new_url,html_cont) # self.urls.add_new_urls(new_urls) self.outputer.collect_data(new_data) count = count + 1 except: print "craw fail" self.outputer.output_html(user_nick)if __name__ == "__main__": print "begin" user_nick = "shaineyy" root_url = "https://tuchong.com/424887/albums/" obj_spider = SpiderMain() obj_spider.craw(root_url, user_nick) print "finish"
2.URL管理器
#coding:utf8Created on 2017-4-9@author: 理工男Happy哥哥@link: https://www.zhihu.com/people/li-gong-nan-happyge-ge/activitiesclass UrlManager(object): def __init__(self): self.new_urls = set() self.old_urls = set() def add_new_url(self , url): if url is None: return if url not in self.new_urls and url not in self.old_urls: self.new_urls.add(url) def add_new_urls(self , urls): if urls is None or len(urls) == 0: return for url in urls: self.add_new_url(url) def has_new_url(self): return len(self.new_urls) != 0 def get_new_url(self): new_url = self.new_urls.pop() self.old_urls.add(new_url) return new_url
3. 網頁下載器
#coding:utf8Created on 2017-4-9@author: 理工男Happy哥哥@link: https://www.zhihu.com/people/li-gong-nan-happyge-ge/activitiesimport urllib2class HtmlDownloader(object): def download(self,url): if url is None: return None response = urllib2.urlopen(url, timeout=10) if response.getcode() != 200: return None return response.read()
4.網頁解析器
#coding:utf8Created on 2017-4-9@author: 理工男Happy哥哥@link: https://www.zhihu.com/people/li-gong-nan-happyge-ge/activitiesfrom bs4 import BeautifulSoupimport jsonclass HtmlParser(object): def _get_albums_urls(self, page_url, user_nick, soup): new_urls = set() links = soup.find_all(a , class_="albums") print links for link in links: new_url = link[href] album_id = new_url[-7:-1] new_full_url = "https://" + user_nick + ".tuchong.com/rest/2/albums/" + album_id + "/images" new_urls.add(new_full_url) print new_full_url return new_urls def parse_albums_urls(self,page_url, user_nick, html_cont): if page_url is None or html_cont is None: return soup = BeautifulSoup(html_cont , html.parser , from_encoding=utf-8) new_urls = self._get_albums_urls(page_url, user_nick, soup) return new_urls def _get_new_data(self, page_url, datas): res_data = [] for img in datas[data][image_list]: print str(img[img_id]) + ".jpg" data = {} data[link] = "https://photo.tuchong.com/" + str(img[user_id]) + "/f/" + str(img[img_id]) + ".jpg" data[fname] = str(img[img_id]) + ".jpg" res_data.append(data) return res_data def parse_image(self,page_url,html_cont): if page_url is None or html_cont is None: return res = json.loads(html_cont) new_data = self._get_new_data(page_url , res) return new_data
5.網頁輸出器
#coding:utf8Created on 2017-4-9@author: 理工男Happy哥哥@link: https://www.zhihu.com/people/li-gong-nan-happyge-ge/activitiesfrom os.path import osimport requestsclass HtmlOutputer(object): def __init__(self): self.datas = [] def collect_data(self , data): if data is None: return self.datas = data def output_html(self, user_nick): count = 0 dir_name = "image_" + user_nick if not os.path.exists(dir_name): os.mkdir(dir_name) for _data in self.datas: print 正在下載第+str(count+1)+張圖片,圖片地址:+_data[link] try: pic= requests.get(_data[link], timeout=10) except: print 【錯誤】當前圖片無法下載 continue string = dir_name + / + _data[fname] fp = open(string.decode(utf-8).encode(cp936),wb) fp.write(pic.content) fp.close() count += 1 self.datas = []
註:該攝影師相冊數量多,所以爬蟲時間較長,請耐心等待。
GitHub:HappyUncle/tuchong-Spider
百度網盤:http://pan.baidu.com/s/1hsbw7ZY
(完)
推薦閱讀:
TAG:爬蟲 |