Wygląda na to, że chcesz utworzyć tabelę z jedną kolumną o nazwie "data"
. Typ tej kolumny to JSON. (Polecam utworzenie jednej kolumny na pole, ale to zależy od Ciebie).
W tym przypadku zmienna data
(to jest odczytywane z żądania) to list
z dict
s. Jak wspomniałem w moim komentarzu, możesz zapętlić data
i wstawiaj pojedynczo jako executemany()
nie jest szybszy niż wielokrotne wywołania execute()
.
To, co zrobiłem, było następujące:
- Utwórz listę pól, na których Ci zależy.
- Zapętlaj elementy
data
- Dla każdego
item
wdata
, wyodrębnij pola domy_data
- Wywołaj
execute()
i przekażjson.dumps(my_data)
(Konwertujemy_data
zdict
do ciągu JSON)
Spróbuj tego:
#!/usr/bin/env python
import requests
import psycopg2
import json
conn = psycopg2.connect(database='NHL', user='postgres', password='postgres', host='localhost', port='5432')
req = requests.get('http://www.nhl.com/stats/rest/skaters?isAggregate=false&reportType=basic&isGame=false&reportName=skatersummary&sort=[{%22property%22:%22playerName%22,%22direction%22:%22ASC%22},{%22property%22:%22goals%22,%22direction%22:%22DESC%22},{%22property%22:%22assists%22,%22direction%22:%22DESC%22}]&cayenneExp=gameTypeId=2%20and%20seasonId%3E=20172018%20and%20seasonId%3C=20172018')
# data here is a list of dicts
data = req.json()['data']
cur = conn.cursor()
# create a table with one column of type JSON
cur.execute("CREATE TABLE t_skaters (data json);")
fields = [
'seasonId',
'playerName',
'playerFirstName',
'playerLastName',
'playerId',
'playerHeight',
'playerPositionCode',
'playerShootsCatches',
'playerBirthCity',
'playerBirthCountry',
'playerBirthStateProvince',
'playerBirthDate',
'playerDraftYear',
'playerDraftRoundNo',
'playerDraftOverallPickNo'
]
for item in data:
my_data = {field: item[field] for field in fields}
cur.execute("INSERT INTO t_skaters VALUES (%s)", (json.dumps(my_data),))
# commit changes
conn.commit()
# Close the connection
conn.close()
Nie jestem w 100% pewien, czy cała składnia postgres jest tutaj poprawna (nie mam dostępu do bazy danych PG do testowania), ale uważam, że ta logika powinna działać w przypadku tego, co próbujesz zrobić.
Aktualizacja dla oddzielnych kolumn
Możesz zmodyfikować swoją instrukcję tworzenia, aby obsługiwała wiele kolumn, ale wymagałoby to znajomości typu danych każdej kolumny. Oto kilka pseudokodów, które możesz śledzić:
# same boilerplate code from above
cur = conn.cursor()
# create a table with one column per field
cur.execute(
"""CREATE TABLE t_skaters (seasonId INTEGER, playerName VARCHAR, ...);"""
)
fields = [
'seasonId',
'playerName',
'playerFirstName',
'playerLastName',
'playerId',
'playerHeight',
'playerPositionCode',
'playerShootsCatches',
'playerBirthCity',
'playerBirthCountry',
'playerBirthStateProvince',
'playerBirthDate',
'playerDraftYear',
'playerDraftRoundNo',
'playerDraftOverallPickNo'
]
for item in data:
my_data = [item[field] for field in fields]
# need a placeholder (%s) for each variable
# refer to postgres docs on INSERT statement on how to specify order
cur.execute("INSERT INTO t_skaters VALUES (%s, %s, ...)", tuple(my_data))
# commit changes
conn.commit()
# Close the connection
conn.close()
Zastąp ...
z odpowiednimi wartościami dla Twoich danych.