2017-10-15 126 views
0

這是a prior thread的後續操作。代碼對於單個值來說工作得很好,但是當我試圖傳遞超過1個值時出現以下錯誤,我根據函數的長度得到一個錯誤。 錯誤vapply(元件,編碼,字符(1)): 值必須是長度爲1,但 FUN(X [1])結果是長度爲3如何在rvest提交表單中傳遞多個值

下面是代碼的樣本。在大多數情況下,我只能用這種方式命名對象並進行刮擦。

library(httr) 
library(rvest) 
library(dplyr) 

b<-c('48127','48180','49504') 

POST(
url = "http://www.nearestoutlet.com/cgi-bin/smi/findsmi.pl", 
body = list(zipcode = b), 
encode = "form" 
) -> res 

我想知道如果一個循環插入值的形式將是正確的方式去?然而,我的循環寫作技巧仍在發展中,我不確定將它放在哪裏;另外當我調用循環時,它不會逐行打印,它只是返回空結果。

#d isn't listed in the above code as it returns null  
d<-for(i in 1:3){nrow(b)} 

回答

0

這裏是發送多個POST請求

library(httr) 
library(rvest) 
b <- c('48127','48180','49504') 

對於b中執行功能的各元件,將發送適當的POST請求

res <- lapply(b, function(x){ 
    res <- POST(
    url = "http://www.nearestoutlet.com/cgi-bin/smi/findsmi.pl", 
    body = list(zipcode = x), 
    encode = "form" 
) 
    res <- read_html(content(res, as="raw")) 
}) 

現在對於中的每個元素的方法清單res您應該執行hrbrmstr解釋的解析步驟:How can I Scrape a CGI-Bin with rvest and R?

library(tidyverse) 

我會使用hrbrmstr的代碼,因爲他是國王,它已經很清楚。我們在這裏做的只是在res列表的每個元素上執行它。

res_list = lapply(res, function(x){ 
    rows <- html_nodes(x, "table[width='300'] > tr > td") 
    ret <- data_frame(
    record = !is.na(html_attr(rows, "bgcolor")), 
    text = html_text(rows, trim=TRUE) 
    ) %>% 
    mutate(record = cumsum(record)) %>% 
    filter(text != "") %>% 
    group_by(record) %>% 
    summarise(x = paste0(text, collapse="|")) %>% 
    separate(x, c("store", "address1", "city_state_zip", "phone_and_or_distance"), sep="\\|", extra="merge") 
    return(ret) 
} 
) 

或使用mappurrr

res %>% 
    map(function(x){ 
    rows <- html_nodes(x, "table[width='300'] > tr > td") 
    data_frame(
     record = !is.na(html_attr(rows, "bgcolor")), 
     text = html_text(rows, trim=TRUE) 
    ) %>% 
     mutate(record = cumsum(record)) %>% 
     filter(text != "") %>% 
     group_by(record) %>% 
     summarise(x = paste0(text, collapse="|")) %>% 
     separate(x, c("store", "address1", "city_state_zip", "phone_and_or_distance"), 
       sep="\\|", extra="merge") -> ret 
    return(ret) 
    } 
) 

如果你想這在數據幀:

res_df <- data.frame(do.call(rbind, res_list), #rbinds list elements 
        b = rep(b, times = unlist(lapply(res_list, length)))) #names the rows according to elements in b 
+0

這項工作非常好,現在我明白我在循環中出錯的地方。對於網頁瀏覽器的開發工具任何推薦閱讀?還有什麼可以幫助更先進的R?我從SAMS和Swirl圖書館瞭解到,但我覺得我很想念。 – Turbogoon

+0

@Turbogoon用於解析刮取的數據,如果你學習'xpath'和'regex',它們在任何編程語言中都是非常普遍的,所以無論你下一步做什麼都花時間,這將是有益的。爲了找出瀏覽器請求中的內容(所以你可以在R中模擬它)Burpsuite可能會派上用場。任何R用戶都應該習慣於應用功能組。大多數現代數據清理方法都利用了一些或所有「全面」的庫。函數如'filter','group_by','summarise','map','separate','mutate'都是'tidyverse'的一部分 – missuse

+0

感謝您的額外資源。我會讀xpath和正則表達式。我習慣了逆轉,但我仍在掙扎。我只用了約90天的時間。我以前的清理方法是SQL,我可以看到爲什麼tidyverse更有效。我真的很感激它! – Turbogoon

0

你可以把下面的帖子裏面的值,

b<-c('48127','48180','49504') 

    for(i in 1:length(b)) { 

    POST(
    url = "http://www.nearestoutlet.com/cgi-bin/smi/findsmi.pl", 
    body = list(zipcode =b[i]), 
    encode = "form" 
    ) -> res 

    # YOUR CODES HERE (for getting content of the page etc.) 

    } 

但是因爲對於每個不同的郵政編碼值,「res」值將會不同,所以您需要將其餘的代碼放入我評論的區域內。否則,你只能得到最後一個值。

相關問題