用Rvest废弃<li>元素

时间:2018-10-04 15:36:53

标签: r rvest

早上好

我刚开始使用R进行抓取,现在很难以有用的方式从网页中抓取元素列表。

这是我的剧本

 [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
    

    或更整洁的格式

    public void CopyFiles(string listTitle, string srcRelativeSource, string destRelativeSource)
        {
            var srcList = ClientContext.Web.Lists.GetByTitle(listTitle);
            var qry = CamlQuery.CreateAllItemsQuery();
            qry.FolderServerRelativeUrl = string.Format("/{0}", srcRelativeSource);
            var srcItems = srcList.GetItems(qry);
            ClientContext.Load(srcItems, icol => icol.Include(i => i.FileSystemObjectType, i => i["FileRef"], i => i.File));
            ClientContext.ExecuteQuery();
    
            createThisFolder(destRelativeSource);
    
            foreach (var item in srcItems)
            {
                switch (item.FileSystemObjectType)
                {
                    case FileSystemObjectType.Folder:
                        var destFolderUrl = ((string)item["FileRef"]).ToLower().Replace(srcRelativeSource, destRelativeSource);
                        createThisFolder(destFolderUrl);
                        break;
                    case FileSystemObjectType.File:
                        var destFileUrl = item.File.ServerRelativeUrl.ToLower().Replace(srcRelativeSource, destRelativeSource);
                        item.File.CopyTo(destFileUrl, true);
                        ClientContext.ExecuteQuery();
                        break;
                }
            }
        }
    
        private void createThisFolder(string destFolderUrl)
        {
            //change destFolderUrl into absolute url
            Uri u = new Uri(ClientContext.Web.Context.Url);
    
            //remove the string after the last slash
            int idx = destFolderUrl.LastIndexOf('/');
            string path = destFolderUrl.Substring(0, idx);
            string lastFolder = destFolderUrl.Split('/').Last();
    
            string filtered = (path.StartsWith("/")) ? path.Substring(1) : path;
    
            string url = u.GetLeftPart(UriPartial.Authority) + "/" + filtered;
            CreateFolder(url, lastFolder);
        }      
    

    我尝试在页面中找到其他选择器或Xpath,但未成功。我得到的最多是选择列表中的一个元素。

    非常感谢任何帮助。

    谢谢。

  • 1 个答案:

    答案 0 :(得分:3)

    每个列表元素看起来像这样(为简洁起见被截断):

    <li class="zone">\n<span class="code-postal">77114</span><ul>\n<li>Gouaix</li>\n<li>Hermé</li>\n ...
    

    因此,每个节点都有一组看起来统一的子节点。我们可以将嵌套<span>中的<li><ul>元素作为目标,以获取所需的内容:

    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
    

    具有显式匿名功能(通过公式函数与.x相比)的tidyverse方法:

    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)