html - R - 将唯一的 HTML/XML 消息解析为数据框

标签 html r xml html-parsing rvest

我正在尝试从 R 中的唯一格式的 XML 消息创建数据框。下面是消息的片段:

000

SXUS70 KWNB 140043

PROG 045004300<?xml version="1.0" encoding="ISO-8859-1"?><XYZ><pn>901392</pn><gpslat>40</gpslat><gpslon>-100</gpslon><met><date>2018-02-14T00:40:00Z</date><sbar1>1021.4</sbar1><wspd1>4.1</wspd1><wdir1>132</wdir1><rwd1>92</rwd1><gust1>5.1</gust1><mxmin1>35</mxmin1><mx1mgt1>4.5</mx1mgt1><mx1mmin1>38</mx1mmin1><ccomp1>40</ccomp1><comptilt>2.127</comptilt></met><MSG1> SOMESTRINGOFTEXT</MSG1></XYZ> 00-0NN  00E

000

SXUS70 KWNB 140043

PROG 045004327<?xml version="1.0" encoding="ISO-8859-1"?><XYZ><pn>902084</pn><gpslat>40</gpslat><gpslon>-100</gpslon><met><date>2018-02-14T00:40:00Z</date><wtmp1>11.4749</wtmp1></met><MSG1> SOMESTRINGOFTEXT<</MSG1></XYZ> 00-0NN  00E

000

SXUS70 KWNB 140053

PROG 045005306<?xml version="1.0" encoding="ISO-8859-1"?><XYZ><waves><date>2018-02-14T00:40:06Z</date><c11m>0.00130;0.00121;0.00156;0.00177;0.00297;0.00452;0.00825;0.01872;0.07662;0.16415;0.23008;0.22462;0.17013;0.36109;0.75136;0.38618;0.43994;0.28302;0.55485;0.52451;0.54084;0.33147;0.29831;0.39193;0.57365;0.50373;0.49669;0.39183;0.59545;0.41549;0.35005;0.40040;0.26235;0.25397;0.22672;0.51727;0.32366;0.27279;0.28407;0.38603;0.31636;0.29787;0.35072;0.41960;0.23254;0.21483;0.20732;</c11m><accxmean>-0.178</accxmean><accxmin>-1.192</accxmin><accxmax>0.749</accxmax><accxstd>0.302</accxstd><accymean>-0.138</accymean><accymin>-1.341</accymin><accymax>1.231</accymax><accystd>0.334</accystd><acczmean>-0.018</acczmean><acczmin>-1.360</acczmin><acczmax>1.473</acczmax><acczstd>0.418</acczstd><acczvsmean>-0.023</acczvsmean><acczvsmin>-1.382</acczvsmin><acczvsmax>1.472</acczvsmax><acczvsstd>0.415</acczvsstd><arxmean>0.002</arxmean><arxmin>-0.205</arxmin><arxmax>0.201</arxmax><arxstd>0.064</arxstd><arymean>0.002</arymean><arymin>-0.189</arymin><arymax>0.211</arymax><arystd>0.058</arystd><arzmean>-0.002</arzmean><arzmin>-0.033</arzmin><arzmax>0.038</arzmax><arzstd>0.010</arzstd><pitchmean>-1.036</pitchmean><pitchmin>-5.855</pitchmin><pitchmax>4.645</pitchmax><pitchstd>1.532</pitchstd><rollmean>0.803</rollmean><rollmin>-4.800</rollmin><rollmax>6.730</rollmax><rollstd>1.768</rollstd><bmean>578.579</bmean><bmin>576.342</bmin><bmax>585.731</bmax><bstd>1.050</bstd><bdmean>275.751</bdmean><bdmin>228.331</bdmin><bdmax>312.689</bdmax><bdstd>11.936</bdstd><azinit>116.889</azinit><azmean>59.646</azmean><azmaxccw>46.525</azmaxccw><azmaxcw>60.144</azmaxcw><azstd>18.708</azstd><tiltmean>2.367</tiltmean><tiltmin>0.069</tiltmin><tiltmax>6.880</tiltmax><tiltstd>1.258</tiltstd><nsmean>0.166</nsmean><nsmin>-4.932</nsmin><nsmax>6.132</nsmax><nsstd>1.555</nsstd><ewmean>-1.229</ewmean><ewmin>-6.647</ewmin><ewmax>4.137</ewmax><ewstd>1.804</ewstd><bey>276.078</bey><bez>-508.459</bez><phim>10;-36;-56;-56;13;21;8;23;7;-7;-14;-5;6;-5;-5;-10;-7;-11;-5;-8;-9;-6;9;-5;-18;-21;-15;-7;17;-15;7;20;-1;-20;-20;13;-27;-34;33;10;14;-28;-26;-24;-37;-55;-32;</phim><rhq>2.83;1.10;1.49;6.11;6.14;5.31;4.03;2.20;1.21;1.06;0.96;0.91;0.99;0.99;0.84;0.90;0.78;0.88;0.76;0.76;0.80;0.98;0.97;0.88;0.77;0.72;0.71;0.96;0.97;0.88;1.02;0.88;1.29;1.17;1.13;0.86;1.15;1.15;1.16;1.08;1.18;1.34;1.11;1.10;1.15;1.12;1.02;</rhq><gamma2>-174;-154;63;62;-12;3;14;-7;-12;-5;0;-2;-2;0;3;-1;3;1;0;1;2;-1;2;-6;-5;9;1;-7;2;1;-1;0;-39;-2;3;0;-3;-7;-3;-6;2;22;23;1;7;119;-139;</gamma2><gamma3>169;158;-14;-23;14;-10;-60;-118;-141;-160;179;-171;-167;178;171;-179;174;173;179;175;172;-179;160;-168;-149;149;168;-128;-62;172;-143;91;-154;-141;-56;74;-167;-152;74;-153;177;167;172;180;178;-171;179;</gamma3><r1>0.593;0.772;0.420;0.162;0.226;0.308;0.331;0.339;0.649;0.756;0.822;0.795;0.836;0.906;0.907;0.864;0.902;0.906;0.919;0.873;0.907;0.861;0.790;0.789;0.792;0.722;0.607;0.663;0.531;0.621;0.489;0.268;0.170;0.503;0.447;0.659;0.531;0.371;0.454;0.665;0.508;0.494;0.575;0.609;0.529;0.409;0.664;</r1><r2>0.636;0.553;0.501;0.641;0.596;0.558;0.604;0.585;0.511;0.750;0.835;0.766;0.764;0.879;0.877;0.751;0.855;0.762;0.804;0.716;0.800;0.676;0.653;0.787;0.598;0.537;0.398;0.409;0.444;0.511;0.227;0.320;0.355;0.482;0.482;0.519;0.393;0.429;0.322;0.592;0.239;0.182;0.080;0.203;0.172;0.351;0.517;</r2><alpha1>53;42;200;205;227;240;249;285;297;296;298;295;293;296;298;310;304;294;296;299;298;309;286;306;291;297;288;287;263;287;279;270;322;282;259;268;294;296;264;295;315;323;331;337;333;16;7;</alpha1><alpha2>29;34;233;154;150;322;325;329;309;306;305;304;298;299;302;315;306;295;297;301;298;309;287;302;289;302;300;291;288;301;303;291;294;290;256;273;290;285;236;283;263;314;295;11;17;67;12;</alpha2><ewvhgt>1.892</ewvhgt><edompd>10.000</edompd></waves><pn>902077</pn><gpslat>40</gpslat><gpslon>-100</gpslon><MSG1> SOMESTRINGOFTEXT<</MSG1></XYZ> 00-0NN  00E

000

SXUS70 KWNB 140053

PROG 045005342<?xml version="1.0" encoding="ISO-8859-1"?><XYZ><pn>901392</pn><gpslat>40</gpslat><gpslon>-100</gpslon><met><date>2018-02-14T00:50:00Z</date><sbar1>1021.4</sbar1><wspd1>4.4</wspd1><wdir1>133</wdir1><rwd1>75</rwd1><gust1>5.6</gust1><mxmin1>46</mxmin1><mx1mgt1>4.7</mx1mgt1><mx1mmin1>45</mx1mmin1><ccomp1>58</ccomp1><comptilt>2.184</comptilt></met><MSG1> SOMESTRINGOFTEXT<</MSG1></XYZ> 00-0NN  00E

我能够将大部分数据放入数据框中,并通过将日期与以下代码匹配来将它们合并在一起:

library(rvest)
library(dplyr)

t <-
  read_html(paste0("~/MSGS/test_msg"))

pn <- html_nodes(t, xpath = "//pn") %>% html_text()
date <- html_nodes(t, xpath = "//date") %>% html_text()
lat <- html_nodes(t, xpath = "//gpslat") %>% html_text()
lon <- html_nodes(t, xpath = "//gpslon") %>% html_text()
msg <- html_nodes(t, xpath = "//msg") %>% html_text()
dat <- as_tibble(data.frame(bind_cols(
  pn = pn,
  date = date,
  lat = lat,
  lon = lon,
  msg = msg
)))
met_names <- html_nodes(t, xpath = "//met") %>%
  xml_children() %>% html_name() %>% unlist() %>% unique()
wav_names <- html_nodes(t, xpath = "//waves") %>%
  xml_children() %>% html_name() %>% unlist() %>% unique()
met_names1 <- paste0('//met/', met_names)
wav_names1 <- paste0('//waves/', wav_names)

wav_ls <- list()
for (i in seq_along(wav_names1)) {
  wav_ls[[i]] <-
    html_nodes(t, xpath = paste0(wav_names1[i])) %>% html_text()
}

met_ls <- list()
for (i in seq_along(met_names1)) {
  met_ls[[i]] <-
    html_nodes(t, xpath = paste0(met_names1[i])) %>% html_text()
}


df <- as_tibble(as.data.frame(wav_ls))
colnames(df) <- wav_names

dat$date <- as.POSIXct(dat$date, format = "%Y-%m-%dT%H:%M:%SZ")
df$date  <- as.POSIXct(df$date, format = "%Y-%m-%dT%H:%M:%SZ")
test_df <- as_tibble(merge(dat, df, by = "date", all.x = T))

df1 <- as_tibble(as.data.frame(met_ls)) # This is where I run into issues
colnames(df1) <- met_names

df1$date  <- as.POSIXct(df1$date, format = "%Y-%m-%dT%H:%M:%SZ")
test_df <- as_tibble(merge(test_df, df1, by = "date", all.x = T))

问题是,有时我无法将列表强制转换为数据框,因为列表由于缺少值/节点而具有不同的长度。此外,我想让日期和观察结果保持一致,这也是一个问题。

是否有更清晰、更有效的方法将这些数据解析为数据帧?上面的示例只是部分示例,实际上,我一次要处理数千条这样的消息。

最佳答案

所以我想我想出了我需要做什么,它可能很难看,但它有效。

library(xml2)
library(rvest)
library(plyr)
library(tidyverse)



SCP.read_xml <- function(file) {

    some.html <-  as_list(html_nodes(read_html(file), xpath = '//xyz'))

    df <- list()
    for (i in seq_along(some.html)) {
      df[[i]] <- data.frame(
        'pn' = some.html[[i]][["pn"]][[1]],
        'date' = if (!is.null(some.html[[i]][["met"]][["date"]][[1]])) {
          some.html[[i]][["met"]][["date"]][[1]]
        } else if (!is.null(some.html[[i]][["waves"]][["date"]][[1]])) {
          some.html[[i]][["waves"]][["date"]][[1]]
        }  else {
          some.html[[i]][["gps"]][["date"]][[1]]
        },
        'lat' = ifelse(length(some.html[[i]][["gpslat"]]) > 0, some.html[[i]][["gpslat"]][[1]], NA),
        'lon' = ifelse(length(some.html[[i]][["gpslon"]]) > 0, some.html[[i]][["gpslon"]][[1]], NA),
        'msg' = some.html[[i]][["msg1"]][[1]]
      )

    }

    test <- as_tibble(ldply(df, data.frame))

    return(test)

  }


SCP.read_xml('~/some_html.txt')

输出:

# A tibble: 4 x 5
  pn     date                 lat   lon   msg                  
  <fct>  <fct>                <fct> <fct> <fct>                
1 901392 2018-02-14T00:40:00Z 40    -100  " 'SOMESTRINGOFTEXT'"
2 902084 2018-02-14T00:40:00Z 40    -100  " 'SOMESTRINGOFTEXT'"
3 902077 2018-02-14T00:40:06Z 40    -100  " 'SOMESTRINGOFTEXT'"
4 901392 2018-02-14T00:50:00Z 40    -100  " 'SOMESTRINGOFTEXT'"

这允许我一次将函数应用于许多消息的列表,甚至可以一次性将它们组合到一个数据框中。我扩展了上面的代码以从这些消息中提取出许多 (~85) 个变量。

关于html - R - 将唯一的 HTML/XML 消息解析为数据框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52573771/

相关文章:

html - Angular ngIf formGroup

javascript - 是否可以根据屏幕尺寸设置表格选项?

performance - 是什么导致我的运行时间比用户时间长得多?

xml - 将 JSON 转换为 XML 并返回是否有严格的规则?

php - 创建一个函数来替换从 XML 文件获取的字符串

html - 背景颜色不适用于调整大小/恢复向下窗口

javascript - 音频范围音量 slider Javascript/HTML5

r - 如何绘制 R 表的箱线图?

r - 获取data.table中上一组的最后一行

ios - 在转发类对象中找不到属性