【问题标题】:How to scrape data from a web site?如何从网站上抓取数据?
【发布时间】:2014-03-20 00:32:19
【问题描述】:

我正在使用以下代码从网站 (http://q.stock.sohu.com/cn/000002/lshq.shtml) 获取信息。但我不知道如何获取包含“日期、打开、关闭、高、低”的数据框。任何帮助将不胜感激。

thepage = readLines('http://q.stock.sohu.com/hisHq?code=cn_000002&start=20131120&end=20140318&stat=1&order=D&period=d&callback=historySearchHandler&rt=jsonp&r=0.8740235545448934&0.28161772061461654')

如何获取数据框?

【问题讨论】:

    标签: r web-scraping dataframe


    【解决方案1】:

    我不知道返回 JSON 的哪些部分是您需要的实际值,但我假设它们是 hq 记录的组成部分。这应该有效:

    library(RJSONIO)
    library(RCurl)
    
    # get the raw data
    dat.json.raw <- getURL("http://q.stock.sohu.com/hisHq?code=cn_000002&start=20131120&end=20140318&stat=1&order=D&period=d&callback=historySearchHandler&rt=jsonp&r=0.8740235545448934&0.28161772061461654%27")
    tt <- textConnection(dat.json.raw)
    dat.json <- readLines(tt)
    close(tt)
    
    # remove callback
    dat.json <- gsub("^historySearchHandler\\(", "", dat.json)
    dat.json <- gsub("\\)$", "", dat.json)
    
    # convert to R structure
    dat.l <- fromJSON(dat.json)
    
    # get the meaty part of the data into a data.frame
    dat <- data.frame(t(sapply(dat.l[[1]]$hq, unlist)), stringsAsFactors=FALSE)
    dat$X1 <- as.Date(dat$X1)
    dat$X2 <- as.numeric(dat$X2)
    dat$X3 <- as.numeric(dat$X3)
    dat$X4 <- as.numeric(dat$X4)
    
    str(dat)
    ## 'data.frame':    79 obs. of  10 variables:
    ##  $ X1 : Date, format: "2014-03-18" "2014-03-17" "2014-03-14" ...
    ##  $ X2 : num  7.76 7.6 7.68 7.58 7.48 7.19 7.22 7.34 6.76 6.92 ...
    ##  $ X3 : num  7.6 7.76 7.53 7.71 7.6 7.5 7.15 7.27 7.32 6.76 ...
    ##  $ X4 : num  -0.16 0.23 -0.18 0.11 0.1 0.35 -0.12 -0.05 0.56 -0.16 ...
    ##  $ X5 : chr  "-2.06%" "3.05%" "-2.33%" "1.45%" ...
    ##  $ X6 : chr  "7.55" "7.59" "7.50" "7.53" ...
    ##  $ X7 : chr  "7.76" "7.80" "7.81" "7.85" ...
    ##  $ X8 : chr  "843900" "1177079" "1303110" "1492359" ...
    ##  $ X9 : chr  "64268.06" "90829.30" "99621.34" "114990.40" ...
    ##  $ X10: chr  "0.87%" "1.22%" "1.35%" "1.54%" ...
    
    head(dat)
    ##           X1   X2   X3    X4     X5   X6   X7      X8        X9   X10
    ## 1 2014-03-18 7.76 7.60 -0.16 -2.06% 7.55 7.76  843900  64268.06 0.87%
    ## 2 2014-03-17 7.60 7.76  0.23  3.05% 7.59 7.80 1177079  90829.30 1.22%
    ## 3 2014-03-14 7.68 7.53 -0.18 -2.33% 7.50 7.81 1303110  99621.34 1.35%
    ## 4 2014-03-13 7.58 7.71  0.11  1.45% 7.53 7.85 1492359 114990.40 1.54%
    ## 5 2014-03-12 7.48 7.60  0.10  1.33% 7.42 7.85 2089873 160315.88 2.16%
    ## 6 2014-03-11 7.19 7.50  0.35  4.90% 7.15 7.59 1892488 141250.94 1.96%
    

    您需要修复一些其他列(因为我不知道您确切需要什么)。

    对于不喜欢从fromJSON 调用返回的警告的人,您可以将readLines 包装为pastedat.json &lt;- paste(readLines(tt), collapse="")。没有必要(警告是无害的),所以我通常不会为额外的步骤而烦恼。

    【讨论】:

    • 希望回调函数名称不会改变。如果是这样,您可以调整第一个 gsub()(我想如果需要,它也可以变得更通用)。从 JSON 中获取内容通常具有挑战性,这种特殊模式在大多数情况下对我来说效果很好(需要调整)。
    【解决方案2】:

    似乎您正在尝试抓取一个在 JSON 中显示数据的网站。

    为此,除了抓取网站所需执行的“常规步骤”之外,您还需要处理解析和操作 JSON 数据:

    通常的做法

    如果你有一个易于抓取的 HTML 表格,这应该可以:

    require("XML")
    x <- readHTMLTable(
        doc="swww.someurl.com"
    )
    

    否则你肯定需要使用一些XPath 来访问你感兴趣的节点。

    这通常涉及通过htmlTreeParse() 解析HTML 代码并通过getNodeSet() 等获取相应的节点:

    x <- htmlTreeParse(
        file="swww.someurl.com",
        isURL=TRUE,
        useInternalNodes=TRUE
    )
    
    res <- getNodeSet(x, <your-xpath-statement>)
    

    包含 JSON 数据的方法

    解析 HTML 代码:

    x <- htmlTreeParse(
        file="http://q.stock.sohu.com/hisHq?code=cn_000002&start=20131120&end=20140318&stat=1&order=D&period=d&callback=historySearchHandler&rt=jsonp&r=0.8740235545448934&0.28161772061461654",
        isURL=TRUE,
        useInternalNodes=TRUE
    )
    

    检索实际的 JSON 数据:

    json <- getNodeSet(x, "//body/p")
    json <- xmlValue(json[[1]])
    

    摆脱非 JSON 组件:

    json <- gsub("historySearchHandler\\(", "", json, perl=TRUE)
    json <- gsub("\\)$", "", json, perl=TRUE)
    

    解析 JSON 数据:

    require("jsonlite")
    fromJSON(json, simplifyVector=FALSE)
    
    [[1]]
    [[1]]$status
    [1] 0
    
    [[1]]$hq
    [[1]]$hq[[1]]
    [[1]]$hq[[1]][[1]]
    [1] "2014-03-18"
    
    [[1]]$hq[[1]][[2]]
    [1] "7.76"
    
    [...]
    

    现在你需要把它变成一个更像data.frame的顺序(想到的方法是do.call()rbind()cbind)。

    编码

    迟早(而不是我们在这个例子中看到的迟早),你会遇到编码问题("ÀÛ¼Æ:" 之类的东西)。

    您可以在解析 HTML 代码时直接使用不同的编码(htmlTreeParse() 中的参数encoding)或通过Encoding“之后”修改字符串的编码。不过,我无法根据您的价值观完全正确。编码问题可能会很痛苦。

    一般建议

    我建议您将来选择基于英语的示例(在这种情况下是基于英语的网站),否则您会极大地限制可能能够帮助您的人数。

    【讨论】:

    • 您的所有建议都非常感谢。我没有资助一个适当的基于英语的例子。就像我得到“thepage”的数据一样。如何将数据转换为仅包括:2014-03-18,"2014-03-18","7.76","7.60","-0.16","-2.06%","7.55" 的数据框,"7.76","843900","64268.06","0.87%"
    • 好吧,按照我概述的工作流程。如果您尝试直接在readLines() 返回的thepage 上工作(这是纯文本,而不是解析的对象),您将不会走得太远和/或需要使用大量的正则表达式。您想要的是使用 parsed HTML 代码,因为它允许您在节点树中轻松导航。如果你想爬网,你需要学习一些 XPath 和/或 JSON,对不起。
    • 页面
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 2013-05-21
    • 1970-01-01
    • 2021-07-14
    相关资源
    最近更新 更多