Зачистка ускользнул JSON данных в пределах - PullRequest
1 голос
/ 25 февраля 2020

В настоящее время я пытаюсь собрать данные из двух графиков на следующей странице html (информация из двух перечисленных там графиков: Forsmark и Ringhals): https://group.vattenfall.com/se/var-verksamhet/vara-energislag/karnkraft/aktuell-karnkraftsproduktion

данные берутся из тегов сценария, подобных этому (фрагмент)

<script type="text/javascript">
/*<![CDATA[*/ productionData = JSON.parse("{\"timestamp\":1582642616000,\"powerPlant\":\"Ringhals\", // etc
</script>

Я хотел бы получить два кадра данных, которые выглядят следующим образом:

F1          F2          F3       
number      number      number 

и

R1          R2          R3       
number      number      number  

Я пытался использовать XML и xpath для разбора html страницы, но ничего с этим не получилось.

У вас есть идеи?

Спасибо!

1 Ответ

1 голос
/ 25 февраля 2020

Эти диаграммы <iframe> с загружаются из

так что вы должны очистить эти две страницы напрямую.

Это был интересный вызов.

Это становится не слишком сложно с rvest и jsonlite, который вам придется установить, если у вас его еще нет. Оба требуют rtools.

Попробуйте это:

library('rvest')
library('jsonlite')

# Load the URL (do the same for the other iframe)
url <- 'https://gvp.vattenfall.com/sweden/produced-power/iframe/forsmark'

# Parse it
webpage <- read_html(url)

# Extract the script element. That's a CSS selector for the specific one that holds the json data
# You can find it in your browser's DevTools by finding the script element
# and right-clicking, choosing Copy > CSS Path/Selector
script_element <- html_nodes(webpage, 'body > section:nth-child(2) > script:nth-child(2)')

# Extract its string content
json = html_text(script_element)

# Clean it up
json = gsub("\n        /*<![CDATA[*/\n        productionData = JSON.parse(", "", json, fixed=TRUE)
json = gsub(");\n        /*]]>*/\n    ", "", json, fixed=TRUE)
json = gsub("\"{", "{\"", json, fixed=TRUE)
json = gsub("}\"", "}", json, fixed=TRUE)
json = gsub("{\"\\\"", "{\\\"", json, fixed=TRUE)

# Extract data
data = jsonlite::fromJSON(gsub("\\\"", "\"", json, fixed=TRUE))

Предостережение: Я не совсем эксперт по R, вероятно, есть более элегантный способ сделать это (особенно часть очистки данных). Но это работает.

Для исторического сохранения, который берет этот узел DOM (текстовое содержимое тега <script>):

"\n        /*<![CDATA[*/\n        productionData = JSON.parse(\"{\\\"timestamp\\\":1582643336000,\\\"powerPlant\\\":\\\"Forsmark\\\",\\\"blockProductionDataList\\\":[{\\\"name\\\":\\\"F1\\\",\\\"production\\\":998.86194,\\\"percent\\\":99.88619},{\\\"name\\\":\\\"F2\\\",\\\"production\\\":1120.434,\\\"percent\\\":97.8545},{\\\"name\\\":\\\"F3\\\",\\\"production\\\":1189.7126,\\\"percent\\\":99.55754}]}\");\n        /*]]>*/\n    "

и приведет к данным этого формата

> data
$timestamp
[1] 1.582647e+12

$powerPlant
[1] "Forsmark"

$blockProductionDataList
  name production  percent
1   F1   997.7902 99.77902
2   F2  1131.6150 98.83100
3   F3  1190.0520 99.58594
...