使用VBA刮掉AJAX页面

问题描述:

我一直在尝试刮掉整个整个 HTML主体并将其分配为字符串变量,然后再处理该字符串以填充excel文件 - 这将在一个循环中完成以更新日期每隔5分钟一次。使用VBA刮掉AJAX页面

这些页面是AJAX页面,所以运行看起来像JavaScript的东西(尽管我并不熟悉JS)。

我使用XMLHttpRequest对象(下面的代码)尝试,但牛逼返回JS调用:

Set XMLHTTP = CreateObject("MSXML2.serverXMLHTTP") 
XMLHTTP.Open "GET", "https://www.google.co.uk/finance?ei=bQ_iWLnjOoS_UeWcqsgE", False 
XMLHTTP.setRequestHeader "Content-Type", "text/xml" 
XMLHTTP.send 
Debug.Print XMLHTTP.ResponseText 

我试图创建一个与下面的代码,但同样的IE对象,同样的问题:

Set IE = CreateObject("InternetExplorer.Application") 
IE.Visible = False 
IE.navigate "https://www.google.co.uk/finance?ei=bQ_iWLnjOoS_UeWcqsgE" 
While IE.Busy Or IE.ReadyState <> 4: DoEvents: Wend 
Set HTMLdoc = IE.Document 
Debug.Print = HTMLdoc.Body.innerHTML 

我想什么它提供给我时,我打F12和到了检查标签准确的文本(即低于黄色区域内的文本的全部。) - 如果我能得到这个(全扩展的)我可以从那里工作。任何帮助将大规模赞赏。

enter image description here

在上面的例子中(谷歌财经),该指数价格异步更新 - 我想在在我指定的字符串时捕捉到这些。

+0

请问您可以添加到您的问题的预期产出?目前尚不清楚开发人员工具中提供的文字是什么。 – omegastripes

+0

@omegastripes我已经包括了最后一句 - 如果我正在寻找CAC 40(法国证券交易所)价值,我目前无法提取它,因为它不包含在'Debug.print'中。 – Jeremy

您刚才检查XHR时的网页呢,查找包含相关数据的人,做出同样XHR(无论是网站提供API或没有)和解析响应的任何动态加载的数据,或者在IE自动化的情况下,你添加额外的等待循环,直到目标元素变为可访问,然后从DOM中检索它。

在这种情况下,您可以通过Google Finance API获取数据。

方法1.

为了让你必须知道股票代码,这可能会网页的HTML内容或电子邮件中轻松找到所求。 G。如果您点击CAC 40,在打开的页面中会出现CAC 40(INDEXEURO:PX1)的标题。

有一些页面上的以下股票和股票交换符号在世界市场表:

Shanghai   SHA:000001 
S&P 500    INDEXSP:.INX 
Nikkei 225   INDEXNIKKEI:NI225 
Hang Seng Index  INDEXHANGSENG:HSI 
TSEC    TPE:TAIEX 
EURO STOXX 50  INDEXSTOXX:SX5E 
CAC 40    INDEXEURO:PX1 
S&P TSX    INDEXTSI:OSPTX 
S&P/ASX 200   INDEXASX:XJO 
BSE Sensex   INDEXBOM:SENSEX 
SMI     INDEXSWX:SMI 
ATX     INDEXVIE:ATX 
IBOVESPA   INDEXBVMF:IBOV 
SET     INDEXBKK:SET 
BIST100    INDEXIST:XU100 
IBEX    INDEXBME:IB 
WIG     WSE:WIG 
TASI    TADAWUL:TASI 
MERVAL    BCBA:IAR 
IPC     INDEXBMV:ME 
IDX Composite  IDX:COMPOSITE 

将它放到网址:

http://finance.google.com/finance/info?q=SHA:000001,INDEXSP:.INX,INDEXNIKKEI:NI225,INDEXHANGSENG:HSI,TPE:TAIEX,INDEXSTOXX:SX5E,INDEXEURO:PX1,INDEXTSI:OSPTX,INDEXASX:XJO,INDEXBOM:SENSEX,INDEXSWX:SMI,INDEXVIE:ATX,INDEXBVMF:IBOV,INDEXBKK:SET,INDEXIST:XU100,INDEXBME:IB,WSE:WIG,TADAWUL:TASI,BCBA:IAR,INDEXBMV:ME,IDX:COMPOSITE

响应包含JSON数据,如此:

[ 
    { 
     "id": "7521596", 
     "t": "000001", 
     "e": "SHA", 
     "l": "3,222.51", 
     "l_fix": "3222.51", 
     "l_cur": "CN¥3,222.51", 
     "s": "0", 
     "ltt": "3:01PM GMT+8", 
     "lt": "Mar 31, 3:01PM GMT+8", 
     "lt_dts": "2017-03-31T15:01:15Z", 
     "c": "+12.28", 
     "c_fix": "12.28", 
     "cp": "0.38", 
     "cp_fix": "0.38", 
     "ccol": "chg", 
     "pcls_fix": "3210.2368" 
    }, 
    ... 
] 

您可以使用下面的VBA代码来解析响应和输出结果。它需要将JSON.bas模块导入到VBA项目以进行JSON处理。

Sub GoogleFinanceData() 

    Dim sJSONString As String 
    Dim vJSON As Variant 
    Dim sState As String 
    Dim aData() 
    Dim aHeader() 

    ' Retrieve Google Finance data 
    With CreateObject("MSXML2.XMLHTTP") 
     .Open "GET", "http://finance.google.com/finance/info?q=SHA:000001,INDEXSP:.INX,INDEXNIKKEI:NI225,INDEXHANGSENG:HSI,TPE:TAIEX,INDEXSTOXX:SX5E,INDEXEURO:PX1,INDEXTSI:OSPTX,INDEXASX:XJO,INDEXBOM:SENSEX,INDEXSWX:SMI,INDEXVIE:ATX,INDEXBVMF:IBOV,INDEXBKK:SET,INDEXIST:XU100,INDEXBME:IB,WSE:WIG,TADAWUL:TASI,BCBA:IAR,INDEXBMV:ME,IDX:COMPOSITE", False 
     .Send 
     If .Status <> 200 Then Exit Sub 
     sJSONString = .responseText 
    End With 
    ' Trim extraneous chars 
    sJSONString = Mid(sJSONString, InStr(sJSONString, "[")) 
    ' Parse JSON string 
    JSON.Parse sJSONString, vJSON, sState 
    If sState = "Error" Then Exit Sub 
    ' Convert to table format 
    JSON.ToArray vJSON, aData, aHeader 
    ' Results output 
    With Sheets(1) 
     .Cells.Delete 
     .Cells.WrapText = False 
     If UBound(aHeader) >= 0 Then OutputArray .Cells(1, 1), aHeader 
     Output2DArray .Cells(2, 1), aData 
     .Columns.AutoFit 
    End With 

End Sub 

Sub OutputArray(oDstRng As Range, aCells As Variant) 

    With oDstRng 
     .Parent.Select 
     With .Resize(1, UBound(aCells) - LBound(aCells) + 1) 
      .NumberFormat = "@" 
      .Value = aCells 
     End With 
    End With 

End Sub 

Sub Output2DArray(oDstRng As Range, aCells As Variant) 

    With oDstRng 
     .Parent.Select 
     With .Resize(_ 
       UBound(aCells, 1) - LBound(aCells, 1) + 1, _ 
       UBound(aCells, 2) - LBound(aCells, 2) + 1) 
      .NumberFormat = "@" 
      .Value = aCells 
     End With 
    End With 

End Sub 

正如你所需要的数据位于l_fixc_fixcp_fix列的结果。方法2。

您也可以由URL使XHR这样一个用于CAC 40:

https://www.google.co.uk/finance/getprices?q=PX1&x=INDEXEURO&i=120&p=20m&f=d,c,v,o,h,l

特别是URL是PX1股票和INDEXEURO证券交易所的符号,120秒的时间间隔在20分钟期间,响应数据d,c,v,o,h,l用于DATE(UNIX TimeStamp),CLOSE,VOLUME,OPEN,HIGH,LOW。

响应格式如下:

EXCHANGE%3DINDEXEURO 
MARKET_OPEN_MINUTE=540 
MARKET_CLOSE_MINUTE=1050 
INTERVAL=120 
COLUMNS=DATE,CLOSE,HIGH,LOW,OPEN,VOLUME 
DATA= 
TIMEZONE_OFFSET=120 
a1491405000,5098.75,5099.92,5098.75,5099.92,0 
1,5100.51,5100.51,5098.09,5098.09,0 
2,5099.63,5101.2,5099.29,5100.68,0 
3,5099.83,5100.04,5099.07,5099.28,0 
4,5098.19,5098.9,5097.71,5098.9,0 
5,5098.56,5099.24,5097.99,5099.24,0 
6,5097.34,5098.2,5096.14,5098.2,0 
7,5096.52,5097.38,5095.66,5097.38,0 
8,5093.27,5095.39,5093.27,5095.39,0 
9,5094.43,5094.43,5092.07,5093.17,0 
10,5088.18,5092.72,5087.68,5092.72,0 

的XHR应列表中的每个股票代码来完成,那么结果应该并入表。

+0

感谢这个。我拥有的问题是,虽然Google有一个API,但这只是一个例子,大多数网页都没有API,所以这不是我能为他们做的事情。有没有其他方法可以解决这个问题? – Jeremy

+0

@Jeremy可以请你提供另一个你需要刮取的网站URL,以及哪个不提供API,举个例子?我会试着说出一些一般的指导方针。 – omegastripes

+0

我已经得到了我的头,围绕CSS querySelectorAll,并且循环遍历Parentelements中的元素(我不知道这可以按照您对'范围内每个'loop范围的相同方式完成),所以问题得以解决 - 您尝试提供帮助的最佳答案!谢谢 :) – Jeremy