天天看點

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

本節書摘來自華章計算機《資料科學r語言實踐:面向計算推理與問題求解的案例研究法》一書中的第2章,第2.7節,作者:[美] 德博拉·諾蘭(deborah nolan)  鄧肯·坦普·朗(duncan temple lang)  更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

圖2-20 2012櫻花公路賽男子組比賽結果的頁面源碼截屏。截屏顯示的是2012櫻花公路賽男子組結果網頁的html源碼,它和2011年女子組比賽結果(見圖2-21)的格式不是很相似,但兩者都是在html文檔中通過

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

圖2-21 2011年櫻花賽女子組結果頁面的源碼截圖。該圖是2011年櫻花公路賽女子組結果的html源碼截屏。注意給出的時間是比賽中點處(5 mile)和兩個比賽完成時間(time和net tim)。還要注意最右邊的列标記為s。盡管和2012年男子組比賽結果的格式不同,但是他們都是在html文檔中通過

getnodeset()函數傳回一個清單,其中的每個元素都對應文檔中的一個

下面檢查txt中的内容。我們首先确定其中包含多少字元,然後檢查它的開始和結束位置。代碼如下:

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

結果顯示我們成功地從web頁面中提取出了資訊。我們還看到以rn結尾的單獨行,可以利用這些字元将690 904個字元分割成獨立的字元串,每個字元串與表中的行對應。方法如下:

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果
《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

現在已經成功地提取了表中的行作為一個字元向量中的元素。

下面讓我們把代碼整理成函數,使其可以應用到所有的28個web網頁(從1999年到2012年的所有男子組和女子組頁面)。函數以web頁面的url作為輸入,傳回一個字元向量,其中每一行為一個元素,包括頭部行和表的結果行。将前面的代碼組織成一個函數:

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

函數的提取結果和之前的一樣。現在我們可以将它應用到跨這些年度的所有男子組的比賽結果中。

假設有一個包含所有url的向量,那麼就可以将我們的函數簡單地應用于該向量。我們通過把基本的url與特定年份的資訊結合在一起,建立這樣的url向量:

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

這裡有一個錯誤,提示prenode有問題。

為了找到關于錯誤原因的更多資訊,我們通過設定recover()函數對象的error選項,把錯誤處理的功能打開,這樣當有錯誤發生時recover()函數就會被調用。該函數允許我們通路活動的調用框,以便檢查對象并檢視結果是否如我們所預料。下面設定options(),并再次調用extractrestable()函數:

當錯誤發生時,以上内容顯示了目前實際的函數調用集合的簡單視圖。這就是“調用棧”。第一條是對lapply()的頂層調用。第二條是對extractrestable()函數的實際調用。lapply()調用了extractrestable()函數,但是是使用名字fun進行調用,這是因為它是lapply()中的參數名,它包含了我們想要使用lapply()第一個參量中的所有元素而調用的這個函數。extractrettable()調用了幾個函數,但是錯誤發生在第三個表達式xmlvalue(prenode[[ 1]]),它是目前調用棧的第三個也是最後一個元素。

recover()函數允許我們選擇想要檢查的調用。在selection提示符處,輸入調用編号(如2)并按下Enter鍵,那麼将直接在指定調用的調用框中執行該函數。我們将可以檢查(和更新)目前參數與局部變量的值,且可以在該位置執行任意代碼。

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

結果顯示在1999年的比賽結果頁面中沒有

我們重新建立urls向量,使其包含正确的web位址。我們将url位址合并到一起:

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

這回我們沒有收到任何錯誤消息。當然,這隻是因為沒有運作錯誤,并不意味着已經能夠正确地提取資料。我們需要檢查結果集以檢視其中是否包含我們所期望的資訊。

首先檢查每一個字元向量的長度。從網站上我們看到每年有幾千名參賽選手完成比賽,是以我們期望在向量中有幾千個元素。

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

但是,2000年和2009年的向量提取結果中隻有一個元素。

這兩年資料的檔案名是正确的,是以需要進一步發掘原因。我們浏覽2000年網頁的源碼,檢查其格式是否符合我們預期。下面是2000年文檔的前幾行資訊:

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

讓我們重新組織html标簽,利用縮進來檢查是否有檔案格式問題。下面是對于相同的内容以更直覺的方式展現的結果:

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

這個文檔不是規範的html文檔。雖然htmlparse()函數可以修複很多畸形文檔問題,比如,關閉

标簽,根據标簽名比對執行個體等。然而,這個函數隻能做到這些。注意上面文檔中和

出現在

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

以上我們已經解決了2000年的問題,但是2009年的問題仍然存在。在此将這個問題留作練習,修改extractrestable()函數以處理該特殊情況。一旦修改了代碼,便會發現2009年的表中有6659行。

既然已經有了可以處理男子組比賽結果頁面的函數,可以嘗試把它應用到女子組頁面上。在操作時,我們發現除了2009年之外其他頁面都能處理得很好。對于這種情況,不需要對女子組該年份的結果做任何特殊的處理。我們可以再次修改函數,使2009年女子組的結果能夠得到預設處理,而不是像2009年男子組結果那樣需要特殊處理,在此我們将它留作練習。

我們儲存資料以便進一步處理:

《資料科學R語言實踐:面向計算推理與問題求解的案例研究法》一一2.7 從網上抓取比賽結果

最後,采用r資料格式儲存字元向量清單的另一種方式是将字元向量寫到普通的文本檔案中。我們可以使用writelines()來完成上述工作。事實上,可以修改extractrestable()函數以接受一個file參量。如果提供了file參量,函數就把結果寫到相應的檔案中;如果file參量為null,那麼函數就傳回一個字元向量。同樣,在此我們把這個關于改進的問題留作練習。

繼續閱讀