如何使用 rvest 正确识别要解析的特定值

how to properly identify specific value to parse using rvest

亲爱的集体智慧

我正在努力尝试使用 rvest 从 https://www.1944.pl/powstancze-biogramy,ord,nazwisko,0,strona,1.html

中解析 table

我需要遍历 table 的所有节点并一一提取其值。然后迭代到下一页并重复。

我打算单独读取 table 值,因为我需要在代码中添加一个变体循环 - 对于每一行,如果“Data urodzenia”列中的值等于“-”,则程序应输入与该行对应的网页并提取其他值(标记为“Rocznik”)。

目前,我无法强制 rvest 从 table 中读取值。我想我不太遵循 html 选择器的想法...我可以使用以下函数中的 (".museumTableRow") 标签阅读整个 table (每页) :

library(rvest) 
library(tidyverse)

page <- read_html("https://www.1944.pl/powstancze-biogramy,ord,nazwisko,0,strona,1.html")
getPage <- function(html){
  html %>% 
    html_nodes(".museumTableRow") %>%      
    html_text() %>% 
    str_trim() %>%                       
    unlist()                             
}

Append_page <- getPage(page)

...但是当我尝试对 table 的特定单元格使用选择器时,我得到一个空的(“字符(0)”)响应。我试图通过手动检查页面并按照库创建者的建议使用 selectorgadget 插件来查找相关标签。这些看起来很奇怪(对我来说),例如。对于“Nazwisko”列中的名字,selectorgadget 建议:

".footable-even:nth-child(1) .footable-第一列.museumTableRow"

所以我也试着和他们一起玩,但我没有成功。我想我不完全理解它是如何工作的。对于如何强制 rvest 逐个单元格读取此 table 并将后续单元格中的值附加到 data.table.

的任何建议,我将不胜感激

我希望这足够具体。

这应该有效:

library(glue)
page <- read_html("https://www.1944.pl/powstancze-biogramy,ord,nazwisko,0,strona,1.html")
dat <- page %>% html_elements(css="tbody tr")  
txt <- dat %>% html_text()
hrefs <- dat %>% html_element("a") %>% html_attr("href")
s <- lapply(1:length(txt), function(i)trimws(strsplit(txt[i], split="\n")[[1]]))
out_txt <- t(sapply(s, function(x)x[which(x != "")]))
stem <- "https://www.1944.pl"
for(i in 1:nrow(out_txt)){
  if(out_txt[i,6] == "-"){
    u <- paste0(stem, hrefs[i])
    h <- read_html(u)
    btxt <- h %>% html_elements(css="div.biogram--info div.tag") %>% html_text()
    ind <- grep("Rocznik", btxt)
    if(length(ind) > 0){
      btxt2 <-   h %>% html_elements(css=glue("div.biogram--info div.info")) %>% html_text()
      out_txt[i,6] <- btxt2[ind]
    }else{
      out_txt[i,6] <- NA_character_
    }
  }
}
head(out_txt)
#             [,1]          [,2]         [,3]      [,4]            [,5]                [,6]         [,7]        
# [1,] "Abajew"      "Aleksander" "-"       "-"             "-"                 "1916-06-06" "-"         
# [2,] "Abakanowicz" "Piotr"      "-"       "-"             "\"Grey\""          "1890-06-21" "1948-06-01"
# [3,] "Abakanowicz" "Maria"      "-"       "-"             "\"Lena\""          "1901"       "-"         
# [4,] "Abczyńska"   "Alicja"     "Henryka" "sanitariuszka" "\"Ciocia Stasia\"" "1900-02-09" "1989-04-26"
# [5,] "Abczyńska"   "Janina"     "-"       "pielęgniarka"  "\"Julia\""         "1883-06-15" "1944-08-30"
# [6,] "Abczyński"   "Stanisław"  "-"       "-"             "\"Stefan\""        NA           "-"         

在上面的代码中,它获取了行中第一个 <a> 标签的数据和 href。如果第 i 行的第 6 列是 "-",它就会转到该引用。如果有一个标记为 "Rocznik" 的条目,如果存在则获取年份,否则用缺失值替换该条目。


编辑:关于 CSS 选择器的详细信息

我假设 stem <- "https://www.1944.pl" 部分之前的所有内容都非常简单,因为它或多或少都遵循您已经走的路。那么,让我们深入研究 for 循环以及它们是如何工作的。正如您所指出的,最初第三行在第六列中有一个 "-" 作为其条目,这应该会触发另一次查找。所以,这意味着应该遵循第三个 href:

hrefs[3]
# [1] "/powstancze-biogramy/maria-abakanowicz,845.html"

为此,我们可以将其粘贴到之前定义的 stem 上以生成有效的 URL,我们将其读入 h。如果您在浏览器中访问 URL,您会看到:

您希望能够识别与“Rocznik”关联的号码。如果您 right-click 选择“Rocznik”一词并选择“检查”,您将看到:

您会注意到所有条目都在 <div> 和 class "biogram--info" 中。此外,每个条目的标题都在 <div> 和 class "tag" 中。我编辑了上面的答案,通过使用 "tag" div 使结果更清晰一些。 btxt 的结果如下所示:

btxt <- h %>% 
  html_elements(css="div.biogram--info div.tag") %>% 
  html_text()
btxt
# [1] "Pseudonim:"                      
# [2] "Data urodzenia:"                 
# [3] "Data śmierci:"                   
# [4] "Funkcja:"                        
# [5] "Rocznik:"                        
# [6] "Stopień:"                        
# [7] "Pseudonimy:"                     
# [8] "Udział w konspiracji 1939-1944:" 
# [9] "Oddział:"                        
# [10] "Szlak bojowy:"                   
# [11] "Miejsce (okoliczności) śmierci :"
# [12] "Uwagi:"                          
# [13] "Publikacje :"   

然后,您可以找出哪一个是“Rocznik”——在本例中是第五个。在原始答案中(我已对其进行编辑以使其更清晰),我有

btxt2 <-   h %>% 
  html_elements(css=glue("div.biogram--info:nth-child({ind-1})")) %>%   
  html_text()

首先,机械原理 - glue() 函数类似于 paste()paste0(),但有时它的作用更清晰一些。在上面的语句中:

glue("div.biogram--info:nth-child({ind-1})")

将等同于以下任何一个:

paste0("div.biogram--info:nth-child(", ind-1, ")")
paste("div.biogram--info:nth-child(", ind-1, ")", sep="")

glue() 中,大括号 {} 中出现的任何内容都会在 R 中进行计算,然后将结果放入文本中。从上面的代码 ind 识别出与“Rocznik”相关联的值 <div>,但是当我们查看 div.biogram--info 的孩子时,我们看到一些 children 有多个条目。这是第四个 child ind-1 拥有“Rocznik”条目。

h %>% 
  html_elements(css="div.biogram--info:nth-child(1)") %>% 
  html_text()
# [1] "\n                        Pseudonim:\n                        \"Lena\"\n                    "                      
# [2] "\n                                Data urodzenia:\n                                -\n                            "
# [3] "\n                                Data śmierci:\n                                -\n                            "  

h %>% 
  html_elements(css="div.biogram--info:nth-child(2)") %>% 
  html_text()
# character(0)

h %>% 
  html_elements(css="div.biogram--info:nth-child(3)") %>% 
  html_text()
# [1] "\n                        Funkcja:\n                        -\n                    "

h %>% 
  html_elements(css="div.biogram--info:nth-child(4)") %>% 
  html_text()
# [1] "\n                                Rocznik:\n                                1901\n                            "

然后代码只提取它找到的任何连续数字。我已经将上面的答案编辑为可能更可靠的答案。如果你回头看看 html 来源的图片,你会看到对于每个 "biogram--info" div,都有一个 "tag" class div 保存标题和 "info" class div 保存与该标题关联的值。使用以下代码,您可以检索与每个 "tag" 条目相对应的所有 "info" 条目:

btxt2 <- h %>% 
  html_elements(css=glue("div.biogram--info div.info")) %>% 
  html_text()
btxt2
# [1] "\"Lena\""                                                                                                                                                                                                                                         
# [2] "-"                                                                                                                                                                                                                                                
# [3] "-"                                                                                                                                                                                                                                                
# [4] "-"                                                                                                                                                                                                                                                
# [5] "1901"                                                                                                                                                                                                                                             
# [6] "starszy strzelec"                                                                                                                                                                                                                                 
# [7] "\"Lenarska\", \"Lena\""                                                                                                                                                                                                                           
# [8] "Narodowe Siły Zbrojne - Okręg I A Warszawa-Miasto"                                                                                                                                                                                                
# [9] "Armia Krajowa - Grupa \"Północ\" - zgrupowanie \"Sienkiewicz\" - następnie odcinek bojowy \"Kuba\" - \"Sosna\" - kompania P-20, następnie w 1. batalionie szturmowym KB \"Nałęcz\" . W Śródmieściu w batalionie KB \"Sokół\"  - patrol sanitarny."
# [10] "Stare Miasto - kanały - Śródmieście Północ"                                                                                                                                                                                                       
# [11] " Poległa na ul. Kopernika (VIII-IX 1944). Inne wersja - zmarła 1992-10-10\n"                                                                                                                                                                      
# [12] "Inny spotykany przydział  - Narodowe Siły Zbrojne - Grupa \"Topór\""                                                                                                                                                                              
# [13] "Wielka Ilustrowana Encyklopedia Powstania Warszawskiego Suplement, Warszawa, 2009"  

要获取与“Rocznik”关联的值,您可以采用 btxt2ind 条目,就像现在在上面的答案中所做的那样。