Excel VBA - Web Scraping - Dapatkan nilai dalam sel Tabel HTML

Sep 04 2020

Saya mencoba membuat makro yang menghapus situs web pelacakan kargo. Tetapi saya harus membuat 4 makro karena setiap maskapai penerbangan memiliki situs web yang berbeda.

Saya baru mengenal VBA dan web scraping.

Saya telah mengumpulkan kode yang berfungsi untuk 1 situs web. Tetapi ketika saya mencoba menirunya untuk yang lain, saya terjebak dalam lingkaran. Saya pikir itu mungkin bagaimana saya mengacu pada elemen, tetapi seperti yang saya katakan, saya baru mengenal VBA dan tidak tahu tentang HTML.

Saya mencoba mendapatkan nilai "diberitahukan" di baris yang disorot dari gambar.

IMAGE: teks "diberitahukan" untuk diekstraksi Di bawah ini adalah kode yang telah saya tulis sejauh ini yang macet di loop. Bantuan apa pun dengan ini akan dihargai.

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

Jawaban

2 Zwenn Sep 05 2020 at 18:04

Beberapa dasar:
Untuk akses sederhana, seperti yang sekarang, Anda dapat menggunakan metode get dari DOM (Model Objek Dokumen). Tetapi ada perbedaan penting antara getElementByID()dan getElementsByClassName()/ getElementsByTagName().

getElementByID()mencari ID unik dari tag html. Ini ditulis sebagai atribut ID untuk tag html. Jika standar html disimpan oleh halaman, hanya ada satu elemen dengan ID unik ini. Itulah alasan mengapa metode ini dimulai dengan getElement.

Jika ID tidak ditemukan saat menggunakan metode ini, VBA akan menampilkan error runtime. Oleh karena itu panggilan dirangkum dalam loop dari jawaban lain dari saya, ke mematikan dan lagi penanganan kesalahan. Namun di halaman pertanyaan ini tidak ada ID untuk area html yang dimaksud.

Sebagai gantinya, elemen yang dibutuhkan dapat diakses secara langsung. Anda mencoba akses dengan getElementsByClassName(). Tepat sekali. Tapi inilah perbedaannya getElementByID().

getElementsByClassName()dan getElementsByTagName()mulai dengan getElements. Itu jamak karena bisa ada sebanyak mungkin elemen dengan kelas atau nama tag yang sama seperti yang Anda inginkan. Kedua metode ini membuat kumpulan node html. Semua elemen html dengan kelas yang diminta atau nama tag akan menjadi listet dalam koleksi tersebut.

Semua elemen memiliki indeks, seperti array. Indeks dimulai dari 0. Untuk mengakses elemen tertentu, indeks yang diinginkan harus ditentukan. Dua nama kelas fs-12 body-font-bold( nama kelas dipisahkan oleh spasi, Anda juga dapat membangun koleksi node dengan hanya menggunakan satu nama kelas) mengirimkan 2 elemen html ke koleksi node. Anda ingin yang kedua jadi Anda harus menggunakan indeks 1.

Ini adalah kode VBA untuk halaman yang diminta dengan menggunakan IE:

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

Edit: Sub sebagai fungsi

Sub ini untuk menguji fungsinya:

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

Ini adalah sub fungsi:

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