3. Análisis del ecosistema
4.1. Conclusiones generales
Las posibilidades que ofrecen las tecnologías empleadas en este trabajo son enormes. El hecho de utilizar Twitter como fuente de información nos permite poner de ma- nifiesto la importancia que tiene en la actualidad las redes sociales. Poder obtener un flujo de información masivo y con una gran dinamicidad diariamente, pone en relieve el increíble potencial que presentan las herramientas de análisis de las redes sociales. Y todo ello con suma facilidad, permitiendo el filtrado de los datos para su análisis.
Dentro de la API deTwitter, existe un rango que proporciona acceso a herramientas que añaden información de geo-posicionamiento dentro de los objetos encapsula- dos en la respuesta JSON. Se tiene que tener en cuenta que para acceder a este rango se tiene que adquirir una licencia comercial. Pese a ello, la información de geo- posicionamiento que proporcionan resultaría de gran utilidad para la obtención, el filtrado y el análisis de los datos.
A pesar que no haber sido posible encontrar la manera de extraer información de los actores «publishers» y «patrocinadores» mediante Twitter, se podría obtener datos de ellos a través de otras fuentes de información. Utilizando los grafos de información junto con las ontologías, agregar estos flujos de datos de diferentes fuentes en un modelo único resulta sencillo. Ésta es una de las grandes ventajas que ofrecen estas tecnologías.
4.2.
Conclusiones personales
Este trabajo me ha permitido adentrarme en una industria que me gusta perso- nalmente, la industria de los esports. He descubierto detalles que desconocía y he aprendido a mirar a esta industria desde una perspectiva completamente nueva. Los esports crecen a pasos agigantados y eso permite que crezca la necesidad de crear herramientas de apoyo.
Exceptuando el lenguaje de programación Python, el resto de tecnologías utilizadas en este trabajo nunca las había manejado. Las posibilidades que ofrecen los grafos de
4.3. Líneas futuras
conocimiento, y mas en concretoGrakn, son muy interesantes. La capacidad de crear esquemas específicos para cada caso hace de ésta una herramienta muy potente. La
Web Semántica y las ontologías están en boga actualmente, y la similitud de Grakn
con estas tecnologías es una gran ventaja. Pero Grakn ofrece una gran documenta- ción para los usuarios que no tengan conocimiento acerca de estas tecnologías. Otra de las tecnologías es la API deTwitter. Esta red social es una de las grandes pla- taformas de la actualidad, y ha sido sorprendente conocer algunas de las posibilidad que ofrece así como la gran cantidad de información que se puede obtener de ella. Al nunca haber utilizado esta tecnología, el aprendizaje ha sido mediante «prueba y error». Y a medida que se iba avanzando durante el trabajo se descubrían nuevas funciones y formas de obtener información. Algunas no se han podido implementar, y hablaremos de estas posibilidades en las líneas futuras.
En definitiva estoy satisfecho con el trabajo realizado, pero me quedo con ganas de realizar una siguiente iteración e intentar añadir más información al grafo e informa- ción más depurada. Aun así creo que he podido asentar unas bases de conocimiento para poder avanzar sobre este trabajo.
4.3.
Líneas futuras
Al mirar atrás al trabajo aparecen muchas ideas que no se han podido implementar. Aquí comentaré esas ideas sin un orden de importancia específico.
• Durante la parte final de implementación, he descubierto que al crear la rela- ción entre organizadores y equipo estaba eliminando algunas de esas relaciones por evitar añadir duplicados. Esta relación sería mucho más interesante si se pudiera ver la existencia de equipos que participan de varias ligas.
• No se ha encontrado una manera de recuperar la información de las relaciones entre patrocinadores con el resto de actores del ecosistema. Completar estas relaciones sería muy importante para añadir un actor fundamental como son los patrocinadores.
• Añadir de alguna manera el juego en el que participan cada jugador, cada equipo y las ligas que organizan los distintos organizadores. Sería una relación compleja pero creo que la información se puede extraer deTwitter, quizás en combinación con otras fuentes de información, gracias a que las ontologías permiten esta integración y combinación de fuentes.
• Añadir información adicional a los distintos actores. En este trabajo solo se ha añadido el nombre de las entidades. Resultaría interesante añadir otro campos como nacionalidad de los jugadores y de los equipos (medianteTwitter creo que resultaría difícil). Una más fácil podría ser el número de seguidores en Twit- ter, también en unión con otras fuentes, de entre las que se ha presentado al comienzo del trabajo, durante la identificación de los actores.
• Se ha descubierto que algunos equipos tienen varios perfiles de Twitter, uno para cada uno de los equipos dentro de sus estructuras (e.g. Mad Lions). Unifi- carlos bajo una misma entidad daría más peso al grafo y reportaría información más depurada.
[1] S.L. Kent, The Ultimate History of Video Games: Volume Two: from Pong to Poke- mon and beyond... the story behind the craze that touched our lives and changed the world. Three Rivers Press, 2010.
[2] Jerkrot, Henrik Nel, and Shahin Adl Zarrabi.Value creation and appropriation in the esports industry. MS thesis. 2016.
[3] The Esports Observer, An Introduction to the Esports Ecosystem. [Online] Dispo-
nible: https://esportsobserver.com/the-esports-eco-system/
[4] P. Jurkic, Esports Ecosystem | Key Components of Competitive Gaming,
Agosto 10, 2019. [Online] Disponible: https://www.esportstalk.com/blog/
esports-ecosystem-key-components-competitive-33087/
[5] Asociación Española de Videojuegos, Libro blanco de los esports en España,
Mayo 2018. [Online] Disponible: http://www.aevi.org.es/web/wp-content/
uploads/2018/05/ES_libroblanco_online.pdf
[6] Newzoo, Top 25 Public Companies by Game Revenues, 2019.
[Online] Disponible: https://newzoo.com/insights/rankings/
top-25-companies-game-revenues/
[7] Gambling Sites, Major esports Game Developers and Publishers in 2018.
[Online] Disponible: https://www.gamblingsites.com/esports-betting/
game-developers-publishers/
[8] Newzoo,Most Watch Games on Twitch, Marzo 2020. [Online] Disponible: https: //newzoo.com/insights/rankings/top-games-twitch/
[9] Antevenio, Principales patrocinadores de esports en España, Septiembre
4, 2019. [Online] Disponible: https://www.antevenio.com/blog/2019/09/
principales-patrocinadores-de-esports-en-espana/
[10] G2,Creators.https://g2esports.com/teams/creators/
[11] Gen.G,Content Creators.https://geng.gg/blogs/content-creators
[12] Riot Games, Partner Program. https://partners.leagueoflegends.com/en_
US/
[13] R. Martín, Los cinco mejores jugadores españoles de eSports que están en mo- do Leyenda, Mayo 31, 2019. [Online] Disponible: https://www.marca.com/ esports/2019/05/31/5cf14606ca47419d708b459d.html
BIBLIOGRAFÍA [14] A. Tejero, I. Pau and G. León, Analysis of the Dynamism in University-Driven Innovation Ecosystems Through the Assessment of Entrepreneurship Role, inIEEE
Access, vol. 7, pp. 89869-89885, 2019.
[15] J. Clement, Statista, Twitter: number of monthly active users 2010-2019, Agos-
to 14, 2019. [Online] Disponible: https://www.statista.com/statistics/
282087/number-of-monthly-active-twitter-users/
[16] R.Chadha, 2019 Gaming on Twitter, Enero 7, 2020. [Online] Dis-
ponible: https://blog.twitter.com/en_us/topics/events/2019/
2019-gaming-on-twitter.html
[17] Esports Bureau, ESL presenta en MGE el “II Estudio de audiencia de esports de España” con datos reveladores sobre el sector, Octubre 27, 2017. [Online]
Disponible: https://www.esportsbureau.com/esl-estudio-esports/
[18] Twitter, User Object, Twitter Developers. [Online] Disponible: https:
//developer.twitter.com/en/docs/tweets/data-dictionary/overview/ user-object
[19] tweepy, Cursor Tutorial. [Online] Disponible: http://docs.tweepy.org/en/
latest/cursor_tutorial.html
[20] SproutSocial, What is a Twitter handle?. [Online] Disponible: https://
sproutsocial.com/glossary/twitter-handle/
[21] Grakn Labs, Migrating CSV, JSON and XML Data with Client Pyt-
hon. [Online] Disponible: https://dev.grakn.ai/docs/examples/
phone-calls-migration-python
[22] Twitter, About replies and mentions. [Online] Disponible: https://help.
twitter.com/en/using-twitter/mentions-and-replies
[23] S. Perez, Twitter officially expands its character count to 280 starting today, No-
viembre 7, 2017. [Online] Disponible: https://techcrunch.com/2017/11/07/
twitter-officially-expands-its-character-count-to-280-starting-today/
[24] Grakn Labs,Graql Queries. [Online] Disponible:https://dev.grakn.ai/docs/ query/overview
.1.
search_twitter.py
1 from searchtweets import ResultStream, gen_rule_payload, load_credentials, collect_results
2 import json
3 import csv
4 5 ’’’
6 Se cargan las credenciales necesarias para
7 realizar las llamadas premium. Para cambiar
8 entre distintos endpoints, hay que modificar
9 el campo yaml_key.
10 ’’’
11 premium_search_args = load_credentials("twitter_credentials.yaml", yaml_key=" fullarchive_search_api", env_overwrite=False)
12
13 teamsFile = open(’teams.csv’, ’a’)
14 teamsWriter = csv.writer(teamsFile)
15
16 with open("organizadores.json", "r") as org:
17 organizadores = json.load(org)
18
19 for orgs in organizadores[’organizadores’]:
20
21 ’’’ Rule para 30-day endpoint ’’’
22 # rule = gen_rule_payload("equipos from:" + orgs)
23
24 ’’’ Rule para Full Archive endpoint ’’’
25 rule = gen_rule_payload("equipos from:" + orgs, from_date="2019-12-01", to_date=" 2020-05-25", results_per_call=100)
26
27 ’’’ El ResultStream se utiliza necesariamente para 30-day ’’’
28 # rs = ResultStream(rule_payload=rule, max_results=100, **premium_search_args)
29
30 ’’’ collect_results se utiliza necesariamente para Full Archive ’’’
31 tweets = collect_results(rule, max_results=100, result_stream_args=premium_search_args )
32
33 ’’’ rs = ResultStream. Utilizar esta entrada de bucle para 30-day ’’’
34 # for tweet in rs.stream():
35
36 ’’’ Esta entrada de bucle se utiliza para Full Archive ’’’
37 for tweet in tweets:
38
39 ’’’
40 Para tener todos los campos del objeto Tweet
41 json.dump(tweet, f) 42 f.write(’\n’) 43 ’’’ 44 45 id_str = tweet[’user’][’id_str’] 46 name = tweet[’user’][’name’] 47 screen_name = tweet[’user’][’screen_name’]
.2. get_players.py
48 ’’’
49 Dependiendo del tamaño del tweet hay unos campos u otros.
50 Si el tweet es menor a 140 caracteres, no recibimos el
51 campo ’extended_tweet’. Se puede consultar el campo ’truncated’
52 para saber si es un tweet extendido o no.
53 truncated == False. Tweet NO extendido.
54 truncated == True. Tweet extendido.
55 ’’’ 56 if tweet[’truncated’] == False: 57 user_mentions = tweet[’entities’][’user_mentions’] 58 else: 59 user_mentions = tweet[’extended_tweet’][’entities’][’user_mentions’] 60 ’’’
61 Puede suceder que no haya usuarios mencionados en el tweet,
62 en ese caso simplemente desechamos el tweet.
63 ’’’
64 if user_mentions:
65 for user in user_mentions:
66 teamsWriter.writerow([id_str, name, screen_name, user[’id_str’ ], user[’name’], user[’screen_name’]]) 67 else: 68 pass 69 70 teamsFile.close()
.2.
get_players.py
1 import tweepy 2 import json 3 import csv 45 with open("twitter_credentials.json", "r") as file:
6 creds = json.load(file)
7 with open("keywords_players.json", "r") as kfile:
8 kwords = json.load(kfile)
9
10 auth = tweepy.OAuthHandler(creds[’CONSUMER_KEY’], creds[’CONSUMER_SECRET’])
11 auth.set_access_token(creds[’ACCESS_TOKEN’], creds[’ACCESS_SECRET’])
12
13 teamsFile = open(’teams_without_dup.csv’, ’r’)
14 playerFile = open(’players.csv’, ’a’)
15 teamsReader = csv.reader(teamsFile)
16 playersWriter = csv.writer(playerFile)
17
18 user_objs = []
19 api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)
20
21 for row in teamsReader:
22 if row[6] == ’user_screen_name’: continue
23
24 for word in kwords[’keywords’]:
25 query = word + ’ ’ + row[6] + ’ -ex -former -coach’
26 for page in tweepy.Cursor(api.search_users, q=query).pages():
27 for user_objs in page:
28
29 id_str = user_objs._json[’id_str’]
30 name = user_objs._json[’name’]
31 screen_name = user_objs._json[’screen_name’]
32 playersWriter.writerow([row[6], id_str, name, screen_name])
33
34 playerFile.close()
.3.
get_streamers.py
1 import tweepy2 import json
3 import csv
4
5 with open("twitter_credentials.json", "r") as file:
6 creds = json.load(file)
7 with open("keywords_streamers.json", "r") as kfile:
8 kwords = json.load(kfile)
9
10 auth = tweepy.OAuthHandler(creds[’CONSUMER_KEY’], creds[’CONSUMER_SECRET’])
11 auth.set_access_token(creds[’ACCESS_TOKEN’], creds[’ACCESS_SECRET’])
12
13 teamsFile = open(’just_teams.csv’, ’r’)
14 streamerFile = open(’streamers.csv’, ’a’)
15 teamsReader = csv.reader(teamsFile)
16 streamerWriter = csv.writer(streamerFile)
17
18 user_objs = []
19 api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)
20
21 for row in teamsReader:
22 if row[2] == ’team_screen_name’: continue
23
24 for word in kwords[’keywords’]:
25 query = word + ’ ’ + row[2] + ’ -player -jugador -jugadora -coach’
26 for page in tweepy.Cursor(api.search_users, q=query).pages():
27 for user_objs in page:
28
29 id_str = user_objs._json[’id_str’]
30 name = user_objs._json[’name’]
31 screen_name = user_objs._json[’screen_name’]
32 streamerWriter.writerow([row[2], id_str, name, screen_name])
33
34 streamerFile.close()
35 teamsFile.close()
.4.
migrate.py
1 from grakn.client import GraknClient
2 import csv
3
4 def build_esports_graph(inputs):
5 with GraknClient(uri="localhost:48555") as client:
6 with client.session(keyspace = "esports_v2") as session:
7 for input in inputs:
8 print("Cargando desde [" + input["data_path"] + "] en Grakn... ")
9 load_data_into_grakn(input, session)
10
11 def load_data_into_grakn(input, session):
12 items = parse_data_to_dictonaries(input)
13
14 for item in items:
15 with session.transaction().write() as transaction:
16 graql_insert_query = input["template"](item)
17 print("Ejecutando Grakn Query: " + graql_insert_query)
18 transaction.query(graql_insert_query)
19 transaction.commit()
20 print("\nInsertados " + str(len(items)) + " items desde [ " + input["data_path"] + "] en Grakn. \n")
.4. migrate.py
22 def teams_template(team):
23 return ’insert $equipo isa equipo, has nombre "’ + team["team_screen_name"] + ’";’
24
25 def players_template(player):
26 return ’insert $jugador isa jugador, has nombre "’ + player["player_screen_name"] + ’ ";’
27
28 def orgs_template(orgs):
29 return ’insert $org isa organizador, has nombre "’ + orgs["org_screen_name"] + ’";’
30
31 def streamer_template(streamer):
32 return ’insert $streamer isa creador, has nombre "’ + streamer["streamer_screen_name"] + ’";’
33
34 def empleo_template(empleo):
35 graql_insert_query = ’match $equipo isa equipo, has nombre "’ + empleo[" team_screen_name"] + ’";’
36 graql_insert_query += ’ $jugador isa jugador, has nombre "’ + empleo[" player_screen_name"] +’";’
37 graql_insert_query += ’ insert (team: $equipo, player: $jugador) isa empleo_jugadores; ’
38 return graql_insert_query
39
40 def creador_template(empleo):
41 graql_insert_query = ’match $equipo isa equipo, has nombre "’ + empleo[" team_screen_name"] + ’";’
42 graql_insert_query += ’ $creador isa creador, has nombre "’ + empleo[" streamer_screen_name"] +’";’
43 graql_insert_query += ’ insert (team: $equipo, streamer: $creador) isa empleo_creadores;’
44 return graql_insert_query
45
46 def liga_template(liga):
47 graql_insert_query = ’match $equipo isa equipo, has nombre "’ + liga["team_screen_name "] + ’";’
48 graql_insert_query += ’ $org isa organizador, has nombre "’ + liga["org_screen_name"] +’";’
49 graql_insert_query += ’ insert (participante: $equipo, org: $org) isa liga;’
50 return graql_insert_query
51
52 def parse_data_to_dictonaries(input):
53 items = []
54 with open(input["data_path"] + ".csv") as data:
55 for row in csv.DictReader(data, skipinitialspace = True):
56 item = { key: value for key, value in row.items() }
57 items.append(item) 58 return items 59 60 inputs = [ 61 { 62 "data_path": "./just_teams", 63 "template": teams_template 64 }, 65 { 66 "data_path": "./players_without_dup", 67 "template": players_template 68 }, 69 { 70 "data_path": "./orgs_without_dup", 71 "template": orgs_template 72 }, 73 { 74 "data_path": "./streamers_without_dup", 75 "template": streamer_template 76 }, 77 { 78 "data_path": "./players_without_dup", 79 "template": empleo_template 80 }, 81 {
82 "data_path": "./orgs_teams", 83 "template": liga_template 84 }, 85 { 86 "data_path": "./streamers_without_dup", 87 "template": creador_template 88 } 89 ] 90 91 build_esports_graph(inputs=inputs)
Este documento esta firmado por
Firmante CN=tfgm.fi.upm.es, OU=CCFI, O=Facultad de Informatica - UPM, C=ES
Fecha/Hora Sat Jun 06 10:36:03 CEST 2020
Emisor del
Certificado [email protected], CN=CA Facultad deInformatica, O=Facultad de Informatica - UPM, C=ES
Numero de Serie 630
Metodo urn:adobe.com:Adobe.PPKLite:adbe.pkcs7.sha1 (Adobe Signature)