Python爬蟲爬取知乎小結(jié)
最近學(xué)習(xí)了一點(diǎn)網(wǎng)絡(luò)爬蟲,并實(shí)現(xiàn)了使用Python來爬取知乎的一些功能,這里做一個(gè)小的總結(jié)。網(wǎng)絡(luò)爬蟲是指通過一定的規(guī)則自動(dòng)的從網(wǎng)上抓取一些信息的程序或腳本。我們知道機(jī)器學(xué)習(xí)和數(shù)據(jù)挖掘等都是從大量的數(shù)據(jù)出發(fā),找到一些有價(jià)值有規(guī)律的東西,而爬蟲則可以幫助我們解決獲取數(shù)據(jù)難的問題,因此網(wǎng)絡(luò)爬蟲是我們應(yīng)該掌握的一個(gè)技巧。
Python有很多開源工具包供我們使用,我這里使用了requests、BeautifulSoup4、json等包。requests模塊幫助我們實(shí)現(xiàn)http請(qǐng)求,bs4模塊和json模塊幫助我們從獲取到的數(shù)據(jù)中提取一些想要的信息,幾個(gè)模塊的具體功能這里不具體展開。下面我分功能來介紹如何爬取知乎。
模擬登錄
要想實(shí)現(xiàn)對(duì)知乎的爬取,首先我們要實(shí)現(xiàn)模擬登錄,因?yàn)椴坏卿浀脑捄枚嘈畔⑽覀兌紵o法訪問。下面是登錄函數(shù),這里我直接使用了知乎用戶fireling的登錄函數(shù),具體如下。其中你要在函數(shù)中的data里填上你的登錄賬號(hào)和密碼,然后在爬蟲之前先執(zhí)行這個(gè)函數(shù),不出意外的話你就登錄成功了,這時(shí)你就可以繼續(xù)抓取想要 的數(shù)據(jù)。注意,在***使用該函數(shù)時(shí),程序會(huì)要求你手動(dòng)輸入captcha碼,輸入之后當(dāng)前文件夾會(huì)多出cookiefile文件和zhihucaptcha.gif,前者保留了cookie信息,后者則保存了驗(yàn)證碼,之后再去模擬登錄時(shí),程序會(huì)自動(dòng)幫我們填上驗(yàn)證碼。
需要注意的是,在login函數(shù)中有一個(gè)全局變量s=reequests.session(),我們用這個(gè)全局變量來訪問知乎,整個(gè)爬取過程中,該對(duì)象都會(huì)保持我們的持續(xù)模擬登錄。
獲取用戶基本信息
知乎上每個(gè)用戶都有一個(gè)唯一ID,例如我的ID是marcovaldong,那么我們就可以通過訪問地址 https://www.zhihu.com/people/marcovaldong 來訪問我的主頁。個(gè)人主頁中包含了居住地、所在行業(yè)、性別、教育情況、獲得的贊數(shù)、感謝數(shù)、關(guān)注了哪些人、被哪些人關(guān)注等信息。因此,我首先介紹如何通過爬蟲來獲取某一個(gè)知乎用戶的一些信息。下面的函數(shù)get_userInfo(userID)實(shí)現(xiàn)了爬取一個(gè)知乎用戶的個(gè)人信息,我們傳遞給該用戶一個(gè)用戶ID,該函數(shù)就會(huì)返回一個(gè) list,其中包含昵稱、ID、居住地、所在行業(yè)、性別、所在公司、職位、畢業(yè)學(xué)校、專業(yè)、贊同數(shù)、感謝數(shù)、提問數(shù)、回答數(shù)、文章數(shù)、收藏?cái)?shù)、公共編輯數(shù)量、關(guān)注的人數(shù)、被關(guān)注的人數(shù)、主頁被多少個(gè)人瀏覽過等19個(gè)數(shù)據(jù)。
下圖是我的主頁的部分截圖,從上面可以看到這19個(gè)數(shù)據(jù),下面第二張圖是終端上顯示的我的這19個(gè)數(shù)據(jù),我們可以作個(gè)對(duì)照,看看是否全部抓取到了。這個(gè)函數(shù)我用了很長時(shí)間來調(diào)試,因?yàn)椴煌说闹黜摰男畔⑼暾潭仁遣煌?,如果你在使用過程中發(fā)現(xiàn)了錯(cuò)誤,歡迎告訴我。
獲取某個(gè)答案的所有點(diǎn)贊者名單
知乎上有一個(gè)問題是如何寫個(gè)爬蟲程序扒下知乎某個(gè)回答所有點(diǎn)贊用戶名單?,我參考了段小草的這個(gè)答案如何入門Python爬蟲,然后有了下面的這個(gè)函數(shù)。
這里先來大概的分析一下整個(gè)流程。我們要知道,知乎上的每一個(gè)問題都有一個(gè)唯一ID,這個(gè)可以從地址中看出來,例如問題2015 年有哪些書你讀過以后覺得名不符實(shí)?的地址為 https://www.zhihu.com/question/38808048 ,其中38808048就是其ID。而每一個(gè)問題下的每一個(gè)答案也有一個(gè)唯一ID,例如該問題下的***票答案2015 年有哪些書你讀過以后覺得名不符實(shí)? - 余悅的回答 - 知乎的地址鏈接為https://www.zhihu.com/question/38808048/answer/81388411 ,末尾的81388411就是該答案在該問題下的唯一ID。不過我們這里用到的不是這兩個(gè)ID,而是我們?cè)谧ト↑c(diǎn)贊者名單時(shí)的唯一ID,此ID的獲得方法是這樣:例如我們打算抓取如何評(píng)價(jià)《人間正道是滄?!愤@部電視劇? - 老編輯的回答 - 知乎的點(diǎn)贊者名單,首先打開firebug,點(diǎn)擊“5321 人贊同”時(shí),firebug會(huì)抓取到一個(gè)“GET voters_profile”的一個(gè)包,把光標(biāo)放在上面,會(huì)看到一個(gè)鏈接 https://www.zhihu.com/answer/5430533/voters_profile ,其中的5430533才是我們?cè)谧ト↑c(diǎn)贊者名單時(shí)用到的一個(gè)唯一ID。注意此ID只有在答案被贊過后才有。(在這安利一下《人間正道是滄?!愤@部電視劇,該劇以楊立青三兄妹的恩怨情仇為線索,從大革命時(shí)期到解放戰(zhàn)爭,比較全面客觀的展現(xiàn)了國共兩黨之間的主義之爭,每一次看都會(huì)新的認(rèn)識(shí)和體會(huì)。)
在拿到唯一ID后,我們用requests模塊去get到知乎返回的信息,其中有一個(gè)json語句,該json語句中包含點(diǎn)贊者的信息。另外,我們?cè)诰W(wǎng)頁上瀏覽點(diǎn)贊者名單時(shí),一次只能看到20條,每次下拉到名單底部時(shí)又加載出20條信息,再加載20條信息時(shí)所用的請(qǐng)求地址也包含在前面的json語句中。因此我們需要從json語句中提取出點(diǎn)攢著信息和下一個(gè)請(qǐng)求地址。在網(wǎng)頁上瀏覽點(diǎn)贊者名單時(shí),我們可以看到點(diǎn)贊者的昵稱、頭像、獲得了多少贊同和感謝,以及提問和回答的問題數(shù)量,這里我提取了每個(gè)點(diǎn)贊者的昵稱、主頁地址(也就是用戶ID)、贊同數(shù)、感謝數(shù)、提問數(shù)和回答數(shù)。關(guān)于頭像的提取,我會(huì)在下面的函數(shù)中實(shí)現(xiàn)。
在提取到點(diǎn)贊者名單后,我將者信息保存了以唯一ID命名的txt文件中。下面是函數(shù)的具體實(shí)現(xiàn)。
注意,點(diǎn)贊者名單中會(huì)有匿名用戶,或者有用戶被注銷,這時(shí)我們抓取不到此用戶的信息,我這里在txt文件中添加了一句“有點(diǎn)贊者的信息缺失”。
使用同樣的方法,我們就可以抓取到一個(gè)用戶的關(guān)注者名單和被關(guān)注者名單,下面列出了這兩個(gè)函數(shù)。但是關(guān)注者名單抓取函數(shù)有一個(gè)問題,每次使用其抓取大V的關(guān)注者名單時(shí),當(dāng)抓取到第10020個(gè)follower的時(shí)候程序就會(huì)報(bào)錯(cuò),好像知乎有訪問限制一般。這個(gè)問題,我還沒有找到解決辦法,希望有solution的告知一下。因?yàn)闆]有看到有用戶關(guān)注10020+個(gè)人,因此抓取被關(guān)注者名單函數(shù)暫時(shí)未發(fā)現(xiàn)報(bào)錯(cuò)。
提取用戶頭像
再往下就是抓取用戶頭像了,給出某個(gè)唯一ID,下面的函數(shù)自動(dòng)解析其主頁,從中解析出該用戶頭像地址,抓取到圖片并保存到本地文件,文件以用戶唯一ID命名。
結(jié)合其他函數(shù),我們就可以抓取到某個(gè)答案下所有點(diǎn)贊者的頭像,某個(gè)大V所有followers的頭像等。
抓取某個(gè)問題的所有答案
給出某個(gè)唯一ID,下面的函數(shù)幫助爬取到該問題下的所有答案。注意,答案內(nèi)容只抓取文字部分,圖片省略,答案保存在txt文件中,txt文件以答主ID命名。
數(shù)據(jù)庫存取數(shù)據(jù)
在完成了上面的這些功能后,下一步要做的是將用戶信息保存在數(shù)據(jù)庫中,方便數(shù)據(jù)的讀取使用。我剛剛接觸了一下sqlite3,僅僅實(shí)現(xiàn)了將用戶信息存儲(chǔ)在表格中。
等熟悉了sqlite3的使用,我的下一步工作是抓取大量用戶信息和用戶之間的follow信息,嘗試著將大V間的follow關(guān)系進(jìn)行可視化。再下面的工作應(yīng)該就是學(xué)習(xí)python的爬蟲框架scrapy和爬取微博了。
另外,在寫這篇博客的時(shí)候我又重新測(cè)試了一下上面的這些函數(shù),然后我再在火狐上訪問知乎時(shí),系統(tǒng)提示“因?yàn)樵撡~戶過度頻繁訪問”而要求輸入驗(yàn)證碼,看來知乎已經(jīng)開始限制爬蟲了,這樣以來我們就需要使用一些反反爬蟲技巧了,比如控制訪問頻率等等,這個(gè)等以后有了系統(tǒng)的了解之后再作補(bǔ)充吧。



































