首页 > 解决方案 > Excel VBA - Web Scraping - 在 HTML 表格单元格中获取值

问题描述

我正在尝试创建一个抓取货物跟踪网站的宏。但是我必须创建 4 个这样的宏,因为每家航空公司都有不同的网站。

我是 VBA 和网络抓取的新手。

我整理了一个适用于 1 个网站的代码。但是当我试图将它复制到另一个时,我陷入了困境。我认为这可能是我指代元素的方式,但就像我说的那样,我是 VBA 新手,对 HTML 一无所知。

我正在尝试从图像中突出显示的行中获取“通知”值。

图像:要提取的“通知”文本 下面是我到目前为止编写的代码,它卡在循环中。对此的任何帮助将不胜感激。

Sub FlightStat_AF()

Dim url As String
Dim ie As Object
Dim nodeTable As Object

  'You can handle the parameters id and pfx in a loop to scrape dynamic numbers
  url = "https://www.afklcargo.com/mycargo/shipment/detail/057-92366691"

  'Initialize Internet Explorer, set visibility,
  'call URL and wait until page is fully loaded
  Set ie = CreateObject("InternetExplorer.Application")
  ie.Visible = False
  ie.navigate url
  Do Until ie.readyState = 4: DoEvents: Loop
  
  'Wait to load dynamic content after IE reports it's ready
  'We can do that in a loop to match the point the information is available
  Do
    On Error Resume Next
    Set nodeTable = ie.document.getElementByClassName("block-whisper")
    On Error GoTo 0
  Loop Until Not nodeTable Is Nothing
  
  'Get the status from the table
  MsgBox Trim(nodeTable.getElementsByClassName("fs-12 body-font-bold").innerText)
  
  'Clean up
  ie.Quit
  Set ie = Nothing
  Set nodeTable = Nothing
End Sub

标签: excelvbaweb-scraping

解决方案


一些基础知识:
对于简单的访问,比如现在的访问,您可以使用 DOM(文档对象模型)的 get 方法。getElementByID()但是and getElementsByClassName()/之间有一个重要的区别getElementsByTagName()

getElementByID()搜索 html 标记的唯一 ID。这被写为 html 标签的 ID 属性。如果页面保持 html 标准,则只有一个元素具有此唯一 ID。这就是该方法以 . 开头的原因getElement

如果在使用该方法时找不到 ID,VBA 会引发运行时错误。因此,调用被封装在我的另一个答案的循环中,关闭并再次打开错误处理。但是在这个问题的页面中,有问题的 html 区域没有 ID。

相反,可以直接访问所需的元素。您尝试使用getElementsByClassName(). 这是正确的。但这里有不同之处getElementByID()

getElementsByClassName()getElementsByTagName()getElements. 那是复数,因为可以有尽可能多的具有相同类或标签名称的元素。这两种方法都创建了一个 html 节点集合。所有具有所要求的类或标签名称的 html 元素都将在这些集合中列出。

所有元素都有一个索引,就像数组一样。索引从 0 开始。要访问特定元素,必须指定所需的索引。两个类名fs-12 body-font-bold(类名用空格隔开,也可以只用一个类名构建一个节点集合)向节点集合传递2个html元素。你想要第二个,所以你必须使用索引 1。

这是使用 IE 的询问页面的 VBA 代码:

Sub FlightStat_AF()

Dim url As String
Dim ie As Object

  'You can handle the parameters id and pfx in a loop to scrape dynamic numbers
  url = "https://www.afklcargo.com/mycargo/shipment/detail/057-92366691"

  'Initialize Internet Explorer, set visibility,
  'call URL and wait until page is fully loaded
  Set ie = CreateObject("InternetExplorer.Application")
  ie.Visible = False
  ie.navigate url
  Do Until ie.readyState = 4: DoEvents: Loop
  
  'Wait to load dynamic content after IE reports it's ready
  'We do that with a fix manual break of a few seconds
  'because the whole page will be "reload"
  'The last three values are hours, minutes, seconds
  Application.Wait (Now + TimeSerial(0, 0, 3))
  
  'Get the status from the table
  MsgBox Trim(ie.document.getElementsByClassName("fs-12 body-font-bold")(1).innerText)
  
  'Clean up
  ie.Quit
  Set ie = Nothing
End Sub

编辑:子作为函数

这个子来测试功能:

Sub testFunction()
  Dim flightStatAfResult As String
  flightStatAfResult = FlightStat_AF("057-92366691")
  MsgBox flightStatAfResult
End Sub

这是子函数:

Function FlightStat_AF(cargoNo As String) As String

Dim url As String
Dim ie As Object
Dim result As String

  'You can handle the parameters id and pfx in a loop to scrape dynamic numbers
  url = "https://www.afklcargo.com/mycargo/shipment/detail/" & cargoNo

  'Initialize Internet Explorer, set visibility,
  'call URL and wait until page is fully loaded
  Set ie = CreateObject("InternetExplorer.Application")
  ie.Visible = False
  ie.navigate url
  Do Until ie.readyState = 4: DoEvents: Loop
  
  'Wait to load dynamic content after IE reports it's ready
  'We do that with a fix manual break of a few seconds
  'because the whole page will be "reload"
  'The last three values are hours, minutes, seconds
  Application.Wait (Now + TimeSerial(0, 0, 3))
  
  'Get the status from the table
  result = Trim(ie.document.getElementsByClassName("fs-12 body-font-bold")(1).innerText)
  
  'Clean up
  ie.Quit
  Set ie = Nothing
  
  'Return value of the function
  FlightStat_AF = result
End Function

推荐阅读