본문 바로가기

Code Snippets/VBA

[VBA] HTML Table 크롤링 (HTML Object Library, XML)

코드

'html table 뽑아내는 vba 코드
​
Sub Get_table()
   
   Dim ws As Worksheet, results(), i As Long, s As Long
   Dim TK As String
   Dim LastRow As Long
   Dim html As MSHTML.HTMLDocument
   Dim data, trow, td As Object
​
   Dim split1() As String, split2() As String, split3() As String, split4() As String
   
   'LastRow = Worksheets("kmtc").Cells(Rows.Count, 3).End(xlUp).Row
   
   Dim URL1, URL2, URL3, FINAL As String
​
   
   Set html = New MSHTML.HTMLDocument
   Debug.Print LastRow
   s = 6
   For i = 6 To 100
       
       'TK = Cells(i, 3).Value
       URL1 = "http://tips.energy.or.kr/m/business_support/market_view.do?no="
       FINAL = URL1 & CStr(i + 10)
'        Debug.Print FINAL
​
       
       With CreateObject("MSXML2.XMLHTTP")
           .Open "GET", FINAL, False
           .send
'            Debug.Print .responseText
           html.body.innerHTML = .responseText
       End With
       Set data = html.querySelector("#listTable1 tbody")
       On Error Resume Next
       If data.getElementsByTagName("tr").Item(0).getElementsByTagName("td").Item(0).innerText <> "" Then
           Cells(s, 4).Value = data.getElementsByTagName("tr").Item(0).getElementsByTagName("td").Item(0).innerText
           Cells(s, 5).Value = data.getElementsByTagName("tr").Item(1).getElementsByTagName("td").Item(0).innerText
           Cells(s, 6).Value = data.getElementsByTagName("tr").Item(2).getElementsByTagName("td").Item(0).innerText
           Cells(s, 7).Value = data.getElementsByTagName("tr").Item(4).getElementsByTagName("td").Item(1).innerText
           Cells(s, 8).Value = data.getElementsByTagName("tr").Item(5).getElementsByTagName("td").Item(0).innerText
           Cells(s, 9).Value = data.getElementsByTagName("tr").Item(6).getElementsByTagName("td").Item(0).innerText
           Cells(s, 10).Value = data.getElementsByTagName("tr").Item(7).getElementsByTagName("td").Item(0).innerText
           Cells(s, 11).Value = FINAL
           s = s + 1
       Else
       End If
   Next
End Sub
​
​​

 

Comments

  • Microsoft HTML Object 라이브러리와 Microsoft XML 라이브러리를 활성화해줘야 한다
  • html.querySelector로 특정 id의 tbody를 가져올 수 있다. ("#listTable1 tbody) 
  • 코드의 핵심은 'HTML Table은 하나의 object인데, 그 안의 tr(Table Row, 행) 및 행 안의 모든 td (table data, 데이터)도 object라는 것이다'. 그렇게 모든 것이 object이고 층계를 이루고 있기 때문에, 위 코드에서는 보이지 않았지만 for each 문법도 사용 가능하다.
  • VBA로 크롤링을 반드시 해야하는 경우만 위 코드를 추천하고, 일반적인 경우에는 파이썬의 pd.read_html를 강력 추천한다.
    • 두 코드의 구현 논리가 완전히 다른데, VBA에서 HTML Table를 크롤링하는 것은 내가 필요한 데이터만 따로 선별해서 뽑아와야 하는 반면, pd.read_html를 쓰면 테이블을 한번에 통째로 가져온 후 필요없는 행이나 열을 날려버릴 수 있다. 후자가 훨씬 편하다