你可聽說過維基百科的真理之路

不知道在知乎上的各位人士們聽說過這樣一個傳說:當你不斷點擊維基百科主體部分的第一個鏈接(非發音鏈接),你最終會到達philosophy這個頁面。

很有趣是吧,那麼這到底是不是真的呢?在今年三月份的時候我和我的小組決定對這條真理之路進行一次探尋。當然,由於地理原因,我和我的小組選擇了英文維基百科詞條頁面。

說了這麼多,先把計劃表列出來:

目的:探尋是否真理之路適用於所有的英文維基百科詞條。並且試著給詞條分類,查看每個類別到真理需要多少次點擊。

方法:python抓取並且通過while loop不斷獲取第一個鏈接的頁面。

結論:暫時不知道。

有了這個不知道有何用處的大綱,我和我的隊員便開始了我們的第一個python抓取項目(各位大神請不要吐槽,我們真的第一次接觸python網路板塊)。

在一開始,我們想要依賴於wikipedia自己所有的python模板。於是我們進行了一系列的探索。我們發現,wiki的模板雖然帶了列印出所有連接這個功能,但是只是把鏈接的名字打出來,更要命的是,鏈接是經過排序的。可是有總比沒有好。Wiki還有一個功能就是把頁面的主體部分的內容列印出來,所以我們一開始設定了這個思路:能不能通過進行對比鏈接和主體部分來獲得第一個鏈接的名字。由於維基百科的頁面都是有這樣一個模板:「en.wikipedia.org/wiki/」,只需要在之後把相應的鏈接名字經過處理加上去就行了,所以看起來貌似真的很便捷呢!

然而事實並不是這樣。維基百科自帶的api速度極其之慢,並且在呼叫過程中對內存的佔用也是相當不客觀。想像一下,如果一個頁面到真理的路有12步遙遠,那麼進行十二次呼叫還沒有什麼辦法去清理內存(我相信有可是我不會),我們這是要死。所以在抓取鏈接這塊我們只好和維基百科api說再見。

可是這就代表維基百科的api一無是處了嗎?

不!我們相信既然它存在,我們就必須要用它!

經過一番研究,我們最終給這個api一個不可或缺,也許是整個項目中最最重要的角色:

生成詞條。

嗯。

沒錯,就是生成詞條。在這方面我們相信維基百科的api(以下簡稱api雖然也沒有什麼出場機會了)是老手。api能每次生成500個隨機詞條,對於我們這些個有夢想心懷大海的孩子們來說,500個簡直就是渣,所以我寫了個while loop生成3000次,並且把重複的詞條篩選出,最終獲得了接近150萬個詞條,不得不說api竟然沒有過多的生成重複詞條這點我很驚訝。當然如果你現在問我要這個列表我只能告訴你:

我刪了。。。。

當然是做完之後刪的,現在我們還留著它有用處。

有了詞條,我們小組自信滿滿的覺得:穩了。

於是兩個senior這之後對於所有的algorithm都沒有貢獻,只留下我和一個帥哥freshman之後苦苦地寫代碼。

相信看到這裡的人肯定要吐槽:我們是來看爬蟲的你扯這麼多別的幹嘛!好的好的我現在就給你們爬蟲。

之前說了,我們想要給詞條分類。當時真的是野心慢慢,一開始我對於分類的想法是:先大規模的獲取頁面主旨部分,找到最頻繁出現的10個詞語,然後通過k-cluster來進行分類。當然分類結果要通過最後自己觀察來給出命名。啊,真是一個完美的套路!

然而事實打了我一個臉。維基百科自己也是有分類的,這個我不是沒有注意到。可是萬萬沒想到,維基百科其實有12個主分類,這12個主分類的下面才有那麼多的小分類,也就是說,一個詞條如果能通過什麼途徑進入這些小分類,那麼我就可以確定他的主分類。不過先給你們看看這些個分類吧。

其實這個截圖不完整,不過你們應該get到點了。那麼怎麼樣才能讓一個詞條進入其中的一個小分類呢?作為一個智障,我給出了最簡單的方法:我也點第一個鏈接。當然是分類中的第一個鏈接。不斷點擊下去最終肯定會到其中一個的。簡單,粗暴,而且有效。雖然這不能百分百保證是完美的分類,但絕對是一個有效的分類法。經測驗,平均5秒可以分類一個詞條,當然這是後話。

思路有了,下面就是喜聞樂見的代碼了。其實特別簡單,中心思想就是三行代碼,其它的都是修飾,下面上代碼

k = urllib.request.urlopen(url) soup = BeautifulSoup(k) t = soup.select(#mw-normal-catlinks ul li a)

如果你審視一下wikipedia的頁面元素,這個代碼其實就是找到category這一行然後把那幾個分類全都挑選出來。簡單且弱智,不敢想像這就是我第一次接觸python web做出來的東西。在這之後我又特意加了一行代碼,來把各種名人直接歸到「人」這一類,原因是很多活人的分類第一個是他的出生日期。

當然,這之後還有從列表中對比,如果不成功則繼續抓第一個鏈接balabala,但是思路已經出來了,所以也就不用細說了。但是,在實際運行的時候會發現其實有一部分的頁面,在維基上面是沒有分類的,換而言之是它不屬於那些大分類中的任何一個小分類,並且最後會停在一個未分類頁面。由於我是對比的列表,所以這時候python會報錯,寫個except就可以解決了。當然,為了防止有些頁面會進入死循環,我還放了個20秒限制,雖然基本沒有什麼頁面會真的進入這個死循環,但是還是防範起見吧。

接下來是重頭戲,也是我的帥哥小學弟寫的代碼,不過考慮到時他主筆的代碼,我還是不直接放上來了,講一下思路吧。

小學弟的代碼也是簡單粗暴,直接搜尋主體中的鏈接。怎麼確定是主體呢?Beautifulsoup會幫你歸類的,所以只需要找到不是發音的鏈接就大功告成了。(劇透,他的主體代碼13行,比我的複雜4倍)

當然,他還把這條路列印在了另一個文件之中,也幸虧他想到了這點,不然我們的project其實沒有什麼出彩之處。

下面,先上一張圖展示一下兩個鏈接的真理之路:

是不是很醜?我也覺得,所以我們寫了個parser整理了一下,結果如下:

嗯,這樣就好多了。然而小學弟畢竟年輕,他沒有考慮到,這條真理之路對於有些詞條是不可能達到的,他們會自己繞圈子。比如下面這位:

小學弟於是一拍腦瓜:哎呀,對哦,可是我不想寫代碼了,而且占內存太多(反正永遠內存的鍋)。於是,我又放了一個20秒限制在上面。

然而,這回是我太年輕了

20秒限制,以我們的網路速度,很多鏈接走了30多次就被限制了,所以這個project之後的數據有一定的誤差,可是我們也只能選擇接受。

反正都是內存的鍋!

這時候,望著我們的星辰大海,那150萬個單詞,我們意識到這是不可能的,保守估計每個人都要跑幾年才能把這麼多跑完。哎。所以最後我們只跑了兩萬多的數據。

不是我不想多跑啊,我的20秒時間限制的模板在windows上載入不出來啊!所以到最後只有3個人跑了數據。

當然,還有什麼君用python2我用python3,beautifulsoup不同版本竟然能頁面讀取的不一樣,python在recursion中出現原來讀取文件沒有被保存什麼的我也就不多說了,這些都是小事了,反正,都是內存的鍋。

說了這麼多廢話,現在是出結果的時候了。

這次的project,我們:

總共抓取頁面:21426

達到真理的頁面:16510

平均步數:17.06

每個分類到達真理的概率如下:

你以為這就結束了嗎?

你又天真了

看到這篇文章的封面了嗎?

那是用在真理之路上出現站點的平率做的一張word cloud。

很酷炫吧?

但是你又以為這就結束了?

你叒天真了

這才是這次project的最終成果,一張交通圖,顯示著離真理10步之遠的站點,當然圖片有19mb知乎上傳不了,有人有興趣可以問我要。

但是我還是會給你們看看的,不能口說無憑是吧

在這裡我們可以看到quality (philosophy)是一個被很多次鏈接的站點,鏈接這個站點的是conscious,之後是awareness,knowledge,以此類推,這就是這張圖的用處。

不過說到這裡你以為總算結束了吧?

呵呵

沒錯是結束了。

推薦閱讀:

從頭學習大數據培訓課程 NOSQL 資料庫 hbase(四)整合 hbase 的批量導入功能
大數據時代下,數據感知在數據質量管理系統中的應用
數據科學家 (Data Scientist) 的日常工作內容包括什麼?
Kibana 日誌查詢
MaxCompute MapReduce的7個性能優化策略

TAG:Python | 編程 | 大數據 |