You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Excel控制已打开页面并优化Selenium的SKU查询效率?

问题解答

问题1:如何通过Excel控制已打开的网页?

控制已打开的网页有两种实用方案,可根据你的技术栈选择:

方案1:基于Selenium复用已打开的浏览器实例

如果已经在用Selenium(比如你问题2的场景),可通过调试端口复用已有会话:

  1. 手动启动浏览器并开启调试模式,例如Edge的启动命令:
    msedge.exe --remote-debugging-port=9222
    
  2. 在Excel VBA中连接到已打开的浏览器:
    Dim bot As New WebDriver
    bot.SetCapability "edgeOptions", {"debuggerAddress": "127.0.0.1:9222"}
    bot.Start "edge" ' 连接到已打开的浏览器,而非新建窗口
    
  3. 之后即可用bot对象操作目标页面,比如获取元素、执行JS等。

方案2:VBA结合IE对象(仅适用于IE浏览器)

针对IE浏览器,可通过ShellWindows直接获取已打开的窗口:

Dim ie As Object
For Each ie In CreateObject("Shell.Application").Windows
    If InStr(ie.FullName, "iexplore.exe") > 0 Then
        ' 匹配目标网页URL
        If ie.LocationURL = "目标网页地址" Then
            ' 执行页面操作,例如输入文本
            ie.Document.getElementById("输入框ID").Value = "内容"
            Exit For
        End If
    End If
Next ie

问题2:复用已打开页面批量处理SKU的优化方案

你当前的核心问题是每次处理SKU都重复启动浏览器、登录网站,这是耗时的主要原因。通过拆分代码逻辑,复用同一个浏览器实例,可大幅提升效率。

优化步骤:

  1. 拆分初始化与登录逻辑,单独完成浏览器启动和网站登录,返回已登录的WebDriver对象。
  2. 修改SKU查询函数,让它接收已有的WebDriver实例,不再每次新建。
  3. 替换固定等待为显式等待,减少不必要的等待时间。

优化后的代码示例:

1. 初始化浏览器并登录的过程

Private Function InitAndLogin() As WebDriver
    Dim bot As New WebDriver
    Dim userID As String
    Dim userPword As String
    Dim keys As New Selenium.keys
    
    bot.Start "edge"
    bot.Get "https://app.shiphero.com/dashboard/product-locations?warehouses=7145&customer=4222"
    
    userID = Application.InputBox("Enter User ID")
    userPword = Application.InputBox("Enter your Password")
    
    bot.FindElementByName("email", 1000).SendKeys userID
    bot.FindElementByName("password", 1000).SendKeys userPword
    bot.FindElementByName("password", 100).SendKeys keys.Enter
    
    ' 等待登录完成,可替换为等待登录后出现的特定元素
    bot.Wait 5000
    
    Set InitAndLogin = bot
End Function

2. 修改后的SKU查询函数(复用WebDriver)

Private Function GetProductLocation(bot As WebDriver, SKU As String, QtyOrdered As Integer) As clsLineItem
    Dim elem As WebElement
    Dim keys As New Selenium.keys
    Dim table As Selenium.WebElement
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' 搜索SKU
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    bot.FindElementByXPath("//*[@id='search_exact_match_product_locations']").Click
    ' 清空搜索框,避免残留内容干扰新SKU查询
    bot.FindElementByXPath("//*[@id='product_locations_filter']/label/input[1]").Clear
    bot.FindElementByXPath("//*[@id='product_locations_filter']/label/input[1]").SendKeys SKU
    bot.FindElementByXPath("//*[@id='product_locations_filter']/label/input[1]").SendKeys keys.Enter
    
    ' 等待搜索结果加载
    bot.Wait 3000
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' 解析库存表格
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Set table = bot.FindElementById("product_locations")
    
    Dim AllRows As Selenium.WebElements
    Dim SingleRow As Selenium.WebElement
    Dim AllRowCells As Selenium.WebElements
    Dim SingleCell As Selenium.WebElement
    Dim RowNum As Long
    Dim ColNum As Long
    
    Dim LocationIsValid As Boolean
    Dim Enough As Boolean
    Dim Expired As Boolean
    Dim productLocation As clsProductLocation
    Dim lineItem As clsLineItem
    
    Set AllRows = table.FindElementsByTag("tr")
    Set productLocation = New clsProductLocation
    Set lineItem = New clsLineItem
    
    RowNum = 0
    For Each SingleRow In AllRows
        LocationIsValid = False
        Enough = False
        Expired = True
        
        RowNum = RowNum + 1
        Set AllRowCells = SingleRow.FindElementsByTag("td")
        
        If AllRowCells.Count = 0 Then
            Set AllRowCells = SingleRow.FindElementsByTag("th")
        End If
        
        ColNum = 0
        For Each SingleCell In AllRowCells
            ColNum = ColNum + 1
            
            Select Case ColNum
                Case 5 ' 位置列
                    If ValidLocation(SingleCell.Text) Then
                        LocationIsValid = True
                        productLocation.Location = SingleCell.Text
                    End If
                    
                Case 9 ' 可用数量列
                    If LocationIsValid Then
                        If CSng(SingleCell.TextAsNumber) >= QtyOrdered Then
                            productLocation.QtyAvailable = SingleCell.TextAsNumber
                            Enough = True
                        End If
                    End If
                    
                Case 12 ' Lot ID列
                    If LocationIsValid Then
                        productLocation.LotCode = SingleCell.Text
                    End If
                
                Case 15 ' 剩余有效期列
                    If LocationIsValid Then
                        If CSng(SingleCell.TextAsNumber) >= 285 Then
                            productLocation.DaysUntilExpired = SingleCell.TextAsNumber
                            Expired = False
                        Else
                            Expired = True
                        End If
                    End If
                    
            End Select
            
            If LocationIsValid And Enough And Not Expired Then
                lineItem.LocationID = productLocation.Location
                lineItem.QtyAvailable = IIf(productLocation.QtyAvailable > 0, productLocation.QtyAvailable, 0)
                lineItem.LotID = productLocation.LotCode
                
                Set GetProductLocation = lineItem
                Exit Function
            End If
        Next SingleCell
    Next SingleRow
    
    If Enough Then
        lineItem.LocationID = "OOS-EXP"
    Else
        lineItem.LocationID = "OOS"
    End If
    
    Set GetProductLocation = lineItem
End Function

3. 批量处理SKU的主过程

Sub BatchProcessSKUs()
    Dim bot As WebDriver
    Dim skuList As Variant
    Dim i As Integer
    Dim qtyOrdered As Integer
    Dim result As clsLineItem
    
    ' 初始化浏览器并完成登录
    Set bot = InitAndLogin()
    
    ' 假设SKU列表在Sheet1的A列(A2到A21),对应订单数量在B列
    skuList = Sheet1.Range("A2:A21").Value
    
    For i = 1 To UBound(skuList)
        qtyOrdered = Sheet1.Range("B" & i + 1).Value
        Set result = GetProductLocation(bot, skuList(i, 1), qtyOrdered)
        
        ' 将结果写入Sheet1的C、D、E列
        Sheet1.Range("C" & i + 1).Value = result.LocationID
        Sheet1.Range("D" & i + 1).Value = result.QtyAvailable
        Sheet1.Range("E" & i + 1).Value = result.LotID
    Next i
    
    ' 处理完成后关闭浏览器(可选)
    bot.Quit
    Set bot = Nothing
End Sub

额外优化建议:

  • 将所有固定bot.Wait替换为显式等待,例如bot.FindElementById("目标元素ID", 10000),元素加载完成后立即执行操作,减少无效等待。
  • 检查ValidLocation函数的执行效率,避免它成为性能瓶颈。
  • 如果网站提供开放API,直接调用API获取数据的效率远高于模拟浏览器操作,可优先考虑这种方式。

内容的提问来源于stack exchange,提问作者rwebb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:02:04