【问题标题】:Scraping Macro Freezing after Just a Couple Loops在几个循环后刮掉宏冻结
【发布时间】:2016-10-05 13:03:47
【问题描述】:

我有一个抓取宏,它过去工作得很好,现在在几个循环(有时一个循环)后就冻结了。我已经做了我能想到的优化宏以不占用太多 CPU。我完全不知道为什么宏会像这样冻结。我的代码如下,任何提示或批评将不胜感激!

    Application.DisplayStatusBar = True
    Application.Calculation = xlCalculationManual
    Application.ScreenUpdating = False
    Application.EnableEvents = False

    Dim wb1 As Workbook
    Dim ws1 As Worksheet
    Dim Rows As Long, IE As InternetExplorer
    Dim i As Long
    Dim rngLinks As Range, rngLink As Range

    Sheet1.Cells.ClearContents
    Sheets("Landing Page").Select
    Range("E7").Select
    Range(Selection, Selection.End(xlDown)).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Sheet1").Range("A1").PasteSpecial xlPasteValues

    Sheets("Landing Page").Select
    Range("B5").Select
    Application.CutCopyMode = False
    Selection.Copy

    Set wb1 = ThisWorkbook
    Set ws1 = wb1.Worksheets("Sheet1")
    Set IE = New InternetExplorer

    Rows = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
    Set rngLinks = ws1.Range("A2:A" & Rows)
    i = 2

    With IE
        .Visible = True

        For Each rngLink In rngLinks
            .navigate (rngLink)

            While .Busy Or .readyState <> 4: DoEvents: Wend
            Application.Wait (Now() + TimeValue("00:00:004"))

            Dim doc As Object, dd As String
            Set doc = IE.document

            On Error GoTo Errorhandler:
            dd = doc.getElementsByClassName("price-display csTile-price")(0).innerText

            ws1.Range("B" & i).Value = dd

            i = i + 1

            Application.StatusBar = i

            dd = ""

            Set IE = Nothing
        Next rngLink
    End With

Errorhandler:

    dd = ""

    Resume Next

    Application.Calculation = xlCalculationAutomatic
    ws1.Activate
    Set rngLinks = Nothing

    'Strip out everything but total price

    Range("C2").Select
    ActiveCell.FormulaR1C1 = "=LEFT(RC[-1],FIND("" "",RC[-1])-0)"
    Range("C2").Select
    Selection.AutoFill Destination:=Range("C2:C" & Rows), Type:=xlFillDefault
    Range("C2:C" & Rows).Select
    Selection.Copy
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
                           :=False, Transpose:=False

    'Apply OnlyNums formula to remove delimeters
    Range("D2").Select
    Application.CutCopyMode = False
    ActiveCell.FormulaR1C1 = "=OnlyNums(RC[-1])"
    Range("D2").Select
    Selection.AutoFill Destination:=Range("D2:D" & Rows), Type:=xlFillDefault
    Range("D2:D" & Rows).Select
    Selection.Copy
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
                           :=False, Transpose:=False

    'Add decimal back in
    Range("E2").Select
    ActiveCell.FormulaR1C1 = "=iferror(RC[-1]/100,"" "")"
    Range("E2").Select
    Selection.AutoFill Destination:=Range("E2:E" & Rows), Type:=xlFillDefault
    Range("E2:E" & Rows).Select
    Selection.Copy
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
                           :=False, Transpose:=False
    Application.CutCopyMode = False
    Selection.Style = "Currency"

    'Remove columns C and D
    Columns("C:D").Select
    Selection.Delete Shift:=xlToLeft

    'Add column headers to F and G
    Range("B1").Select
    ActiveCell.FormulaR1C1 = "HTML Export (Raw)"

    Range("C1").Select
    ActiveCell.FormulaR1C1 = "Price"

    Application.DisplayStatusBar = True
    Application.EnableEvents = True
    Application.DisplayPageBreaks = False

    Range("D1").Select
    ActiveCell.FormulaR1C1 = "Collection Date"
    Rows2 = ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row
    Range("D2:D" & Rows2).Value = Date
    Range("E1").Select
    ActiveCell.FormulaR1C1 = "Company Store Number"
    Range("F1").Select
    ActiveCell.FormulaR1C1 = "UPC"

    Sheets("Landing Page").Select
    Range("B8").Select
    Range(Selection, Selection.End(xlDown)).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Sheet1").Range("E2").PasteSpecial xlPasteValues

    Sheets("Landing Page").Select
    Range("E8").Select
    Range(Selection, Selection.End(xlDown)).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Sheet1").Range("A2").PasteSpecial xlPasteValues

    Sheets("Landing Page").Select
    Range("D8").Select
    Range(Selection, Selection.End(xlDown)).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Sheet1").Range("F2").PasteSpecial xlPasteValues

    ws1.Activate

    Application.Calculation = xlCalculationAutomatic

    Dim acc As New Access.Application

    acc.OpenCurrentDatabase "S:\Aditem\Pricing\Scraping\Database.accdb"
    acc.DoCmd.TransferSpreadsheet _
        TransferType:=acImport, _
        SpreadSheetType:=acSpreadsheetTypeExcel12, _
        TableName:="Company", _
        Filename:=Application.ActiveWorkbook.FullName, _
        HasFieldNames:=True, _
        Range:="Sheet1$C1:F" & Rows

【问题讨论】:

  • 我很惊讶这完全有效 - 从 With IE 块中删除 Set IE = Nothing
  • 你是最棒的!这实际上是别人的建议留下的。我删除了它,到目前为止宏运行良好。

标签: excel vba loops macros screen-scraping


【解决方案1】:

2 个问题。首先(可能与问题无关,因为您没有提到运行时错误)是您在 With IE 块内释放 IE 对象。删除这一行:

Set IE = Nothing

第二个问题(更可能是挂起的原因)是您在将 rngLink 的值传递给 .Navigate 之前从未测试过它。如果rngLink 计算为vbNullString,IE 对象将永远不会从READYSTATE_UNINITIALIZED 更改.readyState,因此您的等待循环将永远不会退出。我会添加一个简单的测试:

If rngLink <> vbNullString Then
    .navigate rngLink

【讨论】:

  • 嗯,我知道你从哪里来的 Set IE = Nothing,但我不确定我是否关注第二个问题。我认为,宏使其进入 .ready 状态,因为它能够循环浏览我提供的 URL 列表。
  • @HenryK - 如果您尝试传递 vbNullString 让 IE 导航到,它不会做任何事情。这意味着这个循环:While .Busy Or .readyState &lt;&gt; 4: DoEvents: Wend 永远不会退出,因为.Busy 将是假的,.readyState 将卡在 0。
  • 所以我添加了您为 vbnull 字符串推荐的步骤,宏再次冻结。它通过大约 20 个链接,然后就冻结了。
  • @HenryK - 下一步是在循环中添加超时。 See this answer.
  • 你又是那个男人。现在运行流畅。通过 100 次循环和计数。
猜你喜欢
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
  • 2016-06-17
  • 1970-01-01
  • 2021-06-14
  • 2017-12-20
  • 1970-01-01
相关资源
最近更新 更多