<jupyter_start><jupyter_text>[![imagenes/pythonista.png](imagenes/pythonista.png)](https://pythonista.io)  Caso de uso: Análisis de tuis.  Objetivo.El objetivo de este capítulo es ejemplificar el uso de herramientas como *NLTK* y *networkX* en un ejemplo práctico.El código siguiente definirá algunas funciones capaces de:* Conectarse a la API de Twitter.* Realizar búsquedas a partir de un término y obtener el resultado en formato JSON.* Guardar y recuperar en un archivo JSON diversos tuits.* Crear una grafo que relaciona a usuarios con sus tuits.* Normalizar los textos de los tuits.* Crear una nube de palabras a partir de los textos de los tuis.  Operaciones iniciales.Se instalarán los componentes.* ```nltk``` para procesamiento de lengauje natural.* ```networkx``` para la vreaci;on de grafos.* ```twitter``` para acceder a la API de Twitter.* ```wordcloud``` es un paquete capaz de generar nubes de palabras https://amueller.github.io/word_cloud/.<jupyter_code>!pip install nltk networkx twitter wordcloud matplotlib<jupyter_output><empty_output><jupyter_text>* Se importarán las herramientas necesarias para ejecutar el código.<jupyter_code>import csv, twitter, json, nltk
from functools import reduce
import networkx as nx
from matplotlib import pyplot as plt
from wordcloud import WordCloud<jupyter_output><empty_output><jupyter_text>* Se inicializarán las credenciales.<jupyter_code>API_KEY, API_SECRET, ACCESS_TOKEN, ACCESS_SECRET = "", "", "", ""<jupyter_output><empty_output><jupyter_text>La función ```acceede_a_tw()```.* Extraerá las credenciales de la API de Twitter a partir de un achivo cuya ruta es definida como argumento.* Regresará un objeto que contiene una conexión a la API de Twitter.<jupyter_code>def accede_a_tw(fuente):
    (API_KEY,
     API_SECRET,
     ACCESS_TOKEN,
     ACCESS_SECRET) = open(
            fuente, 'r').read().splitlines()
    auth = twitter.oauth.OAuth(ACCESS_TOKEN,
                           ACCESS_SECRET,
                           API_KEY,
                           API_SECRET)
    return twitter.Twitter(auth=auth)<jupyter_output><empty_output><jupyter_text>La función ```busqueda_tw()```.Esta función realizará la búsqueda de un término mediante la API de Twitter.<jupyter_code>def busqueda_tw(tw, termino):
    return tw.search.tweets(q=termino, lang="es", count="500")["statuses"]<jupyter_output><empty_output><jupyter_text>La función ```carga_lista()```.Esta función cargará el contenido de un archivo en formato *CSV* que debe de cotener una lista de palabras separada por comas.<jupyter_code>def carga_lista(archivo):
    try:
        with open(archivo, "r") as f:
            lista = [elemento.replace(" ", "") for elemento in \
                     reduce(lambda x, y: x + y,
                            [linea for linea in csv.reader(f, dialect="unix")])]
    except IOError:
        lista = []
    return lista<jupyter_output><empty_output><jupyter_text>La función ```carga_tuits()```.Easta función abre un archivo en formato *JSON* que debe de contenr una estructura de tuits.<jupyter_code>def carga_tuits(archivo):
    try:
        f = open(archivo, "r")
        resultado = json.load(f)
    except IOError:
        resultado = []
    else:
        f.close()
    return resultado<jupyter_output><empty_output><jupyter_text>La función ```guarda_tuits()```.Esta función guardará en un archivo una estructura en formato *JSON* de un objeto tipo ```dict```.<jupyter_code>def guarda_tuits(tuits, archivo):
    with open(archivo, "w") as f:
        json.dump(tuits, f, indent=1)<jupyter_output><empty_output><jupyter_text>La función ```mezcla_tuits()```.Esta función va a mezclar una lista de elementos únicos.<jupyter_code>def mezcla_tuits(actuales, nuevos):
    for tuit in nuevos: 
        if tuit["id"] not in [actual["id"] for actual in actuales]:
            actuales.append(tuit)
    return actuales<jupyter_output><empty_output><jupyter_text>La función ```limpiar()```.Esta función permite limpiar los textos de signos de puntuación, dejanod exclusivamente palabras por medio de una expresión regular.<jupyter_code>def limpiar(texto):
    tokenizer = nltk.RegexpTokenizer(r'\w+')
    limpio = tokenizer.tokenize(texto)    
    return limpio<jupyter_output><empty_output><jupyter_text>La función ```analiza_menciones()```.Esta función permite buscar dentro de la estructura de los tuits al autor del tuit por su "nick" así como a otros tuiteros a los que hace mención el tuit. A partir de este análisis se generará un conjuto de grafos que relacionarán a usuarios de tuiter con las menciones que hacen entre si.<jupyter_code>def analiza_menciones(tuits):
    pares = []
    nodos = []
    for tuit in tuits:
        usuario = tuit["user"]["screen_name"]
        nodos.append(usuario)
        menciones = [mencion["screen_name"] for mencion in tuit["entities"]["user_mentions"]]
        for mencion in menciones:
            if mencion != [] and usuario != mencion:
                par = (usuario, mencion)
                pares.append(par)
    nodos = list(set(nodos))
    pares = list(set(pares))
    G = nx.Graph()
    G.add_nodes_from(nodos)
    G.add_edges_from(pares)
    plt.figure(figsize=(32,32))
    nx.draw_networkx(G)<jupyter_output><empty_output><jupyter_text>La función ```refina_texto()```.Esta función permite eliminar las palabras que se encuentran dentro de una de una lista de exclusión y regresará un objetos str que contendrá la totalidad de los mensajes de los tuits ingresados en minúsculas, sin signos y sin el ```termino``` que se indica.<jupyter_code>def refina_texto(tuits, lista, termino):
    lista_negra = carga_lista(lista) + [palabra.replace("@", "") for palabra in termino.split()]
    texto =""
    for i in range(0, len(lista_negra)):
        lista_negra[i] = lista_negra[i].lower()
    for tuit in tuits:
        texto += (tuit["text"] + " ")
        depurador = nltk.RegexpTokenizer(r'\w+')
    limpio = depurador.tokenize(texto)
    texto = ""
    for termino in limpio:
        termino = termino.lower()
        if  termino not in lista_negra:
            texto += (termino + " ") 
    return str(texto)<jupyter_output><empty_output><jupyter_text>La función ```nube()```.Esta función despliega una nube de palabras a partir del texto que se ingrese como argumento.<jupyter_code>def nube(texto):
    wordcloud = WordCloud().generate(texto)
    plt.imshow(wordcloud)
    plt.axis("off")
    plt.show()<jupyter_output><empty_output><jupyter_text>La función ```main()```.Esta función ejecutará las diversas funciones definidas en la notebook para:* Pedir un término de búsqueda.* Cargar un archivo con tuits previos.* Acceder a Twitter y realizar la búsqueda con el término indicado.* Mezclar los tuis viejos con los nuevos.* Guardar todos los tuits en un archivo.* Generar una imagen con un grafo de menciones.* regresar todos los textos de los tuits aplicando operaciones de limpieza.<jupyter_code>def main(archivo="tuits.json", lista="data/lista_negra.csv"): 
    termino = input("Término de búsqueda: ")
    tuits_previos = carga_tuits(archivo)
    tw = accede_a_tw("data/credenciales.txt")
    tuits_recientes = busqueda_tw(tw, termino)
    tuits = mezcla_tuits(tuits_previos, tuits_recientes)
    guarda_tuits(tuits, archivo)
    analiza_menciones(tuits)
    return refina_texto(tuits, lista, termino)
texto = main()
texto
nube(texto)
tuits = carga_tuits("tuits.json")
texto = refina_texto(tuits, "data/lista_negra.csv", "")
nube(texto)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10519983959363721, 'fraction_numerical': 0.0012030477208929287, 'mean_word_length': 4.17069799585349, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 57, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '443289', 'license': 'MIT', 'n_tokens_mistral': 2638, 'n_tokens_neox': 2646, 'n_words': 711, 'path': '14_caso_analisis_de_tuits.ipynb', 'repo_name': 'PythonistaMX/py301', 'size': '7481'}