2017-07-04 52 views
0
library(rvest) 

df <- data.frame(Links = c("Qmobile_Noir-M6", "Qmobile_Noir-A1", "Qmobile_Noir-E8")) 

for(i in 1:3) { 
    webpage <- read_html(paste0("https://www.whatmobile.com.pk/", df$Links[i])) 
    data <- webpage %>% 
    html_nodes(".specs") %>% 
    .[[1]] %>% 
    html_table(fill = TRUE) 
} 

刮要使循環適用於所有3個值df$Links但上面的代碼剛纔下載的最後一個,並且下載的數據也必須與變量相同的(可能是一個新的具有變量名稱的列)網站中的R與環從data.frame

回答

1

問題在於如何構建for循環。不過,首先不要使用它會容易得多,因爲R有很大的支持來遍歷列表,比如lapplypurrr::map。你如何組織你的數據的一個版本:

library(tidyverse) 
library(rvest) 

base_url <- "https://www.whatmobile.com.pk/" 

models <- data_frame(model = c("Qmobile_Noir-M6", "Qmobile_Noir-A1", "Qmobile_Noir-E8"), 
      link = paste0(base_url, model), 
      page = map(link, read_html)) 

model_specs <- models %>% 
    mutate(node = map(page, html_node, '.specs'), 
      specs = map(node, html_table, header = TRUE, fill = TRUE), 
      specs = map(specs, set_names, c('var1', 'var2', 'val1', 'val2'))) %>% 
    select(model, specs) %>% 
    unnest() 

model_specs 
#> # A tibble: 119 x 5 
#>    model  var1  var2 
#>    <chr>  <chr>  <chr> 
#> 1 Qmobile_Noir-M6  Build   OS 
#> 2 Qmobile_Noir-M6  Build Dimensions 
#> 3 Qmobile_Noir-M6  Build  Weight 
#> 4 Qmobile_Noir-M6  Build  SIM 
#> 5 Qmobile_Noir-M6  Build  Colors 
#> 6 Qmobile_Noir-M6 Frequency 2G Band 
#> 7 Qmobile_Noir-M6 Frequency 3G Band 
#> 8 Qmobile_Noir-M6 Frequency 4G Band 
#> 9 Qmobile_Noir-M6 Processor  CPU 
#> 10 Qmobile_Noir-M6 Processor Chipset 
#> # ... with 109 more rows, and 2 more variables: val1 <chr>, val2 <chr> 

的數據仍然相當混亂,但至少它都在那裏。

+0

我猜header = FALSE刪除第一行,創建模型向量將變得困難,如果df有更多的記錄 – Janjua

+0

這裏的第一行是一個不是嵌套的描述;如果你想保留它,將'header = FALSE'(儘管它會因爲後面的行結構而重複)。創建模型矢量的正確方法是從菜單中刪除它。 – alistaire

+0

#header = FALSE給出>#A tibble:122 x 5 <感謝您的時間 – Janjua

1

它正在捕獲所有三個值,但它會在每個循環中寫入它們。這就是爲什麼它只顯示一個值,最後一個值是一個值

在進入循環之前,您需要初始化一個變量,我建議一個列表,以便您可以爲每個連續的循環存儲數據。所以像

final_table <- list() 

for(i in 1:3) { 
    webpage <- read_html(paste0("https://www.whatmobile.com.pk/", df$Links[i])) 
    data <- webpage %>% 
    html_nodes(".specs") %>% 
    .[[1]] %>% 
html_table(fill= TRUE) 

final_table[[i]] <- data.frame(data, stringsAsFactors = F) 
} 

在這是,它將每個循環的新數據附加到列表。

+0

由於內存分配的原因,使用'for'循環增加列表的速度非常慢。在這種情況下,代碼的其他部分很可能會慢到無所謂的程度,但在其他情況下使用此方法仍然不是一個好主意。預先分配可以避免一些疼痛,例如, 'final_table < - vector(3,mode ='list')',儘管如果你分配的東西很大,可能是不夠的。 – alistaire

+0

我正在做類似於OP的東西,我使用這種方法,而且速度很慢。假設這是R分配內存的方式。但是,我的清單跳過了大約400個獨立的URL,收集了大約5 - 7000個項目。根據你的建議,我是否應該預先分配我的初始化列表?即final_table < - vector(7000,mode ='list')? –

+0

真的最好的方法是不要使用'for'循環'''''''''''''''或''purrr :: map'(和變體)以一種結構良好的方式在內部包含它們,從而避免造成這種混淆問題。然而,在這種情況下,它不一定會快得多,因爲瓶頸可能是互聯網連接和服務器的速度。有沒有簡單的方法來矢量化必要的連接,所以網絡抓取目前有一定緩慢。 – alistaire