123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- import pprint
- import numpy as np
- import pandas as pd
- from graphql_client import GraphQLClient
- pp = pprint.PrettyPrinter(indent=2)
- def myprint(data, show = True):
- if show:
- pp.pprint(data)
- class AnilistApi:
- # Le client graphQL pour effectuer les requetes
- graphql = GraphQLClient('https://graphql.anilist.co')
- # La derniere query graphql
- query = None
- # Le derniere utilisateur
- user = None
-
- def findUser(self, username, returnSelf = True):
- """Cherche un utilisateur passé en paramètre pour les futures appels à l'API"""
- request = '''
- query ($name: String) {
- User(name: $name) {
- id
- mediaListOptions {
- scoreFormat
- }
- }
- }
- '''
- variables = {
- 'name': username
- }
- # Création query
- self.query = self.graphql.query(request, variables)
- # Execution query
- result = self.query.execute().get()
- if(self.graphql.isError(result)):
- result = None
- self.user = result
- # Retour
- if returnSelf:
- return self
- return result != None
-
- def getUserAnimeList(self):
- """Retourne la liste d'anime complétés de l'utilisateur (ou None en cas de problème)"""
- if(self.user == None):
- return None
- request = '''
- query ($id: Int) {
- MediaListCollection (userId: $id, type: ANIME, status: COMPLETED) {
- lists {
- entries {
- score
- media {
- id
- title {
- userPreferred
- }
- averageScore
- format
- episodes
- duration
- popularity
- source
- tags {
- name
- }
- genres
- }
- }
- }
- }
- }
- '''
- variables = {
- 'id': self.user['User']['id']
- }
- # Création query
- self.query = self.graphql.query(request, variables)
- # Execution query
- result = self.query.execute().get()
- if(self.graphql.isError(result)):
- return None
- return UserAnimeList(result['MediaListCollection']['lists'][0]['entries'], self.user['User']['mediaListOptions']['scoreFormat'])
-
- def fetchAnimeList(self, query, page = 0, element = 50):
- if query.object != 'Media':
- raise ValueError('bad query type: ' + query.object)
- # Requete graphql
- request = '''
- query ($page: Int, $element: Int, ${def}) {
- Page(page: $page, perPage: $element) {
- media(${param}) {
- id
- title {
- userPreferred
- }
- averageScore
- format
- episodes
- duration
- popularity
- source
- tags {
- name
- }
- genres
- }
- }
- }
- '''
- # Recupération info query et application
- definition, parameter, variable = query.get()
- request = request.replace('${def}', definition)
- request = request.replace('${param}', parameter)
- variable['page'] = page
- variable['element'] = element
- # Création query
- self.query = self.graphql.query(request, variable)
- # Execution query
- result = self.query.execute().get()
- if(self.graphql.isError(result)):
- return None
- # Préparation pour creation objet AnimeList
- data = []
- for i in range(0, len(result['Page']['media'])):
- data.append({'media': result['Page']['media'][i]})
- return UserAnimeList(data)
-
- def iterateAnimeListFetch(self, query, nb, element):
- for i in range (0, nb):
- yield self.fetchAnimeList(query, i, element)
-
- class AnilistQuery:
- __declaration = ''
- __parameter = ''
- __variable = {}
-
- # Constructeur
- def __init__(self, obj = 'Media'):
- self.object = obj
- self.reset()
-
- def scoreGreaterThan(self, value):
- if(self.__variable.get('sgt') == None):
- self.__declaration += ',$sgt: Int'
- self.__parameter += ',averageScore_greater: $sgt'
- self.__variable['sgt'] = round(value)
- return self
-
- def popularityGreaterThan(self, value):
- if(self.__variable.get('pgt') == None):
- self.__declaration += ',$pgt: Int'
- self.__parameter += ',popularity_greater: $pgt'
- self.__variable['pgt'] = round(value)
- return self
-
- def episodeBetween(self, minValue, maxValue):
- if(self.__variable.get('egt') == None):
- self.__declaration += ',$egt: Int'
- self.__parameter += ',episodes_greater: $egt'
- self.__variable['egt'] = round(minValue)
- if(self.__variable.get('elt') == None):
- self.__declaration += ',$elt: Int'
- self.__parameter += ',episodes_lesser: $elt'
- self.__variable['elt'] = round(maxValue)
- return self
-
- def durationBetween(self, minValue, maxValue):
- if(self.__variable.get('dgt') == None):
- self.__declaration += ',$dgt: Int'
- self.__parameter += ',duration_greater: $dgt'
- self.__variable['dgt'] = round(minValue)
- if(self.__variable.get('dlt') == None):
- self.__declaration += ',$dlt: Int'
- self.__parameter += ',duration_lesser: $dlt'
- self.__variable['dlt'] = round(maxValue)
- return self
-
- def formatIn(self, value):
- if(self.__variable.get('fin') == None):
- self.__declaration += ',$fin: [MediaFormat]'
- self.__parameter += ',format_in: $fin'
- self.__variable['fin'] = value
- return self
-
- def sourceIn(self, value):
- if(self.__variable.get('sin') == None):
- self.__declaration += ',$sin: [MediaSource]'
- self.__parameter += ',source_in: $sin'
- self.__variable['sin'] = value
- return self
-
- def tagIn(self, value):
- if(self.__variable.get('tin') == None):
- self.__declaration += ',$tin: [String]'
- self.__parameter += ',tag_in: $tin'
- self.__variable['tin'] = value
- return self
-
- def genreIn(self, value):
- if(self.__variable.get('gin') == None):
- self.__declaration += ',$gin: [String]'
- self.__parameter += ',genre_in: $gin'
- self.__variable['gin'] = value
- return self
-
- def get(self):
- return self.__declaration.strip(','), self.__parameter.strip(','), self.__variable
-
- def reset(self):
- self.__declaration = ''
- self.__parameter = ''
- self.__variable = {}
-
- def __str__(self):
- return 'Declaration: ' + self.__declaration.strip(',') + '\nParameter: ' + self.__parameter.strip(',') + '\nVariable: ' + pp.pformat(self.__variable)
- class UserAnimeList:
- data = []
-
- # Constructeur, met en forme les données
- def __init__(self, entries, userScoreType = None):
- self.data = []
- for entry in entries:
- media = entry['media']
- d = {
- 'id': media['id'],
- 'title': media['title']['userPreferred'],
- 'score': media['averageScore'],
- 'popularity': media['popularity'],
- 'format': media['format'],
- 'episode': media['episodes'],
- 'duration': media['duration'],
- 'source': media['source']
- }
- # Ajout score de l'utilisateur si present
- if userScoreType != None and entry.get('score') != None:
- d['userScore'] = self.__formatScore(entry['score'], userScoreType)
- # Ajout tag (3 max)
- end = 3 if len(media['tags']) > 3 else len(media['tags'])
- for i in range(0, 3):
- if(i < end):
- d['tag' + str(i + 1)] = media['tags'][i]['name']
- else:
- d['tag' + str(i + 1)] = 'None'
- # Ajout genre (5 max)
- end = 5 if len(media['genres']) > 5 else len(media['genres'])
- for i in range(0, 5):
- if(i < end):
- d['genre' + str(i + 1)] = media['genres'][i]
- else:
- d['genre' + str(i + 1)] = 'None'
- # Ajoute la ligne aux données
- self.data.append(d)
-
- def toDataFrame(self, dummies = False):
- df = pd.DataFrame(self.data)
- if dummies and len(self.data) > 0:
- df = self.__multipleColDummies(df, 'tag', 3)
- df = self.__multipleColDummies(df, 'genre', 5)
- df = pd.get_dummies(df, columns=['format', 'source'])
- return df
-
- def __formatScore(self, score, scoreType):
- if scoreType == 'POINT_10_DECIMAL' or scoreType == 'POINT_10':
- return 10 * score
- elif scoreType == 'POINT_5':
- return 20 * score
- elif scoreType == 'POINT_3':
- return (score / 3) * 100
- else:
- return score
-
- def __multipleColDummies(self, df, colname, num):
- # Recherche de toutes les valeurs possibles
- values = []
- for i in range(1, num + 1):
- d = df[colname + str(i)]
- for item in d.iteritems():
- if not(item[1] in values and item[1] != 'None'):
- values.append(item[1])
- # Creation colonne dans la dataframe
- for val in values:
- df[colname + '_' + val.replace(' ', '_')] = 0
- # Remplissage des colonnes
- newDf = []
- for row in df.iterrows():
- row = pd.Series(row[1])
- for i in range(1, num + 1):
- if row[colname + str(i)] != None:
- name = row[colname + str(i)].replace(' ', '_')
- row[colname + '_' + name] = 1
- newDf.append(row)
- df = pd.DataFrame(newDf)
- # Suppr ancienne colonne
- for i in range(1, num + 1):
- df = df.drop(colname + str(i), axis = 1)
- return df
|