使用Rvest抓取<li>元素

3
早上好,
我是新手,正在使用R进行爬虫,但我在以一种有用的方式从网页上抓取元素列表方面遇到了困难。
以下是我的脚本:
library(rvest)

url <- read_html("https://www.pole-emploi.fr/annuaire/provins-77070")

webpage <- url %>%
  html_nodes('.zone') %>%
  html_text()
webpage
 

当我运行脚本时,所有的元素都挤在一起,没有任何空格分隔,这是可以理解的,因为每个项目都被包含在单独的

  • 标签中。
  •  [1] "77114GouaixHerméNoyen-sur-SeineVilliers-sur-Seine"                                                                                                                                 
     [2] "77118BalloyBazoches-lès-BrayGravon"     
    

    我希望它们要么像这样(或者用逗号分隔)。
    [1] "77114 Gouaix Hermé Noyen-sur-Seine Villiers-sur-Seine"                                                                                                                                 
    [2] "77118 Balloy Bazoches-lès-Bray Gravon"
    

    甚至更好的是以整洁的格式呈现。
     Postal City
     77114  Gouaix
     77114  Hermé
     77114  Noyen-sur-Seine
     77114  Villiers-sur-Seine
    

    我试图在页面中找到其他选择器或Xpath,但没有成功。最多只能选择列表中的一个单独元素。

    如有帮助,将不胜感激。

    提前致谢。

    1个回答

    5
    每个列表元素都长这样(为了简洁而截断):
    <li class="zone">\n<span class="code-postal">77114</span><ul>\n<li>Gouaix</li>\n<li>Hermé</li>\n ...
    

    因此,每个节点都有一组看起来相同的子节点。我们可以针对嵌套的<ul>中的<span><li>元素来获取您想要的内容:

    library(rvest)
    library(tidyverse)
    
    pg <- read_html("https://www.pole-emploi.fr/annuaire/provins-77070")
    
    html_nodes(pg, ".zone") %>% 
      map_df(~{
        data_frame(
          postal = html_node(.x, "span") %>% html_text(trim=TRUE),
          city = html_nodes(.x, "ul > li") %>% html_text(trim=TRUE)
        )
      }) 
    ## # A tibble: 95 x 2
    ##    postal city                 
    ##    <chr>  <chr>                
    ##  1 77114  Gouaix               
    ##  2 77114  Hermé                
    ##  3 77114  Noyen-sur-Seine      
    ##  4 77114  Villiers-sur-Seine   
    ##  5 77118  Balloy               
    ##  6 77118  Bazoches-lès-Bray    
    ##  7 77118  Gravon               
    ##  8 77126  Châtenay-sur-Seine   
    ##  9 77126  Égligny              
    ## 10 77134  Les Ormes-sur-Voulzie
    ## # ... with 85 more rows
    

    使用显式匿名函数的tidyverse方法(与通过公式函数使用.x不同):
    html_nodes(pg, ".zone") %>% 
      map_df(function(x) {
        data_frame(
          postal = html_node(x, "span") %>% html_text(trim=TRUE),
          city = html_nodes(x, "ul > li") %>% html_text(trim=TRUE)
        )
      }) 
    

    同时,还有一个纯粹的基于R的版本:

    elements <- html_nodes(pg, ".zone")
    lapply(elements, function(x) {
      data.frame(
        postal = html_text(html_node(x, "span"), trim=TRUE),
        city = html_text(html_nodes(x, "ul > li"), trim=TRUE),
        stringsAsFactors = FALSE
      )
    }) -> tmp
    
    Reduce(rbind.data.frame, tmp)
    
    # or
    
    do.call(rbind.data.frame, tmp)
    

    非常感谢!那非常有用。只有一个问题,html_node(.x, "span") 中的 .x 是否是将 ".zone" 转发到此嵌套的 html_node 元素的占位符?再次感谢。 - Camilo Moreno
    我添加了两个额外的解决方案,希望能够帮助说明正在发生的事情。主要示例中的“~{}”是一个整洁的purrr“公式函数”,它具有隐含的变量名.x(或只是.)可供使用。它是一种语法糖,有助于简化代码,但像Scala代码中的“_”一样,它只是“从无处弹出一个变量”,并且在第一眼看起来肯定会让人感到困惑。 - hrbrmstr
    非常感谢您添加的评论。现在更加清晰了。 - Camilo Moreno

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接