【问题标题】:parsing html in R: problems with output data.frame making在 R 中解析 html:输出 data.frame 的问题
【发布时间】:2015-03-12 09:26:57
【问题描述】:

我正在尝试从网页中提取数据。出于这个原因,我想用 3 个变量创建一个函数: 1) 要查看的网页向量 2) 输出文件中的列名向量 3) 输出文件中每一列的 html 代码中的标记向量

parser <- function(fileUrl, itemName, itemMark)
{
    library(XML)
    total_result <- data.frame()       
    for (file in fileUrl)    {
        temp <- data.frame(1)
        itemTemp <- c()  
        doc <-htmlTreeParse(file,useInternal=TRUE)
        for (i in 1:length(itemName)){            
            itemTemp <- xpathSApply(doc,itemMark[[i]], xmlValue)
            temp <- data.frame(temp,itemTemp, check.rows=FALSE)
        }
        total_result <- rbind(total_result, temp)        
    }   
    total_result[,1]<-NULL
    names(total_result) <- itemName
    total_result

}

它确实适用于网页上出现频率相同的项目。但它不适用于其他情况。我有这样的错误

data.frame 中的错误(temp,itemTemp,check.rows = FALSE):参数 暗示不同的行数:100, 0

我确实明白,对于 data.frame 函数,我需要参数具有相同的行数,但我不知道如何使我的解析器工作。 你能帮帮我吗?

重现错误:

url <- c("http://www.ebay.com/sch/Cell-Phones-Smartphones-/9355/i.html?LH_BIN=1&_from=R40&LH_ItemCondition=1000&_nkw=(iphone,%20htc,%20samsung,%20lg,%20nokia,%20sony)&_dcat=9355&rt=nc&_pppn=r1&Carrier=Unlocked|!","http://www.ebay.com/sch/Cell-Phones-Smartphones-/9355/i.html?LH_BIN=1&_from=R40&LH_ItemCondition=1000&_dcat=9355&Carrier=Unlocked%7C%21&_nkw=%28iphone%2C+htc%2C+samsung%2C+lg%2C+nokia%2C+sony%29&_pgn=2&_skc=50&rt=nc")
marks <- c("//span[@class='cbx']","//span[@class='cnt']")
names < c("1a","2a")
parser(url,names,marks)

【问题讨论】:

  • 你能让问题重现吗?
  • 我添加了重现错误的代码

标签: r parsing


【解决方案1】:

您正试图在此步骤中将两个长度不等的向量合并到一个数据框中:

temp <- data.frame(temp,itemTemp, check.rows=FALSE)

您似乎正在尝试抓取 ebay 页面左侧的过滤器。这样做,你会错过很多。其中有一个(查看全部)链接。实际上只显示了一个子集。我认为您还有更多工作要弄清楚如何做到这一点...

无论如何,“免费送货”“免费店内取货”“接受退货”“已完成商品”“已售商品”旁边都没有编号。这就是向量不同的原因

library(rvest)
url <- c("http://www.ebay.com/sch/Cell-Phones-Smartphones-/9355/i.html?LH_BIN=1&_from=R40&LH_ItemCondition=1000&_nkw=(iphone,%20htc,%20samsung,%20lg,%20nokia,%20sony)&_dcat=9355&rt=nc&_pppn=r1&Carrier=Unlocked|!","http://www.ebay.com/sch/Cell-Phones-Smartphones-/9355/i.html?LH_BIN=1&_from=R40&LH_ItemCondition=1000&_dcat=9355&Carrier=Unlocked%7C%21&_nkw=%28iphone%2C+htc%2C+samsung%2C+lg%2C+nokia%2C+sony%29&_pgn=2&_skc=50&rt=nc")
url[1] %>% html() %>% html_nodes(xpath="//span[@class='cbx']") %>% html_text()
url[1] %>% html() %>% html_nodes(xpath="//span[@class='cnt']") %>% html_text()

编辑添加:我认为这应该为你做。这有点hacky,但可以完成工作。这里的想法是将 .pad-bottom 元素下载到向量中。这些包含一堆空白,还包含您要查找的文本和数字。到达那里需要一些字符串 grepping、拆分等,但这样做可以确保您拥有匹配的数据。显然,单独下载元素并希望它们稍后匹配是行不通的。

library(rvest)
library(stringr)
a <- url[1] %>% html() %>% html_nodes(".pad-bottom") %>% html_text()
# remove some whitespace
a <- gsub("[\r|\t]", "", a)
# nodes seem to be separated by three new lines. 
a <- unlist(strsplit(a, "\n\n\n"))
# now get rid of the rest of the new lines
a <- gsub("\n", "", a)
# get rid of the elements that are empty
a <- a[a!=""]
# get rid of the elements that don't have a "("... these don't have numbers next to them.
a <- a[grepl("\\(", a)]
# put it all together into a dataframe.
df <- data.frame(name=substring(a, 1, regexpr("\\(", a)-1),
                 count=gsub("\\(|,", "", str_extract(a, "\\(([0-9]*,?[0-9]*)")))

【讨论】:

  • 是的,这只是一个例子。所以我有两个不等长的向量。我可以以某种方式将它们合并到 1 个子集中吗?或者我可以使用另一个函数不是一个一个地为每个标记获取 1 列向量,而是读取 html 并收集行中的所有数据并将它们合并在一起?
  • 谢谢,但很难理解它是如何工作的)你能从我原来的解析器函数中得到正确的代码吗?所以它可以与任何标记向量一起使用。再次感谢!
  • 不,我无法挽救那个烂摊子。您正在尝试下载两个单独的元素,并希望并祈祷它们的长度相同且顺序正确。 rvest 很容易理解。我建议逐步浏览代码以查看它的作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-10
  • 1970-01-01
  • 2013-05-18
  • 1970-01-01
  • 2015-06-06
  • 2013-04-01
  • 1970-01-01
相关资源
最近更新 更多