從零開始寫Python爬蟲 --- 3.3 爬蟲實踐:漫畫批量下載

漫畫網站一般都是通過JavaScript和AJAX來動態載入漫畫的,這也就意味著想通過原來爬取靜態網站的方式去下載漫畫是不可能的,這次我們就來用Selenium&PhantomJS來下載漫畫。

目標分析:

這次我們要爬的漫畫網站是:comic.sfacg.com/

資源豐富,更新頻率也還不錯~

目標依舊很明確:

通過Selenium模擬打開漫畫網站,

找到每一章每一頁的漫畫的圖片地址,

按章節目錄分類並下載該圖片。

數據篩選:

隨便找一個漫畫點進去看看:

我們仔細研究一下,發現每一章漫畫的鏈接都包含在

<div class="comic_Serial_list" >

里:

這樣事情就簡單多了,我們用任何一種數據篩選的方式,都能夠快速的找到漫畫章節的地址。

代碼的編寫:

還是按照模塊化的編寫方式,

目錄創建和圖片保存:

這裡很簡單,沒什麼好說的,直接看代碼和注釋就成

def mkdir(path): """ 防止目錄存在 """ if not os.path.exists(path): os.mkdir(path)def SavePic(filename, url): """ 通過requests庫 將抓取到的圖片保存到本地 """ content = requests.get(url).content with open(filename, "wb") as f: f.write(content)

漫畫章節目錄的獲取:

這裡就按照我們一開始的分析,找到漫畫章節的地址就行

為了方便下載圖片的時候能將圖片放在正確的章節文件夾里,這裡的得傳回去漫畫的title,

當然,這樣做是不好的

這使得程序的每一個部分聯繫的太緊了。用程序員的話就是:高耦合

可是一想,定站爬蟲這種東西,網站結構一變,那肯定就是不能用了,

關鍵部分肯定還是要手動更新,維護什麼的就相當於重寫一遍核心程序。所以我就放縱了一把 (逃~

def get_TOF(index_url): """ 獲取漫畫的目錄中的每一章節的url連接 並返回一個字典類型k:漫畫名 v:章節鏈接 """ url_list = [] # 模擬瀏覽器並打開網頁 browser = webdriver.PhantomJS() browser.get(index_url) browser.implicitly_wait(3) # 找到漫畫標題 並創建目錄 title = browser.title.split(",")[0] mkdir(title) # 找到漫畫章節,注意,漫畫可能會有多種篇章 # 例如番外,正文,短片等等 comics_lists = browser.find_elements_by_class_name("comic_Serial_list") # 尋找、正文等 for part in comics_lists: # 找到包裹鏈接的links links = part.find_elements_by_tag_name("a") # 找到每個單獨的章節鏈接 for link in links: url_list.append(link.get_attribute("href")) # 關閉瀏覽器 browser.quit() Comics = dict(name=title, urls=url_list) return Comics

圖片地址:

這個部分是整個爬蟲的核心,

具體的思路就是:

通過Selenium打開漫畫

找到漫畫的真實地址:

調用圖片下載函數,下載漫畫

找到漫畫中的 下一頁 按鈕,點擊它獲取下一張圖片

循環這個過程

但是在實現的過程中,我發現,

就算到了漫畫的最後一頁,

還是會有下一頁這個按鈕,

所以需要我們自己計算一下漫畫有多少頁

方法也很簡單,相信看了注釋你一定能明白的:

def get_pic(Comics): """ 打開每個章節的url, 找到漫畫圖片的地址, 並寫入到本地 """ comic_list = Comics["urls"] basedir = Comics["name"] browser = webdriver.PhantomJS() for url in comic_list: browser.get(url) browser.implicitly_wait(3) # 創建章節目錄 dirname = basedir + "/" + browser.title.split("-")[1] mkdir(dirname) # 找到該漫畫一共有多少頁 pageNum = len(browser.find_elements_by_tag_name("option")) # 找到下一頁的按鈕 nextpage = browser.find_element_by_xpath("//*[@id="AD_j1"]/div/a[4]") # 找到圖片地址,並點擊下一頁 for i in range(pageNum): pic_url = browser.find_element_by_id("curPic").get_attribute("src") filename = dirname + "/" + str(i) + ".png" SavePic(filename, pic_url) # 點擊下一頁的按鈕,載入下一張圖 nextpage.click() print("當前章節 {} 下載完畢".format(browser.title)) browser.quit() print("所有章節下載完畢")

Mian函數:

這裡就是讓項目跑起來的入口了,沒啥好說的:

def main(): url = str(input("請輸入漫畫首頁地址:
")) Comics = get_TOF(url) get_pic(Comics)if __name__ == "__main__": main()

結果的展示:

粗略的計算了一下,

爬取一個30章的漫畫需要5分鐘左右

可以看到,漫畫都按照目錄乖乖的下載好了:

點開一個文件夾:

Selenium爬蟲雖然能模擬瀏覽器載入JS動態頁面,

但是其速度就十分堪憂了

和Scrapy庫、requests更完全不能比了。

怎麼說呢,有得必有失吧!

我也嘗試寫了一個多線程的版本,可是被封ip啦~代碼我放在GitHub上了,有興趣的小夥伴可以接手開發一下。

到這裡

從零開始寫Python爬蟲系列就完結了,

沒想到當時的衝動居然真的堅持到了最後

當然,這個專欄並不會停止更新的,

還是會時不時的發一些我寫的小爬蟲程序上來,

同時也希望喜歡寫爬蟲的小夥伴來投稿呀~

Bye~

每天的學習記錄都會 同步更新到:

微信公眾號: findyourownway

知乎專欄:從零開始寫Python爬蟲 - 知乎專欄

blog : www.ehcoblog.ml

Github: Ehco1996/Python-crawler

推薦閱讀:

TAG:Python | 爬虫 | Selenium |