如何使用rvest跟踪数据参数的链接

时间:2017-07-07 13:56:14

标签: html css r web-scraping rvest

我正在尝试网络抓取一个公共数据提供者,但是当我不得不点击一个将参数传递给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才能检索特定内容。

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

2 个答案:

答案 0 :(得分:1)

好的,基本上我错过了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)

那就是它!

答案 1 :(得分:1)

强制性单挑:

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

请遵守他们的服务条款。

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

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