Eri*_*eno 5 xml xpath r web-scraping
我有一个像这样的html和R代码,需要将每个节点值与data.frame中的父id相关联.每个人都可以获得一些不同的信息.
example <- "<div class='person' id='1'>
<div class='phone'>555-5555</div>
<div class='email'>jhon@123.com</div>
</div>
<div class='person' id='2'>
<div class='phone'>123-4567</div>
<div class='email'>maria@gmail.com</div>
</div>
<div class='person' id='3'>
<div class='phone'>987-6543</div>
<div class='age'>32</div>
<div class='city'>New York</div>
</div>"
doc = htmlTreeParse(example, useInternalNodes = T)
values <- xpathSApply(doc, "//*[@class='person']/div", xmlValue)
variables <- xpathSApply(doc, "//*[@class='person']/div", xmlGetAttr, 'class')
id <- xpathSApply(doc, "//*[@class='person']", xmlGetAttr, 'id')
# The problem: create a data.frame(id,variables,values)
Run Code Online (Sandbox Code Playgroud)
有了xpathSApply(),我也可以获得电话,电子邮件和年龄值以及人物属性(id).但是,这些信息是孤立的,我需要将它们引用到正确的data.frame变量和正确的人.在我的实际数据中有很多不同的信息,因此命名每个变量的过程必须是自动的.
我的目标是创建一个像这样的data.frame,将每个id与其正确的数据相关联.
id variables values
1 1 phone 555-5555
2 1 email jhon@123.com
3 2 phone 123-4567
4 2 email maria@gmail.com
5 3 phone 987-6543
6 3 age 32
7 3 city New York
Run Code Online (Sandbox Code Playgroud)
我相信我必须创建一个内部使用的功能xpathSApply,它将同时获得个人电话和人员ID,因此它们会相关,但到目前为止我还没有取得任何成功.
谁能帮我?
一般来说,这并不容易:
idNodes <- getNodeSet(doc, "//div[@id]")
ids <- lapply(idNodes, function(x) xmlAttrs(x)['id'])
values <- lapply(idNodes, xpathApply, path = './div[@class]', xmlValue)
attributes <- lapply(idNodes, xpathApply, path = './div[@class]', xmlAttrs)
do.call(rbind.data.frame, mapply(cbind, ids, values, attributes))
V1 V2 V3
1 1 555-5555 phone
2 1 jhon@123.com email
3 2 123-4567 phone
4 2 maria@gmail.com email
5 3 987-6543 phone
6 3 32 age
7 3 New York city
Run Code Online (Sandbox Code Playgroud)
上面将给出属性和值对,假设它们嵌套在一个div带有关联的对象中id.
更新:如果要将其包装在xpathApply类型的调用中
utilFun <- function(x){
id <- xmlGetAttr(x, 'id')
values <- sapply(xmlChildren(x, omitNodeTypes = "XMLInternalTextNode"), xmlValue)
attributes <- sapply(xmlChildren(x, omitNodeTypes = "XMLInternalTextNode"), xmlAttrs)
data.frame(id = id, attributes = attributes, values = values, stringsAsFactors = FALSE)
}
res <- xpathApply(doc, '//div[@id]', utilFun)
do.call(rbind, res)
id attributes values
1 1 phone 555-5555
2 1 email jhon@123.com
3 2 phone 123-4567
4 2 email maria@gmail.com
5 3 phone 987-6543
6 3 age 32
7 3 city New York
Run Code Online (Sandbox Code Playgroud)