주식 시세처럼 웹 페이지에 표로 나오는 데이터를 엑셀로 옮기고 싶을 때, 가장 손이 덜 가는 방법은 HTML에서 <table> 부분만 잘라 엑셀에 그대로 붙여 넣는 겁니다. 엑셀은 클립보드에 들어온 HTML 표를 셀 단위로 알아서 나눠 주기 때문에, 행·열을 일일이 파싱하는 코드를 짤 필요가 없습니다. 아래는 kr.investing.com의 한국 주식 목록 페이지에 HTTPS(443 포트)로 접속해서 시세 표를 가져오는 매크로입니다.

kr.investing.com 한국 주식 시세 표를 엑셀 시트로 가져온 결과

Sub program1472_com()
    Dim T As String, URL As String
    URL = "https://kr.investing.com/equities/StocksFilter?noconstruct=1&smlID=694&sid=&tabletype=price&index_id=49661"
    With CreateObject("MSXML2.XMLHTTP.6.0")
        .Open "GET", URL
        .SetRequestHeader "Host", "kr.investing.com"
        .SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0"
        .SetRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
        .SetRequestHeader "Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3"
        .SetRequestHeader "Connection", "keep-alive"
        .SetRequestHeader "Upgrade-Insecure-Requests", "1"
        .Send
        T = .ResponseText
    End With
    T = Split(Split(T, "<table")(1), "</table")(0)
    T = "<table" & T & "</table>"
    SetClipboard T
    ActiveSheet.Paste Destination:=[A1]
End Sub

'// 클립보드에 텍스트 쓰기
Public Function SetClipboard(ByRef sText As String) As Boolean ' ### 리턴값: 성공 여부
    On Error GoTo nErr
    Dim Clipboard As Object
'    Microsoft Forms 2.0 Object Library
    Set Clipboard = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    Clipboard.SetText sText
    Clipboard.PutInClipboard
    SetClipboard = True
nErr:
End Function

어떤 주소를 부르나

브라우저로 보는 페이지 주소(/equities/south-korea/)가 아니라 StocksFilter?noconstruct=1&... 라는 주소를 직접 호출합니다. 페이지 안에서 표 부분만 따로 불러오는 주소라서 응답이 가볍고, 앞쪽에 메뉴나 광고 HTML이 덜 붙어 있어 첫 번째 <table 이 원하는 시세 표일 확률이 높습니다. 다른 지수나 다른 탭(가격, 실적 등)을 받고 싶다면 브라우저 개발자 도구의 네트워크 탭에서 표가 바뀔 때 어떤 주소가 호출되는지 보고 파라미터를 바꾸면 됩니다.

요청 헤더는 실제 파이어폭스가 보내는 값을 흉내 낸 것입니다. 이런 사이트는 User-Agent 가 없거나 이상하면 차단 페이지를 돌려주는 경우가 많아서, 브라우저 헤더를 그대로 옮겨 두는 편이 무난합니다. .Open 의 세 번째 인자를 생략했으니 동기 방식이고, .Send 가 끝날 때까지 엑셀이 기다립니다.

표만 잘라 붙여 넣는 부분

Split(T, "<table")(1) 로 첫 번째 <table 뒤를 잡고, 다시 Split(..., "</table")(0) 로 그 표가 끝나는 지점 앞까지만 남깁니다. 잘리면서 떨어져 나간 여는 태그와 닫는 태그를 앞뒤로 다시 붙여서 온전한 <table>...</table> 문자열을 만들고요.

이걸 SetClipboard 로 클립보드에 넣은 뒤 ActiveSheet.Paste 로 A1부터 붙이면, 엑셀이 HTML 표를 해석해서 셀에 나눠 담습니다. SetClipboard 는 참조 추가 없이 CreateObject 에 CLSID를 넘겨 Microsoft Forms 2.0의 DataObject를 만드는 방식이라, 어느 PC에서든 별도 설정 없이 돌아갑니다.

막히는 지점

응답에 <table 이 하나도 없으면, 예를 들어 사이트가 차단 페이지나 오류 페이지를 돌려주면, Split(...)(1) 에서 "아래 첨자 사용이 잘못되었습니다" 오류가 납니다. 실제로 쓸 때는 InStr(T, "<table") 로 먼저 확인하고, 없으면 응답 일부를 시트나 디버그 창에 찍어서 무엇이 왔는지 보는 게 좋습니다.

붙여 넣기 방식은 시트에 원래 있던 서식을 덮어쓰고, 표 크기가 바뀌면 이전 결과가 일부 남을 수 있습니다. 반복 실행할 거라면 붙이기 전에 대상 영역을 지우세요. 그리고 투자 정보 사이트는 자동 수집을 막거나 약관으로 제한하는 경우가 많으니, 짧은 간격으로 계속 돌리는 용도라면 공식 데이터 제공 방법이 있는지 먼저 확인하는 게 순서입니다.