? ? 最近使用node.js寫(xiě)了一個(gè)爬知乎的爬蟲(chóng)荧琼,用來(lái)爬取用戶(hù)的個(gè)人信息譬胎,主要是個(gè)人主頁(yè)的內(nèi)容,這里主要介紹一下在這個(gè)過(guò)程中遇到的問(wèn)題和整個(gè)項(xiàng)目的結(jié)構(gòu)命锄。
?遇到的問(wèn)題
1.由于知乎打開(kāi)之后堰乔,顯示的數(shù)據(jù)量是有限的,只有在右側(cè)滾動(dòng)條滾動(dòng)到底部的時(shí)候脐恩,才會(huì)顯示下一頁(yè)的信息镐侯,是異步獲取數(shù)據(jù)的,所以不能通過(guò)解析html獲得驶冒,需要觀察后臺(tái)發(fā)送的異步請(qǐng)求來(lái)找到獲取數(shù)據(jù)的來(lái)源苟翻。
如何知道前前端是通過(guò)哪個(gè)url獲取數(shù)據(jù)的呢?
在你打開(kāi)知乎的個(gè)人主頁(yè)之后骗污,按F12崇猫,打開(kāi)瀏覽器的調(diào)試界面(我使用的是chrome),點(diǎn)擊最上面一欄的network, 然后點(diǎn)擊右下的response需忿,點(diǎn)擊左側(cè)的一個(gè)個(gè)url诅炉,當(dāng)Response下顯示的是一個(gè)json數(shù)據(jù)的時(shí)候,這就很有可能是一個(gè)異步的前段請(qǐng)求屋厘。你需要通過(guò)你的爬蟲(chóng)調(diào)用這個(gè)url來(lái)獲取異步加載的數(shù)據(jù)涕烧,直接解析返回的json格式的數(shù)據(jù)就可以了。
2.在for循環(huán)里使用異步操作汗洒。由于使用異步操作可以極大加大數(shù)據(jù)的吞吐量议纯,所以在程序的各個(gè)地方使用異步。如果在for循環(huán)中使用異步仲翎,就會(huì)導(dǎo)致很?chē)?yán)重的問(wèn)題痹扇,由于for循環(huán)結(jié)束地比異步早,所以就會(huì)導(dǎo)致異步操作中所有使用到i(for循環(huán)里的參數(shù))的地方溯香,都是for循環(huán)執(zhí)行完最后一次的值鲫构,所以最后使用async在for循環(huán)中使用同步操作。
項(xiàng)目的整體結(jié)構(gòu)
項(xiàng)目主要由三個(gè)部分組成
(1)數(shù)據(jù)庫(kù)交互模塊玫坛,主要用于與數(shù)據(jù)庫(kù)進(jìn)行交互结笨,使用了mongoose
(2)用戶(hù)信息獲取模塊,主要用于訪問(wèn)特定的url獲取某個(gè)用戶(hù)的數(shù)據(jù)湿镀,然后進(jìn)行處理后炕吸,存儲(chǔ)進(jìn)數(shù)據(jù)庫(kù),是項(xiàng)目的最主要部分
(3)線程控制模塊勉痴,會(huì)根據(jù)cpu的數(shù)量赫模,開(kāi)啟多個(gè)線程,進(jìn)行用戶(hù)數(shù)據(jù)的獲取蒸矛,多線程可以提高數(shù)據(jù)的吞吐量瀑罗。
項(xiàng)目中數(shù)據(jù)的大體流程如下:在數(shù)據(jù)庫(kù)中讀取某個(gè)用戶(hù)token ?-->> ?拼裝url來(lái)獲取這個(gè)用戶(hù)的詳細(xì)信息,并存入數(shù)據(jù)庫(kù) ?-->> ?將用戶(hù)所關(guān)注的人的token存入數(shù)據(jù)庫(kù)中雏掠,作為下一個(gè)需要爬取的用戶(hù) -->> 在數(shù)據(jù)庫(kù)中隨機(jī)讀取一個(gè)沒(méi)有被爬取過(guò)的用戶(hù)爬取他的詳細(xì)信息-----循環(huán)不止斩祭。
最后附上項(xiàng)目的github(https://github.com/majinliang123/zhihu-crawler)地址,歡迎各位的star和pull request乡话。