用于在线抓取数据的 VBA 程序使我的笔记本电脑性能变慢

Posted

技术标签:

【中文标题】用于在线抓取数据的 VBA 程序使我的笔记本电脑性能变慢【英文标题】:VBA program for scraping data online that makes my laptop performance getting slower 【发布时间】:2016-07-03 16:32:51 【问题描述】:

今天是我第一次创建用于从网站上抓取数据的 VBA Excel 程序。首先,我尝试使用一个简单的程序来抓取单个值并将其打印在cells(1,1) 中。虽然失败了很多次,也收到了我的杀毒软件的很多警告,但我终于成功了。然后我把程序修改成一个复杂的程序,每次修改都运行程序来检查是否发生错误。然后我意识到,每次我在修改后运行程序时,我的笔记本电脑运行速度非常慢,它的处理器风扇运行速度过快并且非常响亮。然而我的程序仍然有效。这是我的完整代码:

Sub Download_Data()
Dim IE As Object, Data_FOREX As String
T0 = Timer
Application.ScreenUpdating = False
Range("A:J").Clear

Set IE = CreateObject("internetexplorer.application")
With IE
    .navigate "http://uk.investing.com/currencies/streaming-forex-rates-majors"
    .Visible = False
End With
Do
    DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE

For i = 1 To 13
Set FOREX = IE.document.getElementById("pair_" & i)
    For j = 1 To 9
        Data_FOREX = FOREX.Cells(j).innerhtml
        If j = 1 Then
            Cells(i + 1, j + 1) = Mid(Data_FOREX, 11, 7)
        Else
            Cells(i + 1, j + 1) = Data_FOREX
        End If

        If Cells(i + 1, 8) < 0 Then
            Cells(i + 1, 8).Font.Color = vbRed
            Cells(i + 1, 9).Font.Color = vbRed
        Else
            Cells(i + 1, 8).Font.Color = vbGreen
            Cells(i + 1, 9).Font.Color = vbGreen
        End If

        If j = 9 Then
        Cells(i + 1, 10) = Mid(Data_FOREX, 4, 2) & "/" & Mid(Data_FOREX, 1, 2)
        End If
    Next j
Next i

IE.Quit
Set IE = Nothing

Cells(1, 2) = "Pair"
Cells(1, 3) = "Bid"
Cells(1, 4) = "Ask"
Cells(1, 5) = "Open"
Cells(1, 6) = "High"
Cells(1, 7) = "Low"
Cells(1, 8) = "Change"
Cells(1, 9) = "% Change"
Cells(1, 10) = "Date"
Range("A1:J").Font.Bold = True
Range("A1:J1").HorizontalAlignment = xlCenter
Range("C:H").NumberFormat = "0.0000"
Columns("A:J").AutoFit
MsgBox "Downloading data is complete." _
        & vbNewLine & "The running time is " & Round(Timer - T0, 2) & " s."
End Sub

我之前没有使用 Timer 功能,但我决定用它来知道程序运行了多长时间,因为每次修改它都会变得越来越慢。当我运行上面的程序时,它需要很长时间,所以我停止了它。当我删除了Timer功能后,仍然运行很长时间。我再次停止它,但这一次Sheet1中没有输出。即使在那之后,我的笔记本电脑运行速度非常慢,我将其关闭了两次(非常努力地尝试并花了很长时间才将其关闭)。我试图简化程序,但奇怪的是,虽然它以前可以工作,但它却没有工作。我认为问题出在我的互联网连接上,因为这里正在下雨。我尝试Speed Test 来检查我的互联网连接,但它看起来不错。我测试了五次:

Ping (ms)   Download Speed (Mbps)   Upload Speed (Mbps)
10          3.64                    0.62
10          3.24                    0.34
11          2.94                    0.53
11          3.33                    0.58
10          4.84                    0.49

那么,问题出在哪里?你能修好它吗?我还想知道如何将表格Forex Rate 中的向上/向下箭头插入A 列中的单元格?我试过Dim Arrow As Icon: Arrow = FOREX.Cells(0).innerHTML,但没有用。

【问题讨论】:

使用 sleep api 并调用 sleep 函数(甚至 250 毫秒)和 DoEvents - 如果您将 IE 文档加载到对象中并仅在内存中的对象, @dbmitch 抱歉,就像我在 OP 中所说的那样,我是这个新手。我不明白你说的。你能发布你的答案吗?谢谢 【参考方案1】:

这个答案的灵感来自我自己的帖子中的Mr. Jeeped's answer:Code that works once/ twice either by F5 or F8 but then gets multiple errors。我要感谢他为学习 VBA Excel 提供的分步指南。他的慷慨真的帮助了我。

我把它放在工作表代码模块 (Sheet1) 中。它需要工具 ► 参考中的 Microsoft HTML 对象库Microsoft XML, v6.0。该程序的输出几乎与Investing.com 上显示的显示完全相同,包括格式数字(请参阅How to make Excel doesn't truncate 0's in formatting decimal numbers? 上的相关主题)。

Sub Download_Data()
    Dim FOREX As New HTMLDocument, xmlHTTP As New MSXML2.XMLHTTP60
    Dim Website_URL As String, Data_FOREX As String, Range_Data As Range
    Dim i As Long, j As Long, Dec_Number As Long, Last_Row As Long

    Application.ScreenUpdating = False
    Range("A:J").Clear
    Website_URL = "http://uk.investing.com/currencies/streaming-forex-rates-majors"

    With xmlHTTP
        .Open "GET", Website_URL, False
        .setRequestHeader "User-Agent", "XMLHTTP/1.0"
        .send
        If .Status <> 200 Then GoTo Safe_Exit
        FOREX.body.innerHTML = .responseText
    End With

 For i = 1 To 20
    For j = 1 To 9
    With FOREX
        If Not .getElementById("pair_" & i) Is Nothing Then
            With .getElementById("pair_" & i)
                Data_FOREX = CStr(.Cells(j).innerText)
                Cells(i + 1, j + 1).Value = Data_FOREX

                'Formatting the numbers, i.e. quote prices
                If j > 1 And j < 7 Then
                    Dec_Number = Len(Data_FOREX) - InStr(Data_FOREX, ".")
                    Cells(i + 1, j + 1) = Val(Data_FOREX)

                    If Dec_Number = Len(Data_FOREX) Then
                        Cells(i + 1, j + 1).NumberFormat = "0"
                    Else
                        Cells(i + 1, j + 1).NumberFormat = "0." _
                        & WorksheetFunction.Rept("0", Dec_Number)
                    End If
                End If
            End With
        Else
            Exit For
        End If
    End With
    Next j

    'Copy number format in column G and paste it in column H
    Cells(i + 1, "G").Copy
    Cells(i + 1, "H").PasteSpecial Paste:=xlPasteFormats

    'Coloring specific data        
    If Cells(i + 1, "H") < 0 Then
        Cells(i + 1, "H").Font.Color = vbRed
        Cells(i + 1, "I").Font.Color = vbRed
    Else
        Cells(i + 1, "H").Font.Color = RGB(0, 150, 0)
        Cells(i + 1, "I").Font.Color = RGB(0, 150, 0)
    End If
    Cells(i + 1, "B").Font.Bold = True
    Cells(i + 1, "B").Font.Color = RGB(18, 86, 168)
    Range(Cells(i + 1, "H"), Cells(i + 1, "I")).Font.Bold = True
Next i

'Deleting the cells with empty entries, i.e. pair_i doesn't exist
Last_Row = Cells(Rows.Count, "B").End(xlUp).Row
Set Range_Data = Range("A2:J" & Last_Row).SpecialCells(xlCellTypeBlanks)
Range_Data.Rows.Delete Shift:=xlShiftUp

'Format table header
Cells(1, 2) = "Pair"
Cells(1, 3) = "Bid"
Cells(1, 4) = "Ask"
Cells(1, 5) = "Open"
Cells(1, 6) = "High"
Cells(1, 7) = "Low"
Cells(1, 8) = "Change"
Cells(1, 9) = "% Change"
Cells(1, 10) = "Time"
Range("A1:J1").Font.Bold = True
Range("A1:J1").HorizontalAlignment = xlCenter
Range("A:J").VerticalAlignment = xlCenter
Columns("A:J").ColumnWidth = 10

Safe_Exit:
    Set FOREX = Nothing: Set xmlHTTP = Nothing
End Sub

【讨论】:

以上是关于用于在线抓取数据的 VBA 程序使我的笔记本电脑性能变慢的主要内容,如果未能解决你的问题,请参考以下文章

如何在电脑上抓取手机浏览器的数据包

怎么用VBA或网络爬虫程序抓取网站数据

VBA - 自定义插件在笔记本电脑上完美运行,但在其他计算机上不起作用

VBA 2010 - CDate 类型不匹配问题

python中selenium控制浏览器尺寸

如何使我的电脑作为主机服务器工作?