我正在尝试网络抓取一个公共数据提供者,但是当我不得不点击一个将参数传递给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才能检索特定内容。
关于如何解决问题的任何想法?
答案 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
请求。我们可以找到请求的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