관련: 지식인

 

셀레니움은 화면을 클릭하거나 정보를 입력해서 조회한 결과 값을 불러올 때 효율적입니다.

https://klayswap.com/assets 이 사이트의 경우는 JSON 데이터로 한번에 34페이지의 정보를 불러와서

실시간으로 10개씩 보여주는 구조이다 보니

일반 HTTP접속으로 JSON데이터를 한번에 가져와서 파싱하는 것이 훨씬 효율적입니다. 속도도 더 빠릅니다.

F12 개발도구로 살펴보면 가격에 대한 JSON데이터는 아래 주소로 받아옵니다.

https://s.klayswap.com/stat/tokenInfo.min.json

그리고 한글 이름에 대한 데이터는 아래 주소로 받아옵니다.

https://s.klayswap.com/data/klayswap/tokens.json

 

대개 JSON데이터를 파싱하기위해 VBAJSON을 이용하는데

첫번째 Json 데이터의 경우 아래처럼 키(key)가 없이 순수하게 JavaScript 배열구조로만 구성되어 있어서 VBAJSON에서 Json구문오류가 납니다.

Json 원본

Json 문자열은 VBA에서도 자바스크립트를 이용해서 2차원배열로 만들어서 처리할 수도 있습니다.

하지만 이번에는 또 다른 라이브러리(클래스)인 JsonBag을 이용해보겠습니다.

JsonBag 은 2.5버전이 공개되어 있고 비공식적으로 2.6까지 나와 있습니다.

 사용법은 JsonBag.Cls 를 프로젝트창에 끌어다 놓아서 클래스를 추가한 다음, 아래처럼 사용하면 됩니다.

특히 Dictionary를 사용하지 않아서 따로 라이브러리는 추가하지 않아도 됩니다.

 

Sub test_JasonBag()

    Dim JB As New JsonBag
    Dim str1 As String, str2 As String
    
    str1 = "[[1, ""hong"", ""leader of thievs"", false], [2, ""Robin"", ""leader of robbers"", true]]"
    str2 = "[{""id"": 1, ""userId"": ""hong"", ""job"": ""leader of thieves"", ""married"": false }, " & _
        "{ ""id"": 2, ""name"": ""Robin"", ""job"":""leader of robbers"", ""married"":true }]"
    
    JB.JSON = str1 'Json문자열
    Debug.Print JB(2)(1), JB(2)(3), JB(2)(4)   'Key가 없는 Array인 경우
    
    JB.JSON = str2
    Debug.Print JB(2)("id"), JB(2)("job"), JB(2)("married") 'Key가 있는 Collection인 경우
End Sub

 

이제 Json파일을 서버에서 받아와서 이 문자열을 JsonBag을 이용해서 파싱한 다음 화면에 출력해보도록 하겠습니다.

일단 아래처럼 XMLHttp를 이용해서 JB1과 JB2 두 개의 Json 데이터를 받아옵니다.

WinHttp를 이용해서 데이터를 받아올 수도 있으나 한글 인코딩이 깨집니다.

 

Option Explicit

Sub Main()

    Dim URL1 As String, URL2 As String
    Dim Http As Object
    Dim result As String
    Dim JB1 As New JsonBag   'need JsonBag Class ( https://github.com/sdomi/awsom )
    Dim JB2 As New JsonBag
    Dim I As Long, kname As String
    
    Set Http = CreateObject("MSXML2.ServerXMLHTTP")
    
    URL1 = "https://s.klayswap.com/stat/tokenInfo.min.json"
    URL2 = "https://s.klayswap.com/data/klayswap/tokens.json"
    
    With Http
        'get price
        .Open "get", URL1, False
        .SetRequestHeader "User-Agent", "Mozila/5.0"
        .SetRequestHeader "Accept", "application/json, text/plain, */*"
        .Send
        JB1.JSON = .ResponseText
        '[["id","address","symbol","name","chain","decimal","img","grade",
        ' "contractGrade","isDrops","isStable","amount","volume","oraclePrice","price"], [....]....]
        
        'get names in Korean
        .Open "get", URL2, False
        .SetRequestHeader "User-Agent", "Mozila/5.0"
        .SetRequestHeader "Accept", "application/json, text/plain, */*"
        .Send
        JB2.JSON = .ResponseText
        ' {
        '  "0x0000000000000000000000000000000000000000": {
        '    "id": 1,
        '    "name_en": "Klaytn",
        '    "name_ko": "클레이튼",
        '    "bridgeDeposit": 0
        '  }, ...

    End With

 

받아온 Json 문자열을 JsonBag구조로 만들었기 때문에 이제 아래와 같이 시트에 Json 값을 출력합니다.

JB1에는 영어이름만 들어 있기 때문에

해당 'address' 를 JB2에서 찾아서 name_ko 키값을 찾아줍니다.

 

    Cells.Clear
    
    With Range("A1:D1")
        .Value = Array("토큰", "가격", "심볼", "id")
        .Interior.Color = rgbDarkOrange
        .Font.Color = rgbWhite
        .Item(1).Select
        ActiveWindow.FreezePanes = True
    End With
    
    For I = 2 To JB1.Count
        Cells(I, 1).NumberFormat = "@"
        If JB2.Exists(ValueByKey(JB1, I, "address")) Then 'JB1(I)(2):해당 ID의 한글이름이 있으면
            kname = JB2(ValueByKey(JB1, I, "address"))("name_ko")
        Else
            kname = ""
        End If
        If kname = "" Then
            Cells(I, 1) = ValueByKey(JB1, I, "symbol") 'JB1(I)(3)  'symbol
        Else
            Cells(I, 1) = kname
        End If
        Cells(I, 2).NumberFormat = "0.00000"
        Cells(I, 2) = ValueByKey(JB1, I, "price") 'JB1(I)(15)
        Cells(I, 3).NumberFormat = "@"
        Cells(I, 3) = ValueByKey(JB1, I, "symbol") 'JB1(I)(3)
        Cells(I, 4) = ValueByKey(JB1, I, "id")  'JB1(I)(2)
    Next I
    
    Cells.Columns.AutoFit
    
    If Not JB1 Is Nothing Then Set JB1 = Nothing
    If Not JB2 Is Nothing Then Set JB2 = Nothing
    If Not Http Is Nothing Then Set Http = Nothing
    
End Sub

 

그리고 JB1의 경우 순수한 배열이라서

JB1(1)(1) 이런 식으로 가져오기 때문에 어떤 종류의 데이터인지 알 수 없어서 불편합니다.

알기 쉽게 키 이름으로 데이터를 가져오기 위해 1번째 배열에서 키를 찾아서 해당 index의 값을 찾아오도록 아래와 같은 function을 만들어 이용할 수 있습니다.

 

'Json 1번째 데이터가 Key역할인 경우, 주어진 Key로 값을 찾아음
Function ValueByKey(J As Object, idx As Long, key As String) As String
    Dim k As Integer
    Dim Found As Boolean
    For k = 1 To J(1).Count
        If J(1)(k) = key Then Found = True: Exit For
    Next k
    If Not Found Then
        MsgBox "key not found: " & key, vbCritical
    Else
        ValueByKey = J(idx)(k)
    End If
End Function

 

 

이제 JB1(2)(15) 로 가져오는 대신 ValueByKey(JB1, 2, "price") 로 직관적으로 값을 가져올 수 있겠습니다.

실행결과:

 

GetJson_klayswap1.xlsm
0.11MB