如何使用带有URL中数字范围的VBA-JSON解析数据?

时间:2019-02-17 06:37:55

标签: json excel vba web-scraping xmlhttprequest

需要使用VBA-JSON从URL编号发生变化的不同URL中提取数据

我正在从我玩的加密游戏中收集数据。我已经可以使用网站的API来解析“我的怪物”中的数据。我正在尝试为游戏中的所有mons收集相同的数据。该API可让您一次提取99个mons的数据(一次最多可提取99个)。有大约。存在48,000个mons,并且这个数字还在继续增加。每个星期一都有一个ID号(第一个被捕获为1,之后为每个n + 1)。

这是访问星期一1-99数据的链接:https://www.etheremon.com/api/monster/get_data?monster_ids=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99

我需要先提取1-99,然后100-198,然后199-297等数据,直到48000。

我想从每个星期一收集ID号,“ class_name”,“ total_level”,“ perfect_rate”,“ create_index”(都是字典),最重要的是,我想要“ total_battle_stats”(它是一个数组) 。

这是我要提取清单中所有mons变量的代码(它引用了其他链接),但是它已经包含了我想要的方式。

我只需要那些相同的变量,但要引用很多不同的链接,而不仅仅是一个。

显式选项

公共Sub WriteOutBattleInfo()     Dim headers(),r为Long,i为Long,json为对象,键为Variant,ws为工作表,battleStats为对象     设置ws = ThisWorkbook.Worksheets(“ Sheet1”)     标头= Array(“ Monster#”,“ Name”,“ Total Level”,“ Perfection”,“ Catch Number”,“ HP”,“ PA”,“ PD”,“ SA”,“ SD”,“ SPD” )

With CreateObject("MSXML2.XMLHTTP")
    .Open "GET", "https://www.etheremon.com/api/user/get_my_monster?trainer_address=0x2Fef65e4D69a38bf0dd074079f367CDF176eC0De", False
    .Send
    Set json = JsonConverter.ParseJson(.ResponseText)("data")("monsters") 'dictionary of dictionaries
End With
r = 2
ws.Cells(1, 1).Resize(1, UBound(headers) + 1) = headers
For Each key In json.Keys
    With ws
        .Cells(r, 1) = key
        .Cells(r, 2) = json(key)("class_name")
        .Cells(r, 3) = json(key)("total_level")
        .Cells(r, 4) = json(key)("perfect_rate")
        .Cells(r, 5) = json(key)("create_index")
        Set battleStats = json(key)("total_battle_stats")

        For i = 1 To battleStats.Count
            .Cells(r, i + 5) = battleStats.Item(i)
        Next i
    End With
    r = r + 1
Next

Range(Selection, ActiveCell.SpecialCells(xlLastCell)).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add2 key:=Range("C2:C110" _
    ), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
    .SetRange Range("A1:K110")
    .Header = xlYes
    .MatchCase = False
    .Orientation = xlTopToBottom
    .SortMethod = xlPinYin
    .Apply
End With
Selection.Columns.AutoFit

结束子

我希望它看起来像这样:https://imgur.com/a/xPA9T7W

但是我希望所有Mons从ID 1到48000。

1 个答案:

答案 0 :(得分:2)

您可以使用一个函数来增加ID以连接到基本URL。如果您要求太快/可能太多次,则站点会受到限制/阻塞。查看文档以获取任何建议。

我展示了如何检索所有内容。我提供了一个1到5个请求的测试用例(取消注释以获取全部请求。注:我给一行代码供您调整,它允许每个x请求增加延迟,以尝试避免节流/阻塞。在发生这种情况之前,这个数字似乎很低。

稍后,您可以考虑将其移到一个类中以保存xmlhttp对象并为其提供诸如getItems之类的方法。示例here

Option Explicit

Public Sub WriteOutBattleInfo()
    Const BASE_URL As String = " https://www.etheremon.com/api/monster/get_data?monster_ids="
    Const END_COUNT As Long = 48000
    Const BATCH_SIZE As Long = 99
    Dim numberOfRequests As Long, i As Long, j As Long, ids As String
    Dim headers(), r As Long, json As Object, key As Variant, ws As Worksheet, battleStats As Object

    Set ws = ThisWorkbook.Worksheets("Sheet1")
    headers = Array("Monster #", "Name", "Total Level", "Perfection", "Catch Number", "HP", "PA", "PD", "SA", "SD", "SPD")
    numberOfRequests = Application.WorksheetFunction.RoundDown(END_COUNT / BATCH_SIZE, 0)
    ids = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99"

    Dim results()
    ReDim results(1 To END_COUNT, 1 To 11)
    r = 1

    With CreateObject("MSXML2.XMLHTTP")
        For i = 1 To 5 'numberOfRequests + 1
            If i Mod 10 = 0 Then Application.Wait Now + TimeSerial(0, 0, 1)
            If i > 1 Then ids = IncrementIds(ids, BATCH_SIZE, END_COUNT)
            .Open "GET", BASE_URL & ids, False
            .send
            Set json = JsonConverter.ParseJson(.responseText)("data")

            For Each key In json.keys
                results(r, 1) = key
                results(r, 2) = json(key)("class_name")
                results(r, 3) = json(key)("total_level")
                results(r, 4) = json(key)("perfect_rate")
                results(r, 5) = json(key)("create_index")

                Set battleStats = json(key)("total_battle_stats")

                For j = 1 To battleStats.Count
                    results(r, j + 5) = battleStats.item(j)
                Next j
                r = r + 1
            Next
        Next
    End With

    ws.Cells(1, 1).Resize(1, UBound(headers) + 1) = headers
    ws.Cells(2, 1).Resize(UBound(results, 1), UBound(results, 2)) = results
End Sub

Public Function IncrementIds(ByVal ids As String, ByVal BATCH_SIZE As Long, ByVal END_COUNT) As String
    Dim i As Long, arrayIds() As String
    arrayIds = Split(ids, ",")
    For i = LBound(arrayIds) To UBound(arrayIds)
        If CLng(arrayIds(i)) + BATCH_SIZE <= END_COUNT Then
            arrayIds(i) = arrayIds(i) + BATCH_SIZE
        Else
            ReDim Preserve arrayIds(0 To i - 1)
            Exit For
        End If
    Next
    IncrementIds = Join(arrayIds, ",")      
End Function