r - R - 使用 tydiverse 和 xml2 将 XML 从多个 URL 解析到数据框
问题描述
这个问题可能会被标记为重复,但我无法让它发挥作用。作为记录,我已经阅读了所有其他 stackoverflow 问题并阅读了文档。
我想从 iTunes 中提取多个页面的数据评论(链接:https ://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=1/xml )并且我想以整洁和动态的方式进行方式,最好使用XML2和tydiverse。
我的最终目标是:
在列中有一个包含所有可用字段(如 ID、作者等)的数据框并填充数据。
我的奋斗从一开始就开始了。我只能运行链接并将其作为 XML 获取,但我无法为提取的 XML 代码运行简单的代码行。我显然在这里遗漏了一些东西。我也不知道如何浏览这些页面。我知道存在多少页,但我想以动态的方式拥有它。
library("tidyverse")
library("xml2")
# Data extraction ---------------------------------------------------------
df_xml <- read_xml('https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=1/xml')
teste <- xml_text(xml_find_all(df_xml, '//feed/entry/ author')) *here I try to extract the field author*
> teste
> character(0)
谢谢大家
解决方案
问题是,当您调用 时xml_find_all(df_xml, '//feed/entry/ author')
,搜索找不到您要查找的节点,因为它们都在 xml 命名空间内。
uri <- "https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=1/xml"
my_xml <- read_xml(uri)
xml_find_all(my_xml, "//feed")
#> {xml_nodeset (0)}
您可以像这样找出文档中使用了哪些命名空间:
xml_ns(my_xml)
#> d1 <-> http://www.w3.org/2005/Atom
#> im <-> http://itunes.apple.com/rss
因此,您可以指定要在 xpath 中使用的命名空间,您将获得您正在寻找的节点,如下所示:
xml_find_all(my_xml, "//d1:feed")
#> {xml_nodeset (1)}
#> [1] <feed xmlns:im="http://itunes.apple.com/rss" xmlns="http://www.w3.org/2005/Atom ...
这显然有点烦人,因为您必须在 xpath 中的所有标记前加上d1:
,并且您的文档结构使得您可以在没有名称空间的情况下进行操作,因此最好忽略它们。
我发现最简单的方法是使用read_html
而不是read_xml
,因为除其他外,它会自动去除名称空间并且更能容忍错误。但是,有一个函数,如果您愿意xml_ns_strip
,您可以在阅读后调用。read_xml
因此,您在本文档中处理命名空间的三个选项是:
- 为所有标签名称添加前缀
d1:
xml_ns_strip
之后使用read_xml
- 利用
read_html
此代码将遍历所有 xml 页面,并为您提供所有 365 评论的字符向量。你会发现虽然content
xml的每一页有100个标签,那是因为content
每个标签里面有两个entry
标签。其中一个具有评论的原始文本,另一个具有相同的内容但以 html 字符串的形式。因此,循环丢弃包含字符串的 html 以支持原始文本:
library("tidyverse")
library("xml2")
base <- "https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page="
reviews <- author <- review_date <- character()
max_pages <- 100
for(i in seq(max_pages))
{
cat("Trying", paste0(base, i, "/xml"), "\n")
my_xml <- paste0(base, i, "/xml") %>% read_xml() %>% xml_ns_strip()
next_reviews <- xml_find_all(my_xml, xpath = '//feed/entry/content') %>%
xml_text() %>%
subset(seq_along(.) %% 2 == 1)
if(length(next_reviews) == 0){
result <- tibble(review_date, author, reviews)
break
}
reviews <- c(reviews, next_reviews)
next_author <- xml_text(xml_find_all(my_xml, xpath = '//feed/entry/author/name'))
author <- c(author, next_author)
next_date <- xml_text(xml_find_all(my_xml, xpath = '//feed/entry/updated'))
review_date <- c(review_date, next_date)
}
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=1/xml
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=2/xml
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=3/xml
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=4/xml
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=5/xml
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=6/xml
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=7/xml
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=8/xml
#> Trying https://itunes.apple.com/gb/rss/customerreviews/id=1388411277/page=9/xml
现在result
将包含tibble
三个感兴趣的字段:
result
#> # A tibble: 367 x 3
#> review_date author reviews
#> <chr> <chr> <chr>
#> 1 2020-05-05T02:38:35~ **stace** "Really good and useful app. Nice to be able to g~
#> 2 2020-05-05T01:51:49~ fire-hazza~ "Not for Scotland or Wales cmon man"
#> 3 2020-05-04T23:45:59~ Adz-Coco "Unable to register due to NHS number. My number ~
#> 4 2020-05-04T23:34:50~ Matthew ba~ "Probably spent about £5 developing this applicat~
#> 5 2020-05-04T16:40:17~ Jenny19385~ "Why it is so complicated to sign up an account? ~
#> 6 2020-05-04T14:39:54~ Sienna hea~ "Thankyou NHS for this excellent app I feel a lot~
#> 7 2020-05-04T13:09:45~ Raresole "A great app that lets me book appointments and a~
#> 8 2020-05-04T12:28:56~ chanters934 "Unable to login. App doesn’t recognise the code ~
#> 9 2020-05-04T11:26:44~ Ad_T "Unfortunately my surgery must not be participati~
#> 10 2020-05-04T08:25:17~ tonyproctor "It’s a good app although would be better with a ~
#> # ... with 357 more rows
推荐阅读
- android - 自定义背景资源在android中不起作用
- ios - swift如何让UILabel对齐到左上角
- reactjs - 我无法为元标记分配动态值?
- javascript - JQuery.Ajax() 不工作不确定脚本是否正确加载
- assembly - 是否可以在基于累加器的机器/ISA 中实现流水线操作?
- azure-active-directory - 免费 Office 帐户的无效授权错误
- python - 大熊猫汇总
- time-complexity - 内循环根据外循环增加的时间复杂度
- jaeger - 当服务在不同的主机上运行时如何设置 jaeger 后端?
- php - 使用 WSL2 时 VSCode Php 调试器无法正常工作