50?python爬?代碼, 帶你正確打開知乎新世界!
作者:聶大哥的CS小弟 @Hunting
本篇適用於,
想學爬蟲,
也有一丟丟Python基礎的,
小白2.0們。
老司機開車,
上車請坐穩!
---------- 小弟yy的對話場景 ----------
?哥:快看快看,這個?姐姐腿好長好?!
小弟:唉,知乎現在是世風?下,好好的問答社區,你說你們這些?怎麼就喜歡看低俗的?H圖?你還是個已婚人妻!!!
?哥: 哇,?機內存不夠了,?電腦保存?姐姐們的照?吧。
小弟:我說,你們看就看吧,還要?個個右鍵點開圖?保存?清?圖。。。
?哥:好?煩啊,?百張圖?我?都擼酸了,嘿嘿嘿。。。
小弟:什麼?還想要偷懶?問我有沒有簡單的辦法,可以?次性下載完所有圖??
?哥:雙眼布靈布靈(可憐狀)。。。
小弟:好吧,其實呢,我是不屑於看這些低俗的?H圖的。但既然你們這麼求我,我就勉為其難地寫個爬?代碼,滿??下你們饑渴的?靈。。。
Section 1 - 準備工作
0. 你以為第一件事情就是要學習知識,搭建環境么?當然不是,第?件事情當然是確??標,睜?雙眼,發現這個世界的美,嘿嘿嘿。。。我呢,給你們先列?個知乎問題鏈接,先點進去看看,你們肯定會回來努?學習的(圍笑)。
你的?常搭配是什麼樣??
?材好是?種怎樣的體驗?
拍照時怎樣擺姿勢好看?
?性胸部過?會有哪些困擾與不便?
腿長是?種什麼體驗?
??腿好看胸平是?種什麼體驗?
短髮?孩要怎麼拍照才性感?
1. ?先,你要在電腦?安裝 python 的環境,我會提供2.7和3.6兩個版本的代碼,
但是本?只以python3.6版本為例。
我建議不管是Win還是Mac?戶,都最好下載?個 anaconda,?於管理python庫和環境。
- (Anaconda下載鏈接)http://www.continuum.io/downloads
- (用戶手冊)http://conda.io/docs/test-drive.html#managingconda
安裝完成後,打開你電腦的終端(Terminal)執?以下命令:
# 搭建 python 3.6環境,爬蟲專用。如果你已經裝好了 python3.6的環境,那麼可以跳過搭建環境這一步,直接安裝所需要的 python庫。nconda create --name crawler python=3.6nn# 檢查環境是否已創建nconda info --envsnn# 激活python3.6環境n# Mac/Linux 用戶nsource activate crawler #激活nsource deactivate #退出nn# Win 用戶nactivate crawler # 激活ndeactivate # 退出nn# 檢查 python 版本npython --versionn
2. 因為知乎?站前端是? react 搭建的,頁?內容隨著?戶?標滾軸滑動、點擊
依次展現,為了獲取海量的圖?內容,我們需要?selenium這個 lib 模擬?戶對瀏覽
器進?滑動點擊等操作。
- https://pypi.python.org/pypi/selenium
# 利? pip 安裝 seleniumnpip install -U seleniumn
下載安裝完成後,我建議?家打開上?的鏈接,閱讀?下 selenium 的使??法。意思?致為,為了運? selenium,我們需要安裝?個 chrome 的 driver,下載完成後,對於 Mac ?戶,直接把它複製到/usr/bin或者/usr/local/bin,當然你也可以?定義並添加路徑。對於 Win ?戶,也是同理。
- Chrome: https://sites.google.com/a/chromium.org/chromedriver/downloads
- Firefox: https://github.com/mozilla/geckodriver/releases
- Safari: https://webkit.org/blog/6900/webdriver-support-in-safari-10/
3. 在爬?的時候我們經常會發現?頁都是經過壓縮去掉縮進和空格的,頁?結構會很不清晰,這時候我們就需要? BeautifulSoup 這個 lib 來進?html ?件結構化。
pip install beautifulsoup4n
Section 2 - 代碼解釋
2.0 Import Libraries
from selenium import webdrivernimport timennimport urllib.requestnnfrom bs4 import BeautifulSoupnnimport html.parsern
2.1 確定目標URL
在 main 函數裡邊,打開chrome driver,然後輸入 url
def main():n # ********* Open chrome driver and type the website that you want to view ***********************nn driver = webdriver.Chrome() # 打開瀏覽器nn # 列出來你想要下載圖片的網站nn # driver.get("https://www.zhihu.com/question/35931586") # 你的日常搭配是什麼樣子?n # driver.get("https://www.zhihu.com/question/61235373") # 女生腿好看胸平是一種什麼體驗?n # driver.get("https://www.zhihu.com/question/28481779") # 腿長是一種什麼體驗?n # driver.get("https://www.zhihu.com/question/19671417") # 拍照時怎樣擺姿勢好看?n # driver.get("https://www.zhihu.com/question/20196263") # 女性胸部過大會有哪些困擾與不便?n # driver.get("https://www.zhihu.com/question/46458423") # 短髮女孩要怎麼拍照才性感?n driver.get("https://www.zhihu.com/question/26037846") # 身材好是一種怎樣的體驗?n
2.2 模擬滾動點擊操作
在 main 函數?我們定義?個重複執?的函數,來進?滾動和點擊的操作。?先我們可以?driver.execute_scrip來進?滾動操作。通過觀察,我們發現知乎問題底部有?個「查看更多回答的」的按鈕,如下圖。因此我們可以?driver.find_element_by_css_selector來選中這個按鈕,並點擊。為了愛護?朋友們的?體,我們這?只爬取五個頁?的圖?。其實,五個頁?,100個回答,往往都能有1000張圖?了。。。
# ****************** Scroll to the bottom, and click the "view more" button *********n def execute_times(times):nn for i in range(times):n driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 滑動到瀏覽器底部n time.sleep(2) # 等待頁面載入n try:n driver.find_element_by_css_selector(button.QuestionMainAction).click() # 選中並點擊頁面底部的載入更多n print("page" + str(i)) # 輸出頁面頁數n time.sleep(1) # 等待頁面載入n except:n breaknn execute_times(5) # 注意身體,五個頁面夠了的(微笑)n
2.3 結構化HTML頁面並保存
我們每次爬取頁?信息,要做的第?件事就是把頁? HTML 存儲下來。為了?便我們?眼瀏覽,這時候就需要?beautifulSoup把壓縮後的 HTML ?件結構化並保存。
# **************** Prettify the html file and store raw data file *****************************************nnresult_raw = driver.page_source # 這是原網頁 HTML 信息nresult_soup = BeautifulSoup(result_raw, html.parser)nnresult_bf = result_soup.prettify() # 結構化原 HTML 文件nnwith open("./output/rawfile/raw_result.txt", w) as girls: # 存儲路徑里的文件夾需要事先創建。n girls.write(result_bf)ngirls.close()nprint("Store raw data successfully!!!")n
2.4 爬取知乎問題回答里的<img> nodes
要知道,在我們每次想要爬取頁?信息之前,要做的第?件事就是觀察,觀察這個頁?的結構,量??裁。?般每個頁??都有很多個圖?,?如在這個知乎頁??,有很多?戶頭像以及插?的圖?。但是我們這?不想要?戶頭像,我們只想要要回答問題?的照?,所以不能夠直接爬取所有 <img> 的照?。通過觀察,我發現每?個圖?附近都會有?個<noscript>的node,?邊不僅有縮略圖 URL 還有?清原圖的 URL。因此,我為了偷懶,就直接把所有<noscript>給爬了下來。仔細觀察,你會發現每個<noscript>的<>都是被 escape(HTML entity 轉碼)了的,所以要?html.parser.unescape進?解碼。
# **************** Find all <nonscript> nodes and store them *****************************************nwith open("./output/rawfile/noscript_meta.txt", w) as noscript_meta: # 存儲路徑里的文件夾需要事先創建。n noscript_nodes = result_soup.find_all(noscript) # 找到所有<noscript>noden noscript_inner_all = ""n for noscript in noscript_nodes:n noscript_inner = noscript.get_text() # 獲取<noscript>node內部內容n noscript_inner_all += noscript_inner + "n"nn noscript_all = html.parser.unescape(noscript_inner_all) # 將內部內容轉碼並存儲n noscript_meta.write(noscript_all)nnnoscript_meta.close()nprint("Store noscript meta data successfully!!!")n
轉碼後,結果如下(琳琅滿目的高清無碼大圖 URL):
2.5 下載圖片
有了 img 的所有 node,下載圖?就輕鬆多了。??個 urllib.request.urlretrieve就全部搞定。這?我又做了?點清理,把所有的 url 單獨存了?下,並?序號標記,你也可以不要這?步直接下載。
# **************** Store meta data of imgs *****************************************n img_soup = BeautifulSoup(noscript_all, html.parser)n img_nodes = img_soup.find_all(img)n with open("./output/rawfile/img_meta.txt", w) as img_meta:n count = 0n for img in img_nodes:n if img.get(src) is not None:n img_url = img.get(src)nn line = str(count) + "t" + img_url + "n"n img_meta.write(line)n urllib.request.urlretrieve(img_url, "./output/image/" + str(count) + ".jpg") # 一個一個下載圖片n count += 1nn img_meta.close()n print("Store meta data and images successfully!!!")n
記得還有最後的!!!
if __name__ == __main__:n main()n
2.6 您好,您的小H圖大禮包已送達!
成功後,你會看到以下消息。然後你就可以孤身一人躲在被窩裡嘿嘿嘿了。。。
# ***大哥:小弟變成這樣真的不是我教的?????? ***
因為考慮到肖像問題,只展示圖庫的冰山一小角(不露臉的),隨便給吃瓜群眾們展示一下:
圖侵刪!!!
習慣性衣來伸手飯來張口的客官們!
代碼已經給爺準備好了:
https://github.com/huntingzhu/webcrawler
Python 2.7和Python 3.6的代碼都有......
原發於公眾號:「大數據應用(Datalaus)」
知乎ID:數據應用學院
推薦閱讀: