R语言中从HTML页面提取并解析内嵌JSON数据

DDD
发布: 2025-10-02 11:09:00
原创
886人浏览过

R语言中从HTML页面提取并解析内嵌JSON数据

本文详细阐述了在R语言中如何处理HTML页面内嵌的JSON数据。通过结合rvest包获取页面文本内容,并利用jsonlite包解析JSON字符串,可以高效地从非标准HTML结构中提取所需的嵌套数据,尤其适用于那些将JSON作为纯文本内容嵌入到HTML中的场景,最终将复杂数据转换为R中的数据框或矩阵以便进一步分析。

引言:R语言中处理HTML内嵌JSON数据的挑战

在进行网络数据抓取时,我们经常会遇到数据以json格式存在,但却被嵌入到html页面中的情况。传统的rvest包的html_nodes()函数主要用于选择html标签和属性,对于直接以纯文本形式存在于html结构中的json数据则束手无策。例如,当一个网页的源代码看起来像一个json数组,但被read_html()加载后,它被视为html文档中的一个文本节点,而不是可供html_nodes()直接查询的结构。此时,理解如何正确地提取并解析这些内嵌的json数据,是r语言网络爬虫的关键技能。

准备工作:所需R包

为了完成这项任务,我们需要用到以下两个R包:

  • rvest: 用于从网页读取HTML内容。
  • jsonlite: 用于解析JSON格式的字符串。

如果尚未安装,可以通过以下命令进行安装:

install.packages(c("rvest", "jsonlite"))
登录后复制

第一步:获取HTML页面内容

首先,我们需要使用rvest包中的read_html()函数来加载目标网页。即使页面内容看起来像是纯JSON,read_html()也会尝试将其解析为HTML文档结构。

library(rvest)
library(jsonlite) # 提前加载jsonlite

# 假设目标URL是包含JSON数据的页面
# 请替换为实际的URL
url <- "https://mywebsite.com/data.json" # 示例URL,实际可能指向一个包含JSON的HTML页面
page_content <- read_html(url)

# 此时的page_content是一个html_document对象
# 它的内部可能包含一个<body>或<p>标签,其中包含了JSON字符串
print(page_content)
登录后复制

通过print(page_content),你可能会看到类似<body><p>[{"title1":"abc 123", ...}]</p></body>的输出,这表明JSON数据被当作HTML中的普通文本内容。

立即学习前端免费学习笔记(深入)”;

第二步:提取原始JSON字符串

由于JSON数据被视为HTML文档中的文本内容,我们不能直接使用html_nodes()来选择它。相反,我们需要使用html_text()函数来提取整个HTML文档的文本内容。这个函数会返回一个包含HTML文档中所有可见文本的字符串,其中就包括了我们想要的JSON字符串。

# 提取HTML文档的纯文本内容
json_string <- html_text(page_content)

# 打印部分字符串以确认是否包含JSON数据
head(json_string, 500) # 打印前500个字符
登录后复制

这一步的关键在于,html_text()能够获取到包含JSON数据的完整字符串。如果HTML页面中包含其他不相关的文本,你可能需要进一步处理json_string,例如使用正则表达式grep或gsub来精确提取JSON部分。但在许多情况下,如果页面主体就是JSON,直接提取即可。

第三步:解析JSON数据

获得了原始的JSON字符串后,下一步就是使用jsonlite包的parse_json()函数将其解析为R中的数据结构。parse_json()函数可以将JSON字符串转换为R的列表(list)或数据框(data frame)等对象。

Find JSON Path Online
Find JSON Path Online

Easily find JSON paths within JSON objects using our intuitive Json Path Finder

Find JSON Path Online 30
查看详情 Find JSON Path Online

一个非常有用的参数是simplifyDataFrame = TRUE。当JSON结构允许时,它会尝试将嵌套的JSON对象自动简化为数据框,这大大方便了后续的数据处理。

# 解析JSON字符串
parsed_data <- parse_json(json_string, simplifyDataFrame = TRUE)

# 查看解析后的数据结构
str(parsed_data)
登录后复制

此时,parsed_data通常会是一个列表或数据框,其结构与原始JSON的层级结构相对应。例如,如果JSON是一个数组,parsed_data可能是一个数据框或一个包含多个列表元素的列表。

第四步:提取并整理特定嵌套数据

根据原始JSON的结构,我们现在可以访问和提取所需的特定数据。以问题中提到的"title7"为例,它是一个嵌套在"title4"中的列表,每个元素又是一个包含两个数值的向量。

# 访问嵌套的title4和title7数据
title7_list <- parsed_data$title4$title7

# title7_list现在是一个列表,每个元素是一个数值向量
# 我们可以使用do.call(rbind, ...)将其转换为一个矩阵
final_result <- do.call(rbind, title7_list)

# 将矩阵转换为数据框,并添加ID列和有意义的列名
final_df <- as.data.frame(final_result)
colnames(final_df) <- c("title7_1", "title7_2")
final_df$id <- 1:nrow(final_df) # 添加一个ID列
final_df <- final_df[, c("id", "title7_1", "title7_2")] # 重新排序列

# 打印最终结果
print(final_df)
登录后复制

这段代码首先通过parsed_data$title4$title7访问到包含所有title7数据的列表。然后,do.call(rbind, ...)是一个非常方便的技巧,可以将一个由向量组成的列表绑定成一个矩阵,从而将嵌套的数值数据扁平化。最后,将矩阵转换为数据框并进行列名和ID的整理,使其符合最终期望的输出格式。

完整示例代码

下面是整合上述所有步骤的完整示例代码:

library(rvest)
library(jsonlite)
library(dplyr) # 用于数据框操作,如select、mutate等

# 1. 模拟一个包含JSON的HTML页面(实际操作中替换为真实URL)
# 注意:这里为了演示,我直接创建了一个包含JSON字符串的HTML内容
# 实际URL可能直接返回JSON,但read_html仍可能将其包装在HTML标签内
# 假设我们访问的URL内容如下:
# [
#   {
#     "title1" : "abc 123",
#     "title2" : "bca 321",
#     "title3" : "cba 213",
#     "title4" : {"title5": "title6", "title7": [ -17662.3456, 987621.7654]}
#   },
#   {
#     "title1" : "aec 183",
#     "title2" : "bga 351",
#     "title3" : "cha 293",
#     "title4" : {"title5": "title6", "title7": [ -1621626123.23234, 652238322.122]}
#   }
# ]
# 为了模拟read_html的行为,我们假设它被包装在<p>标签内
mock_html_content <- '<html><body><p>[\n{\n"title1" : "abc 123",\n"title2" : "bca 321",\n"title3" : "cba 213",\n"title4" : {"title5": "title6", "title7": [ -17662.3456, 987621.7654]}\n},\n{\n"title1" : "aec 183",\n"title2" : "bga 351",\n"title3" : "cha 293",\n"title4" : {"title5": "title6", "title7": [ -1621626123.23234, 652238322.122]}\n}\n]</p></body></html>'

# 使用read_html加载(如果是真实URL,直接 read_html(url) 即可)
# 对于模拟内容,可以使用read_html(charToRaw(mock_html_content)) 或 read_html(paste0("data:text/html,", URLencode(mock_html_content)))
# 更直接的方式是利用rvest的html_parse功能
page_content <- read_html(mock_html_content)

# 2. 提取原始JSON字符串
json_string <- html_text(page_content)

# 3. 解析JSON字符串
parsed_data <- parse_json(json_string, simplifyDataFrame = TRUE)

# 4. 提取并整理特定嵌套数据
# 访问title4下的title7列表
title7_list <- parsed_data$title4$title7

# 将列表中的向量绑定为矩阵
final_matrix <- do.call(rbind, title7_list)

# 转换为数据框,并添加id和有意义的列名
final_df <- as.data.frame(final_matrix) %>%
  rename(title7_1 = V1, title7_2 = V2) %>%
  mutate(id = row_number()) %>%
  select(id, title7_1, title7_2) # 调整列顺序

# 打印最终结果
print(final_df)

# 期望输出:
#   id      title7_1    title7_2
# 1  1 -1.766235e+04    987621.8
# 2  2 -1.621626e+09 652238322.1
登录后复制

注意事项与总结

  • 数据源的识别:在开始爬取之前,最好通过浏览器的开发者工具(F12)查看页面的“网络”或“源代码”选项卡,确认目标数据是以纯JSON形式存在还是作为HTML元素的一部分。如果直接返回的是application/json类型的响应,jsonlite::fromJSON(url)可能更直接。但如果JSON被包裹在HTML标签内,则本文的方法是正确的选择。
  • 错误处理:在实际的网络爬虫中,需要考虑网络连接失败、页面结构变化、JSON格式错误等情况。可以加入tryCatch语句来增强代码的健壮性。
  • simplifyDataFrame的局限性:simplifyDataFrame = TRUE在许多情况下非常方便,但对于过于复杂或不规则的JSON结构,它可能无法完全扁平化所有数据。此时,你可能需要手动遍历列表,逐步提取和整理数据。
  • 数据清洗:提取到的数据可能仍需进一步清洗和转换,例如日期格式转换、缺失值处理等。
  • 效率考量:对于大规模数据,考虑使用data.table包进行高效的数据操作,或者优化JSON解析逻辑以提高性能。

通过结合rvest和jsonlite这两个强大的R包,我们可以有效地应对HTML页面中内嵌JSON数据的抓取和解析挑战,将非结构化或半结构化的网页数据转化为R中可分析的结构化数据。理解数据在HTML中是如何呈现的,是选择正确工具和方法的基础。

以上就是R语言中从HTML页面提取并解析内嵌JSON数据的详细内容,更多请关注php中文网其它相关文章!

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号