【问题标题】:How to follow a link with data-params using rvest如何使用 rvest 跟踪带有数据参数的链接
【发布时间】:2017-07-07 13:56:13
【问题描述】:

我正在尝试从网络上抓取一个公共数据提供者,但是当我不得不单击一个将参数传递给 JS 的按钮时,我被卡住了。这是我的尝试:

require(rvest)
url <- 'https://myterna.terna.it/SunSet/Public/'
page <- url %>% read_html()
node_link <- page %>% html_node('.sub-item:nth-child(1) .postlink')

node_link我可以很容易地找到目标页面作为这个HTML标签的href

<a href="/SunSet/Public/Pubblicazioni"
   class="postlink"
   data-params="filter.IdSezione=52767620567B3077E053A8829B0A9478">

关键是我无法轻松检索链接页面的内容,因为还有其他按钮指向相同的链接。各种按钮之间的唯一区别是 data-params 属性,可能必须将其提供给 JS 才能检索特定内容。

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: html css r web-scraping rvest


    【解决方案1】:

    强制性提示:

    不清楚该网站是否允许抓取,Legal Notice 表示 授权复制本网站上发布的文件仅供个人使用,不得用于商业目的,前提是来源名称正确

    在尊重他们的服务条款的情况下使用它。

    单击该链接时检查网络活动,我们可以看到网页向https://myterna.terna.it/SunSet/Public/Pubblicazioni/List 发出POST 请求。我们可以找到请求的headers 和发送的params

    par <- '{"draw":1,"columns":[{"data":0,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":1,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":2,"name":"","searchable":false,"orderable":false,"search":{"value":"","regex":false}},{"data":3,"name":"","searchable":false,"orderable":false,"search":{"value":"","regex":false}},{"data":4,"name":"","searchable":false,"orderable":false,"search":{"value":"","regex":false}},{"data":5,"name":"","searchable":false,"orderable":false,"search":{"value":"","regex":false}},{"data":6,"name":"","searchable":false,"orderable":false,"search":{"value":"","regex":false}},{"data":7,"name":"","searchable":false,"orderable":false,"search":{"value":"","regex":false}}],"order":[],"start":0,"length":10,"search":{"value":"","regex":false},"filter":{"IdSezione":"52767620567B3077E053A8829B0A9478","Titolo":"","Id":"","ExtKey":"","TipoPubblicazione":"","SheetName":"","Anno":"2017","Mese":"7","Giorno":"","DataPubblicazione":"","TipoDatoPubblicazione":""},"details":{}}'
    

    这是json,我们可以根据需要解析和更改它的值(尽管我尝试了一些不同的过滤器,但没有太多响应)

    par <- jsonlite::fromJSON(par)
    par$filter$Mese <- '7'
    

    至于标题只有X-Requested-With:MLHttpRequest 是真正需要的,所以我们可以减少它。

    response <- POST('https://myterna.terna.it/SunSet/Public/Pubblicazioni/List', 
         add_headers('X-Requested-With' = 'XMLHttpRequest'),
         body = par,
         encode = 'json')
    
    json_data <- content(response)$data
    

    这会返回一个列表,我们可以安全地将其转换为数据框以方便使用:

    df <- data.frame(matrix(unlist(json_data), nrow=length(json_data), byrow=TRUE))
    
    head(df, 2)
    #>                                                                     X1
    #> 1       SbilanciamentoAggregatoZonale_SegnoGiornaliero_Orario_20170709
    #> 2 SbilanciamentoAggregatoZonale_SegnoGiornaliero_QuartoOrario_20170709
    #>                      X2
    #> 1 /Date(1499680800000)/
    #> 2 /Date(1499680800000)/
    #>                                                                                            X3
    #> 1 <div class="actions detail-inline export" data-pk="53F4A57FCB70304EE0532A889B0A7758"></div>
    #> 2 <div class="actions detail-inline export" data-pk="53F4A57FCB6D304EE0532A889B0A7758"></div>
    #>                                 X4 X5                              X6
    #> 1 53F4A57FCB70304EE0532A889B0A7758 25        SEGNO_MACROZONALE_ORARIO
    #> 2 53F4A57FCB6D304EE0532A889B0A7758 25 SEGNO_MACROZONALE_QUARTO_ORARIO
    #>                  X7            X8
    #> 1 Segno Giornaliero        Orario
    #> 2 Segno Giornaliero Quarto Orario
    

    【讨论】:

    • 谢谢@GGamba,你明白了!我认为网络上关于这个主题的内容并不多,所以你的贡献绝对有用!
    【解决方案2】:

    好的,基本上我错过了 HTTP 的工作机制。经过几天的学习,我了解到正确的方法是使用httr 包,如下所示。

    首先我从公共页面检索到所有需要的设置:

    lnkd_url <- paste0(dirname(dirname(url)),
                       node_link %>%
                           html_attr('href'))
    lnkd_id <- strsplit(zs_node %>%
                           html_attr('data-params'), '=')[[1]][2]
    

    那么就可以向目标页面发起POST请求了:

    lnkd_page <- POST(lnkd_url,
                      body = list('filter.IdSezione' = lnkd_id)
    

    就是这样!

    【讨论】:

      猜你喜欢
      • 2012-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多