Разбор json "dict of dicts" в базу данных sqlite3 - PullRequest
0 голосов
/ 11 января 2019

Мне нравится эта новая карточная игра под названием Keyforge, и я любитель данных, который хочет предоставить сообществу некоторые интересные инструменты и функции. Моя конечная цель - разработать приложение, которое сканирует новый QR-код новой колоды и сразу скажет вам, насколько хороша ваша новая колода и как она размещается по сравнению с остальными колодами в мире. Все это с помощью машинного обучения.

У компании, которая делает игру, есть API, из которого я извлекаю все данные, и он поставляется в виде объекта JSON. Я считаю, что это диктат (я скопировал часть файла JSON ниже, чтобы вы подтвердили, что я прав). У меня нет особого опыта работы с объектами JSON, но я в целом хорошо разбираюсь в python.

Я пытаюсь проанализировать или извлечь данные (все или некоторые из них) в базу данных sqlite3. Я довольно плохо знаком с базами данных, поэтому я изо всех сил.

Помимо JSON для sqlite 3, мне также нужно манипулировать данными в формате, который необходим для моего алгоритма обучения, но я думаю, что справлюсь с этим.

Я перепробовал много вещей, которые нашел здесь и в Интернете, но ни одна из них не работает.

Ниже приведены начало и некоторая средняя часть одного из файлов JSON, чтобы вы могли понять, как структурированы данные. Я прочитал, что мне нужно сначала сгладить это, и я попробовал несколько вещей, но мне пока не повезло. Моя цель - создать таблицу, в которой каждая строка представляет собой колоду (или образец для алгоритма обучения). Ниже вы можете увидеть пару колод: «Доктор Олд Джеффрис» и «Джендри В. Райнити, загадочный». Столбцы таблицы будут представлять собой уникальный идентификационный номер (главный ключ, автоматическое увеличение и т. Д.), В основном 1, 2, 3, ... и т. Д., А остальные столбцы будут называться «name», "расширение", "уровень_уровня" и т. д. Фактические минимальные данные, которые мне действительно нужны, это номер идентификатора (основной ключ, авто-увеличение), "номер_карты" для каждой из 36 карт в каждой колоде (это число из От 1 до 370, которые являются карточками в игре), а затем столбцы для «выигрышей», «проигрышей», «casual_wins» и «casual_losses», что жизненно важно для обучения алгоритма обучения хорошей удачной колоде.

{
  "count": 459959, #this is how many decks are live in the World
  "data": [        #this contains the name of each deck and other data
    {
      "name": "Dr. \"The Old\" Jeffries",
      "expansion": 341,
      "power_level": 0,
      "chains": 0,
      "wins": 0,
      "losses": 0,
      "id": "ec86db52-e41e-4e6a-9f1a-a2d0e3d3277d",
      "is_my_deck": false,
      "notes": [],
      "is_my_favorite": false,
      "is_on_my_watchlist": false,
      "casual_wins": 0,
      "casual_losses": 0,
      "_links": {
        "houses": [
          "Brobnar",
          "Dis",
          "Logos"
        ],
        "cards": [        #this is the list of 36 cards for this deck
          "d438faa9-7920-437a-8d1c-682fade5d350",
          "d438faa9-7920-437a-8d1c-682fade5d350",
          "0ef760a3-68b9-42a9-93fa-419ea171917b",
          "68e2188c-4002-43d4-9fe1-0262df26c33f",
          "68e2188c-4002-43d4-9fe1-0262df26c33f",
          "3d650fe4-817a-4922-ba0f-297c1ebf816d",
          "652c4e38-c4fa-4e30-8f8d-036e95249529",
          "d4f666db-302f-43d0-b0af-bd03071f92ce",
          "0c3231e1-1230-4e7d-890e-6d3149125de2",
          "d792387f-8392-49b3-ad7c-ccaf7552256f",
          "f2c71c05-7a23-4465-8a89-82ab8e258a68",
          "e1312fbf-c297-4d9f-b403-2d892271de62",
          "d2edea65-7c2f-487f-a6f4-f44a077c4a65",
          "10715fd2-031a-47ca-9119-9b7b2ec1d2c0",
          "10715fd2-031a-47ca-9119-9b7b2ec1d2c0",
          "be492d70-5c87-441e-8223-79fb2bce85c9",
          "d42dd1d0-3462-410f-b683-dd0768b84188",
          "5607fecd-b90e-4e12-84bc-cb36d079117c",
          "ea2a390e-e121-4cbd-96c5-2430cc600e81",
          "96548d93-b318-40e3-9f5c-3297c8070ebd",
          "17e9dbd4-53cb-4c75-bdad-48e1550ff1e7",
          "916f271b-9928-437c-bfc4-d60d32af8c7c",
          "9ed7d241-1ca3-4a2a-b067-bb44776f7d4b",
          "b8343462-b5d7-48b0-9e3b-f020c5e73c55",
          "1283215c-3ea2-4d2b-9af4-452d7c0d57d9",
          "1283215c-3ea2-4d2b-9af4-452d7c0d57d9",
          "448c1335-d45b-473e-b222-d71f31ba0292",
          "448c1335-d45b-473e-b222-d71f31ba0292",
          "45d564a2-fcc9-4baa-8dc8-8e1a0fe2a37a",
          "5a521238-f524-48e3-b121-40c16e1f7610",
          "57bccc52-b6a1-4d11-b9d9-6356d8ac279c",
          "cd83ebe7-f961-4e5e-a00e-046d1be5e5d3",
          "53f7d3ec-a65f-4b05-8c82-74f44a7bdc44",
          "60f095d7-1816-4f14-88ec-04412ebde43b",
          "60f095d7-1816-4f14-88ec-04412ebde43b",
          "bec84d69-68f0-456c-a7bd-9f1e94d55a22"
        ]
      }
    },
    {
      "name": "Gendry V. Rineity, the Enigmatic",
      "expansion": 341,
      "power_level": 0,
      "chains": 0,
      "wins": 0,
      "losses": 0,
      "id": "48761c52-1bf0-4437-ba12-f0544237da4e",
      "is_my_deck": false,
      "notes": [],
      "is_my_favorite": false,
      "is_on_my_watchlist": false,
      "casual_wins": 0,
      "casual_losses": 0,
      "_links": {
        "houses": [
          "Dis",
          "Logos",
          "Mars"
        ],
        "cards": [
          "699f06e3-e47b-4910-90b9-c67fac157d6e",
          "10715fd2-031a-47ca-9119-9b7b2ec1d2c0",
          "10715fd2-031a-47ca-9119-9b7b2ec1d2c0",
          "aa73a693-e1e6-4097-8010-ddc820cc6d96",
          "9644c85a-12a7-44ff-a8bb-877dddb46995",
          "750a9323-9c07-4ae7-be5e-79367b4a2a8d",
          "c5ed37f7-0d05-48bc-a595-4f25c0ec1e6d",
          "f97316b0-75a4-45a4-8735-15e72cc1568c",
          "916f271b-9928-437c-bfc4-d60d32af8c7c",
          "3d6a02d0-b5c8-49be-93e4-dfdd5c1200eb",
          "9152cbad-d83f-4ee4-9846-87cc60d185f1",
          "b8343462-b5d7-48b0-9e3b-f020c5e73c55",
          "8c763540-bb69-47aa-be43-4a8ace89864c",
          "f51e8ec0-ab0e-46a8-a5f5-680039d6e664",
          "1838fbaa-a062-4593-acbe-53ecfadfb5cc",
          "1838fbaa-a062-4593-acbe-53ecfadfb5cc",
          "2cb1f58c-5979-4d3a-ae86-9dadc6000288",
          "2cb1f58c-5979-4d3a-ae86-9dadc6000288",
          "2cb1f58c-5979-4d3a-ae86-9dadc6000288",
          "448c1335-d45b-473e-b222-d71f31ba0292",
          "3c5c1881-486c-4911-a3ce-497ef258e8ba",
          "2ec5cbf6-3c41-41ef-9cb7-33a0601fd607",
          "2ec5cbf6-3c41-41ef-9cb7-33a0601fd607",
          "c08c91f0-043a-4a8a-8761-6080e9f46183",
          "16168a85-bbfa-4e54-8c84-5ea02e2a7da1",
          "cc44ca9a-6994-4897-9308-ff332cc8de57",
          "19b74b4e-bec8-4fbb-bd35-cb635f500249",
          "0cc7c1ea-5196-40ff-b408-f31997c8ab4d",
          "179f877a-9b59-46d6-a43e-15b4524af3c6",
          "0e5e8a55-ab05-44be-8637-8362974dad8b",
          "aabeebf7-1da5-4149-afab-e7e221b47d93",
          "a8a3578c-7a61-4e15-90ac-483daf2aff16",
          "1a84631d-7fcb-4c9a-a50c-9539dcb84928",
          "211c5213-7838-4292-b9c4-fb3a663898ee",
          "ac8fb9f6-ee8e-4434-85e8-d084a66c50db",
          "ff104cf4-f99d-4021-a570-dd949e559e97"
        ]
      }
    },


#...
#... there are 25 decks per page. I can only get that many per API call
#...

  "_linked": {     #here are the actual houses per deck and the actual cards
    "houses": [
      {
        "id": "Brobnar",
        "name": "Brobnar",
        "image": "https://cdn.keyforgegame.com/media/houses/Brobnar_RTivg44.png"
      },
      #...more data was in here but there is URL limit
      {
        "id": "Mars",
        "name": "Mars",
        "image": "https://cdn.keyforgegame.com/media/houses/Mars_CmAUCXI.png"
      }
    ],
    "cards": [
      {
        "id": "469dd68d-cdd6-40e0-8fc9-a167c45a9aea",
        "card_title": "Grasping Vines",
        "house": "Untamed",
        "card_type": "Action",
        "front_image": "https://cdn.keyforgegame.com/media/card_front/en/341_324_VH9R4P26824V_en.png",
        "card_text": "Play: Return up to 3 artifacts to their owners’ hands.",
        "traits": null,
        "amber": 1,
        "power": 0,
        "armor": 0,
        "rarity": "Uncommon",
        "flavor_text": null,
        "card_number": 324,
        "expansion": 341,
        "is_maverick": false
      },
      {
        "id": "1a84631d-7fcb-4c9a-a50c-9539dcb84928",
        "card_title": "Yxilo Bolter",
        "house": "Mars",
        "card_type": "Creature",
        "front_image": "https://cdn.keyforgegame.com/media/card_front/en/341_204_H9HQ5F59FJQX_en.png",
        "card_text": "Fight/Reap: Deal 2<D> to a creature. If this damage destroys that creature, purge it.",
        "traits": "Martian • Soldier",
        "amber": 0,
        "power": 3,
        "armor": 0,
        "rarity": "Common",
        "flavor_text": null,
        "card_number": 204,
        "expansion": 341,
        "is_maverick": false
      },   #the data goes on for quite a bit

import json
import requests
import sqlite3
from datetime import datetime

DATE_FORMAT = '%Y-%m-%d'

class Keyforge():
#    def __init__(self):

    def download(self,pagestart,pagestop):
        #Downloads batches of 25 decks per page. pagestart=1,pagestop=5 will download the first 100 decks in the master vault
        for i in range(pagestart,pagestop):
            response = requests.get("https://www.keyforgegame.com/api/decks/?page="+str(i)+"&links=cards&page_size=25")
            raw_data = json.loads(response.text)
            someitem = raw_data.items()
            columns = list(someitem)
            print (columns)

            with open("keyforge_scraped"+str(i)+".json","w") as data_file:
                json.dump(raw_data,data_file,indent=2)
                print ("Generating batch number %d." % i)
        conn = sqlite3.connect('keyforge.db')
        c = conn.cursor()
        c.execute("CREATE TABLE "keyforge" ( `deck number` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, `deck name` TEXT, `cardID0` INTEGER, `cardID1` INTEGER, `cardID2` INTEGER, `cardID3` INTEGER, `cardID4` INTEGER, `cardID5` INTEGER, `cardID6` INTEGER, `cardID7` INTEGER, `cardID8` INTEGER, `cardID9` INTEGER, `cardID10` INTEGER, `cardID11` INTEGER, `cardID12` INTEGER, `cardID13` INTEGER, `cardID14` INTEGER, `cardID15` INTEGER, `cardID16` INTEGER, `cardID17` INTEGER, `cardID18` INTEGER, `cardID19` INTEGER, `cardID20` INTEGER, `cardID21` INTEGER, `cardID22` INTEGER, `cardID23` INTEGER, `cardID24` INTEGER, `cardID25` INTEGER, `cardID26` INTEGER, `cardID27` INTEGER, `cardID28` INTEGER, `cardID29` INTEGER, `cardID30` INTEGER, `cardID31` INTEGER, `cardID32` INTEGER, `cardID33` INTEGER, `cardID34` INTEGER, `cardID35` INTEGER, `Wins` INTEGER, `Losses` INTEGER, `Casual wins` INTEGER, `Casual losses` INTEGER )")
        for i in raw_data:
            c.execute("insert into keyforge values (columns[1],?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",columns)
            conn.commit()

        conn.close()
        return raw_data

"""    def updateDB(raw_data):
        conn = sqlite3.connect('keyforge.db')
        c = conn.cursor()
        c.execute("CREATE TABLE IF NOT EXISTS keyforge (id varchar(3), raw_data json)")
        for i in raw_data:
            c.execute("insert into keyforge values (?,?)",[i['id'], json.dumps(raw_data)])
            conn.commit()

        conn.close()
"""


start = int(input("Enter start page: "))
stop = int(input("Enter stop page: "))
a = Keyforge()
raw_data = a.download(start,stop)
#a.updateDB(raw_data)

Вы можете увидеть беспорядок, который я создал в моем коде, попробовав много разных вещей. Я успешно загружаю объекты JSON с веб-сайта и архивирую их на свой диск, но мне не везет с базой данных sqlite.

Я создал вручную, используя графический интерфейс, таблицу, которую я хочу, но я не знаю, как заполнить такую ​​таблицу из данных JSON.

В конечном итоге я хочу запустить свой код keyforge.py, выбрать, с какой страницы, на какую страницу (каждая страница содержит 25 колод данных), которую я хочу загрузить и обработать (архивировать на диске и хранить в базе данных) и для этой базы данных будет обновляться и увеличиваться с течением времени. Очевидно, что я также обработал бы данные, чтобы передать их в свой алгоритм обучения.

Не могли бы вы, ребята, помочь мне, пожалуйста? Я застрял в дыре. Пожалуйста, помогите мне выбраться из дыры:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...