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

标签 json excel vba web-scraping xmlhttprequest

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

我正在从我玩的加密游戏中收集数据。我已经能够使用该站点的 API 为我的“mons”解析数据。我正在尝试为游戏中的所有 mons 收集相同的数据。该 API 允许您一次提取 99 个 mons 的数据(一次最多 99 个)。大约有。存在 48,000 个 mons,而且这个数字还在继续上升。每个 mon 都有一个 ID 号(1 是第一个被抓到的人,之后每个人都有 n+1 个)。

这是访问 mons 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

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

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

这是我为我的库存中的 mons 提取所有这些变量的代码(它引用了不同的链接),但它已经包含了我想要它的排列方式。

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

选项显式

公共(public)子 WriteOutBattleInfo()
Dim headers(), r As Long, i As Long, json As Object, key As Variant, ws As Worksheet, BattleStats As Object
设置 ws = ThisWorkbook.Worksheets("Sheet1")
headers = Array("Monster #", "Name", "Total Level", "Perfect", "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

但我想要从 ID 1 到 48000 的所有 Mons。

最佳答案

您可以使用函数来增加 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

关于json - 如何使用带有数字范围的 VBA-JSON 解析数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54730790/

相关文章:

arrays - 过滤具有特定属性 Swift 的 json 数组

C# 使用 newtonsoft 删除 json 子节点

python - 如何从数组写入 Excel 中的整行 - xlwt

基于其他列的 Excel 条件格式

excel - Shape.OnAction 在复制工作簿后导致错误的工作表名称中不包含下划线

excel - 将图像和文本添加到旧的 Excel 游戏

ms-access - 当所有复选框切换时填写字段 Access 2010

javascript - 将对象数组和嵌套数组转换为 JSON

javascript - 通过 json 和 ajax 将事件从 Controller 获取到完整日历

c# - 以编程方式获取 Excel 列的最后一个非空单元格