【问题标题】:R Disparity between browser and GET / getURLR浏览器和GET / getURL之间的差异
【发布时间】:2014-08-07 02:21:49
【问题描述】:

我正在尝试从页面下载内容,但我发现响应数据格式不正确或不完整,好像 GET 或 getURL 在加载这些数据之前正在拉取。

library(httr)
library(RCurl)
url <- "https://www.vanguardcanada.ca/individual/etfs/etfs.htm"
d1 <- GET(url) # This shows a lot of {{ moustache style }} code that's not filled
d2 <- getURL(url) # This shows "" as if it didn't get anything

我不确定如何继续。我的目标是获取与浏览器中显示的链接相关的数字:

https://www.vanguardcanada.ca/individual/etfs/etfs-detail-overview.htm?portId=9548

所以在这种情况下,我想下载并抓取“9548”。

不确定为什么 getURL 和 GET 得到的结果似乎与浏览器中显示的结果大不相同。似乎数据加载缓慢,几乎就像 GET 和 getURL 在完全加载之前拉取一样。

例如看:

x <- "https://www.vanguardcanada.ca/individual/etfs/etfs-detail-prices.htm?portId=9548"
readHTMLTable(htmlParse(GET(x)))

【问题讨论】:

    标签: r curl rcurl httr


    【解决方案1】:

    重要的是要了解,当您抓取网页时,您将获得该网页的原始 HTML 源代码;这不一定是您将在 Web 浏览器中与之交互的内容。当您调用GET(url) 时,您将获得实际的html/text,这是该页面的来源。这是直接从服务器发送的内容。现在大多数网页还假设浏览器不仅会显示 HMTL,还会在该页面上执行 javascript 代码。当大量页内内容稍后由 javascript 生成时尤其如此。这正是这个页面中发生的事情。在该页面的 html 源代码中找不到页面上的“内容”;稍后通过 javascript 下载。

    httrRCurl 都不会执行用您实际查看的表格“填充”页面所需的 javascript。有一个名为 RSelenium 的包能够与浏览器交互以执行 javascript,但在这种情况下,我们实际上可以绕过它。

    首先,请说明为什么getURL 不起作用。看起来这个网络服务器嗅探请求程序发送的用户代理以发送不同的内容。无论 RCurl 使用的默认用户代理是什么,都不足以从服务器获取 html。您可以通过指定不同的用户代理来解决此问题。例如

    d2 <- getURL(url, .opts=list(useragent="Mozila 5.0"))
    

    似乎有效。

    但是回到主要问题。在处理此类问题时,我强烈建议您使用 Chrome 开发人员工具(或您喜欢的浏览器中的任何等效工具)。在 Chrome 开发者工具中,特别是在网络选项卡上,您可以看到 Chrome 为获取数据而发出的所有请求

    如果您单击第一个(“etfs.html”),您可以看到该请求的标题和响应。在响应子选项卡上,您应该看到与GETgetURL 找到的完全相同的内容。然后我们下载一堆 CSS 和 javascript 文件。看起来最有趣的文件是“GetETFJson.js”。这实际上似乎以 几乎 JSON 格式保存大部分数据。它实际上在 JSON 块前面有一些真正的 javascript,这会妨碍它。但是我们可以用

    下载那个文件
    d3 <- GET("https://www.vanguardcanada.ca/individual/mvc/GetETFJson.js")
    

    并将内容提取为文本

    p3 <- content(d3, as="text")
    

    然后用

    把它变成一个R对象
    library(jsonlite)
    r3 <- fromJSON(substr(p3,13,nchar(p3)))
    

    再次,我们使用上面的substr 去除开头的非 JSON 内容,以便于解析。

    现在,您可以探索返回的对象。但是看起来您想要的数据存储在以下向量中

    cbind(r3$fundData$Fund$profile$portId, r3$fundData$Fund$profile$benchMark)
    
          [,1]   [,2]                                                                            
     [1,] "9548" "FTSE All World ex Canada Index in CAD"                                         
     [2,] "9561" "FTSE Canada All Cap Index in CAD"                                              
     [3,] "9554" "Spliced Canada Index"                                                          
     [4,] "9559" "FTSE Canada All Cap Real Estate Capped 25% Index"                              
     [5,] "9560" "FTSE Canada High Dividend Yield Index"                                         
     [6,] "9550" "FTSE Developed Asia Pacific Index in CAD"                                      
     [7,] "9549" "FTSE Developed Europe Index in CAD"                                            
     [8,] "9558" "FTSE Developed ex North America Index in CAD"                                  
     [9,] "9555" "Spliced FTSE Developed ex North America Index Hedged in CAD"                   
    [10,] "9556" "Spliced Emerging Markets Index in CAD"                                         
    [11,] "9563" "S&P 500 Index in CAD"                                                          
    [12,] "9562" "S&P 500 Index in CAD Hedged"                                                   
    [13,] "9566" "NASDAQ US Dividend Achievers Select Index in CAD"                              
    [14,] "9564" "NASDAQ US Dividend Achievers Select Index Hedged in CAD"                       
    [15,] "9557" "CRSP US Total Market Index in CAD"                                             
    [16,] "9551" "Spliced US Total Market Index Hedged in CAD"                                   
    [17,] "9552" "Barclays Global Aggregate CAD Float Adjusted Index in CAD"                     
    [18,] "9553" "Barclays Global Aggregate CAD 1-5 Year Govt/Credit Float Adj Ix in CAD"        
    [19,] "9565" "Barclays Global Aggregate Canadian 1-5 Year Credit Float Adjusted Index in CAD"
    [20,] "9568" "Barclays Global Aggregate ex-USD Float Adjusted RIC Capped Index Hedged in CAD"
    [21,] "9567" "Barclays U.S. Aggregate Float Adjusted Index Hedged in CAD"  
    

    因此希望这足以提取您需要的数据,以使用更多数据识别 URL 的路径。

    【讨论】:

    • 这是一个很棒的答案。我已经为其他几个站点重新创建了您的方法,使用 chrome (F12) 查看请求可以更轻松地查看正在发生的事情。谢谢!
    • 很高兴您发现此策略很有用。
    • @MrFlick 我在 PHP 中遇到了类似的问题。我尝试了不同的用户代理,但它不起作用。如何选择有效的用户代理和推荐人?另外,您是否有任何建议或库可能会有所帮助。
    猜你喜欢
    • 2011-11-28
    • 1970-01-01
    • 2012-11-01
    • 2018-07-16
    • 2012-05-09
    • 2011-04-21
    • 2022-01-16
    • 1970-01-01
    相关资源
    最近更新 更多