【问题标题】:Unable to select a specific html table using xpathSapply in R无法在 R 中使用 xpathSapply 选择特定的 html 表
【发布时间】:2016-08-17 21:04:18
【问题描述】:

我正在尝试从以下链接http://cepea.esalq.usp.br/frango/?page=379&Dias=15 中抓取第二张表

我已经使用 XML 包尝试了以下 R 代码:

    p_frango_resfriado <- htmlTreeParse("http://cepea.esalq.usp.br/frango/?page=379&Dias=15", 
    useInternalNodes = TRUE, 
    encoding = "UTF-8")

    xpathSApply(p_frango_resfriado, "//table[@width = '95%']//tr//td[2]", xmlValue)
    xpathSApply(p_frango_resfriado, "//table[@width = '95%']//tr//td[3]", xmlValue)
    xpathSApply(p_frango_resfriado, "//table[@width = '95%']//tr//td[4]", xmlValue)

问题是这段代码抓取了网页中的两个html表,我只想抓取第二个。我试过了,下面的代码没有返回任何有趣的东西:

xpathSApply(p_frango_resfriado, 
"//a[text() = 'Preços do frango resfriado CEPEA/ESALQ - Estado SP']/table[@width = '95%']", 
xmlValue)

谁能帮我解决这个问题?我不太擅长 XPath 语言和 html。

【问题讨论】:

    标签: html r xpath web-scraping scrape


    【解决方案1】:

    在 XPath 查询中使用 XML::xmlToDataFrame

    library("httr")
    library("XML")
    URL <- "http://cepea.esalq.usp.br/frango/?page=379&Dias=15"
    temp <- tempfile(fileext = ".html")
    GET(url = URL, user_agent("Mozilla/5.0"), write_disk(temp))
    

    这两个表的唯一区别是在 xpath 查询中使用的表名

    表 1:Preços do frango congelado CEPEA/ESALQ - Estado SP

    xpexpr <- "//center/a[contains(., 'do frango congelado')]/../table/tr/td/font/tr"
    

    表 2:Preços do frango resfriado CEPEA/ESALQ - Estado SP

    xpexpr <- "//center/a[contains(., 'do frango resfriado')]/../table/tr/td/font/tr"
    
    doc <- htmlParse(temp)
    listofTableNodes <- getNodeSet(doc, xpexpr)
    length_nodes <- length(listofTableNodes)
    include_indices1 <- 1:(length_nodes - 2)
    
    # create dataframe using xmlvalues of the nodelist. Both `getNodeSet()` 
    # and `xpathSApply` will provide identical results.
    # using `getNodeSet()`
    df <- xmlToDataFrame(listofTableNodes[include_indices1], stringsAsFactors=FALSE)
    # using `xpathSApply`
    df <- xmlToDataFrame(xpathSApply(doc, xpexpr)[include_indices1], stringsAsFactors=FALSE)
    
    # clean data
    df$td <- as.Date(gsub("[Â ]\\s*", "", df$td), format = "%d/%m/%Y")
    df[, 4] <- gsub("\t$", '', df[, 4])
    
    # add column names
    xpexpr <- "//center/a[contains(., 'do frango resfriado')]/../table/tr/td/font/text()"
    # for Table-1
    # xpexpr <- "//center/a[contains(., 'do frango congelado')]/../table/tr/td/font/text()"
    listofTableNodes <- getNodeSet(doc, xpexpr)
    colnames(df) <- c('Date', sapply(listofTableNodes, xmlValue))
    df
    #            Date Valor R$ Var./dia Var./mês
    #   1  2016-08-17     4,37    0,46%     8,17%
    #   2  2016-08-16     4,35    0,46%     7,67%
    #   3  2016-08-15     4,33    0,46%     7,18%
    #   4  2016-08-12     4,31    0,00%     6,68%
    #   5  2016-08-11     4,31    0,70%     6,68%
    #   6  2016-08-10     4,28    0,47%     5,94%
    #   7  2016-08-09     4,26   -0,70%     5,45%
    #   8  2016-08-08     4,29    3,87%     6,19%
    #   9  2016-08-05     4,13    0,49%     2,23%
    #   10 2016-08-04     4,11    0,00%     1,73%
    #   11 2016-08-03     4,11    1,73%     1,73%
    #   12 2016-08-02     4,04    0,00%     0,00%
    #   13 2016-08-01     4,04    0,00%     0,00%
    #   14 2016-07-29     4,04    0,00%    -0,49%
    #   15 2016-07-28     4,04   -0,25%    -0,49%
    

    注意:每天,此网页上的值都会更新,将使用length_nodes 将其考虑在内。

    在没有 XPath 查询的情况下使用 XML::readHTMLTable

    library("httr")
    library("XML")
    URL <- "http://cepea.esalq.usp.br/frango/?page=379&Dias=15"
    temp <- tempfile(fileext = ".html")
    GET(url = URL, user_agent("Mozilla/5.0"), write_disk(temp))
    df <- readHTMLTable(temp, stringAsFactors = FALSE, which = 8)
    # Table 1
    df[4:18,]
    # Table 2
    df[28:42,]
    

    在 XPath 查询中使用 XML::readHTMLTable

    library("httr")
    library("XML")
    URL <- "http://cepea.esalq.usp.br/frango/?page=379&Dias=15"
    temp <- tempfile(fileext = ".html")
    GET(url = URL, user_agent("Mozilla/5.0"), write_disk(temp))
    doc <- htmlParse(temp)
    
    # XPath Query
    # Table -1
    xpexpr <- "//center/a[contains(., 'do frango congelado')]/../table/tr/td/font"
    df <- xpathSApply(doc, xpexpr, readHTMLTable)
    include_indices <- 1:(nrow(df[[4]]) -4)
    df <- df[[4]][include_indices,]
    
    # Table-2
    xpexpr <- "//center/a[contains(., 'do frango resfriado')]/../table/tr/td/font"
    df <- xpathSApply(doc, xpexpr, readHTMLTable)
    include_indices <- 1:(nrow(df[[4]]) -4)
    df <- df[[4]][include_indices,]
    

    【讨论】:

    • 嗨,Sathish,感谢您的帮助,但如果可能的话,我想知道我需要传递的特定 XPath 表达式以获得第二个表。
    • df &lt;- readHTMLTable(temp, which=1) ,我得到: readHTMLTable(temp, which = 1) 中的错误:未使用的参数(which = 1),如果我省略 which=1 也没关系,从那以后我得到: .subset2(x, i, exact = exact) 中的错误:下标超出范围
    • 我想知道不同的版本是否有问题。我得到unused arguments (stringAsFactors = FALSE, which = 8)。我正在使用 XML 3.98-1.4,这是 CRAN 认为的当前版本。
    • @42- XML pkg 版本 packageVersion("XML"); # [1] ‘3.98.1.4’
    • 重启后错误现在是:Error in (function (classes, fdef, mtable) : unable to find an inherited method for function ‘readHTMLTable’ for signature ‘"list"’ 但是chinsoon12的方法是有效的。
    【解决方案2】:

    这现在应该可以工作,但我想知道如果你每天运行它是否会正常工作。

    options(stringsAsFactors=FALSE)
    library(XML)
    
    #get website
    tfile <- tempfile()
    download.file("http://cepea.esalq.usp.br/frango/?page=379&Dias=15", tfile)
    temp <- readHTMLTable(tfile)
    
    #read in table
    tbl <- temp[[5]][!is.na(temp[[5]]$V2) & !is.na(temp[[5]]$V4),]
    tbl2 <- split(tbl, cumsum(tbl$V1==""))[[2]][-1,]
    tbl2 
    
    #perform formatting
    colnames(tbl2) <- c("Date","Price","Pct1","Pct2")
    tbl2 <- data.frame(apply(tbl2, c(1,2), function(x) {
        x <- gsub("Â","",x)
        x <- gsub(",",".",x,fixed=TRUE)
        x <- gsub("%","",x)
    }))
    tbl2$Date <- as.Date(tbl2$Date,"  %d/%m/%Y  ")
    tbl2$Price <- as.numeric(tbl2$Price)
    tbl2$Pct1 <- as.numeric(tbl2$Pct1) / 100
    tbl2$Pct2 <- as.numeric(tbl2$Pct2) / 100
    tbl2
    
    #         Date Price    Pct1    Pct2
    #65 2016-08-17  4.37  0.0046  0.0817
    #66 2016-08-16  4.35  0.0046  0.0767
    #67 2016-08-15  4.33  0.0046  0.0718
    #68 2016-08-12  4.31  0.0000  0.0668
    #69 2016-08-11  4.31  0.0070  0.0668
    #70 2016-08-10  4.28  0.0047  0.0594
    #71 2016-08-09  4.26 -0.0070  0.0545
    #72 2016-08-08  4.29  0.0387  0.0619
    #73 2016-08-05  4.13  0.0049  0.0223
    #74 2016-08-04  4.11  0.0000  0.0173
    #75 2016-08-03  4.11  0.0173  0.0173
    #76 2016-08-02  4.04  0.0000  0.0000
    #77 2016-08-01  4.04  0.0000  0.0000
    #78 2016-07-29  4.04  0.0000 -0.0049
    #79 2016-07-28  4.04 -0.0025 -0.0049
    

    【讨论】:

    • 仍然得到与先前答案相同的错误:temp &lt;- readHTMLTable(tfile) ... tb[["tbody"]] 中的错误:下标越界
    • @42- 你能从浏览器打开 tfile 吗?
    • 哦,当然。表格按预期显示。我检查的第一件事。
    • 重启后成功了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多