2016-11-17 62 views
0

我有一系列的9個網址,我想從刮數據:環與rvest

http://www.basketball-reference.com/play-index/draft_finder.cgi?request=1&year_min=2001&year_max=2014&round_min=&round_max=&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id&order_by_asc=&offset=0 

偏移=在連桿的端部從0上升到900(當頁面通過最後頁面改變時,通過100)。我想循環遍歷每個頁面並刮擦每個表格,然後使用rbind將每個df按順序堆疊在一起。我一直在使用rvest,並希望使用lapply,因爲我比那更好的循環。

問題與此類似(Harvest (rvest) multiple HTML pages from a list of urls),但不同,因爲我不希望在運行該程序之前將所有鏈接複製到一個向量。我想要一個通用的解決方案,以便如何遍歷多個頁面並收集數據,每次創建一個數據框。

第一頁以下工作:

library(rvest) 
library(stringr) 
library(tidyr) 

site <- 'http://www.basketball-reference.com/play-index/draft_finder.cgi?request=1&year_min=2001&year_max=2014&round_min=&round_max=&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id&order_by_asc=&offset=0' 

webpage <- read_html(site) 
draft_table <- html_nodes(webpage, 'table') 
draft <- html_table(draft_table)[[1]] 

但我想對所有頁面重複此操作而無需將URL粘貼到載體中。我嘗試以下,並沒有奏效:

jump <- seq(0, 900, by = 100) 
site <- paste('http://www.basketball-reference.com/play-index/draft_finder.cgi?request=1&year_min=2001&year_max=2014&round_min=&round_max=&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id&order_by_asc=&offset=', jump,'.htm', sep="") 

webpage <- read_html(site) 
draft_table <- html_nodes(webpage, 'table') 
draft <- html_table(draft_table)[[1]] 

所以應該爲每個頁面的數據幀和我想象它會更容易把它們放在一個列表中,然後用rbind堆棧他們。

任何幫助將不勝感激!

+0

你管理的收穫甚至第一頁? – HubertL

+0

@HubertL是剛剛編輯上面的問題。第一塊代碼產生一個數據幀 – jvalenti

+1

這是另一個可能的解決方案:http://stackoverflow.com/questions/39129125/how-to-scrape-all-pages-1-2-3-n-from-a-網站使用r-vest/39131227#39131227 – Dave2e

回答

2

您正在嘗試矢量化一個方法,該方法在一次調用中不能攜帶多個項目。具體而言,read_html()每次調用需要一個頁面,因爲它需要一次讀取一個網頁數據,並且需要一個標量值。考慮通過site清單,lapply循環,那麼所有DFS捆綁在一起:

jump <- seq(0, 800, by = 100) 
site <- paste('http://www.basketball-reference.com/play-index/draft_finder.cgi?', 
       'request=1&year_min=2001&year_max=2014&round_min=&round_max=', 
       '&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0', 
       '&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y', 
       '&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=', 
       '&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id', 
       '&order_by_asc=&offset=', jump, sep="") 

dfList <- lapply(site, function(i) { 
    webpage <- read_html(i) 
    draft_table <- html_nodes(webpage, 'table') 
    draft <- html_table(draft_table)[[1]] 
}) 

finaldf <- do.call(rbind, dfList)    # ASSUMING ALL DFs MAINTAIN SAME COLS 
+0

這是非常直觀的,但我運行它時不斷收到錯誤「下標超出範圍」。 – jvalenti

+0

您在哪一行收到錯誤? 'dfList'是否填充? – Parfait

+0

它出現錯誤來自dfList的最後一行。 dfList不填充 – jvalenti

1

您可以使用curl一次運行所有請求。我對那些可能有小型服務器的網站很好,並且不要把它們炸燬。使用此代碼,您可以在末尾使用lapply清理表格,以便與do.call(rbind, AllOut)堆疊,但我會將其保留給您。

library(rvest) 
library(stringr) 
library(tidyr) 

OffSet <- seq(0, 900, by = 100) 

Sites <- paste0('http://www.basketball-reference.com/play-index/draft_finder.cgi?request=1&year_min=2001&year_max=2014&round_min=&round_max=&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id&order_by_asc=&offset=', OffSet) 


library(curl) 

out <<- list() 
# This is function, function which will be run if data vendor call is successful 
complete = function(res){ 
    # cat("Request done! Status:", res$status, "\n") 
    out <<- c(out, list(res)) 
} 

for(i in 1:length(Sites)){ 
    curl_fetch_multi(
    Sites[i] 
    , done = complete 
    , fail = print 
    , handle = new_handle(customrequest = "GET") 
    ) 
} 

multi_run() 

AllOut <- lapply(out, function(x){ 

    webpage <- read_html(x$content) 
    draft_table <- html_nodes(webpage, 'table') 
    Tab <- html_table(draft_table) 
    if(length(Tab) == 0){ 
    NULL 
    } else { 
    Tab 
    } 

})