import snscrape.modules.twitter as sntwitter
import pandas as pd
tweets_list_hastag = []
for i,tweet in enumerate(sntwitter.TwitterHashtagScraper('#SOSMarMenor since:2012-01-01 until:2022-04-20').get_items()):
tweets_list_hastag.append([tweet.id, tweet.date, tweet.content,tweet.user.username, tweet.mentionedUsers, tweet.retweetCount])
tweets_df = pd.DataFrame(tweets_list_hastag, columns=['ID','Datetime', 'Text', 'Username','mentionedUsers','nretweets'])
tweets_df
tweets_df.to_csv("mar_menor.csv", index=0)
import pandas as pd
pd.set_option('max_colwidth', None)
tweets_df = pd.read_csv("mar_menor.csv",parse_dates=['Datetime'])
tweets_df.head(5)
import re
from os.path import exists
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
stop_words = stopwords.words('spanish')
from nltk.stem import SnowballStemmer
from nltk.tokenize import ToktokTokenizer
stemmer = SnowballStemmer("spanish")
def preprocesar_texto__tokenizar():
if not exists("./preprocesado.csv"):
tweets_pre = tweets_df.copy(deep=True)
# Quitamos urls
tweets_pre['Text'] = tweets_pre['Text'].apply(lambda x: re.sub(r'(\n)|(https?:\/\/.*[^\s])', '', x))
# Quitamos hashtags
tweets_pre["Text"] = tweets_pre["Text"].apply(lambda x: re.sub(r'(?:#\w*)','',x).lower())
# Quitamos @usuarios
tweets_pre["Text"] = tweets_pre["Text"].apply(lambda x: re.sub(r'(?:@\w*)','',x).lower())
# Quitamos los números
tweets_pre["Text"] = tweets_pre["Text"].apply(lambda x: re.sub(r'\d+', '', x))
# Quitamos símbolos y emojis
tweets_pre["Text"] = tweets_pre["Text"].apply(lambda x: re.sub(r'[^\w\s]','',x).lower())
# Quitar saltos de párrafo
tweets_pre["Text"] = tweets_pre["Text"].apply(lambda x: re.sub(r'\n','',x))
# Quitamos espacios en blanco con mas de uno
tweets_pre["Text"] = tweets_pre["Text"].apply(lambda x: re.sub(r'\s{2,}','',x))
# Quitamos espacios en blanco al principio y al final
tweets_pre["Text"] = tweets_pre["Text"].apply(lambda x: re.sub(r'^\s+|\s+$','',x))
# Espacios en balnco por un solo espacio
tweets_pre["Text"] = tweets_pre["Text"].apply(lambda x: re.sub(r'\s+',' ',x))
# Tokenizamos
tokenizer = ToktokTokenizer()
tweets_pre["Tokens"] = tweets_pre.Text.apply(tokenizer.tokenize)
# tweets_pre["Tokens"] = tweets_pre["Text"].apply(lambda x: word_tokenize(x))
# stopwords Tokens
tweets_pre["Tokens"] = tweets_pre["Tokens"].apply(lambda x: [word for word in x if word not in stop_words])
# Stemming Tokens
tweets_pre["Stemming"] = tweets_pre["Tokens"].apply(lambda x: [stemmer.stem(word) for word in x])
# Guardamos los @usuarios y hashtags
tweets_pre["Usuarios_hastags"] = tweets_df["Text"].apply(lambda x: re.findall(r'(?:@\w*)',x))
tweets_pre["Usuarios_hastags"] = tweets_pre["Usuarios_hastags"] + tweets_df["Text"].apply(lambda x: re.findall(r'(?:#\w*)',x))
# Guardamos el csv
tweets_pre.to_csv("preprocesado.csv", index=0)
return pd.read_csv("preprocesado.csv", parse_dates=['Datetime'])
else:
return pd.read_csv("preprocesado.csv", parse_dates=['Datetime'])
tweets_pre = preprocesar_texto__tokenizar()
tweets_pre.head(5)
import pandas as pd
tweets_df = pd.read_csv("mar_menor.csv")
tweets_df.sort_values(by=['Datetime'], inplace=True)
tweets_df.head(10)
# Convertimos Object a Datetime
tweets_df["Datetime"] = pd.to_datetime(tweets_df["Datetime"])
tweets_df.dtypes
tweets_df["Mes"] = tweets_df['Datetime'].dt.month
tweets_df["Year"] = tweets_df['Datetime'].dt.year
tweets_df["Day"] = tweets_df['Datetime'].dt.day
tweets_df_grouped_year_month = tweets_df.groupby(["Mes","Year"])
tweets_df_grouped_year_month.size().sort_values(ascending=False)
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(rc={"figure.figsize":(12, 7)})
sns.histplot( data = tweets_df, x="Mes", hue="Year", palette="Set1", kde=True).set(xlabel="Mes", ylabel="Número de tweets")
tweets_df.plot(x="Datetime", y="nretweets", figsize=(17,8))
pd.set_option('max_colwidth', None)
tweets_df[(tweets_df["Year"] == 2021) & (tweets_df["Mes"] == 8)].sort_values(by=['nretweets'], inplace=False, ascending=False).head(10)
tweets_df[(tweets_df["Year"] == 2019) & (tweets_df["Mes"] == 10)].sort_values(by=['nretweets'], inplace=False, ascending=False).head(10)
tweets_df_grouped_user = tweets_df.groupby("Username")
tweets_df_grouped_user["Username"].unique().count()
tweets_df_grouped_user["Username"].count().sort_values(ascending=False).head(100)
tweets_df_grouped_user["Username"].count().sort_values(ascending=False).head(50).plot(kind='bar').set(xlabel="Usuario", ylabel="Número de tweets")
import snscrape.modules.twitter
for username in tweets_df_grouped_user["Username"].count().sort_values(ascending=False).head(20).iteritems():
scraper = snscrape.modules.twitter.TwitterUserScraper(username[0])
if scraper.entity:
print(username[0], "-->", scraper.entity.description)
KlimoMur -->
Miguel_Egea --> Segunda estrella a la derecha y todo recto hasta el amanecer...
😷🏥 HUSL
#ObjetivoIsaacPeral⚓🇪🇦
#SOSMarMenor💙
Último clasificado @Rutafor_Oficial 2019🏅
Mariloliana --> Nunca dejes de perseguir tus sueños. A veces se gana y a veces... se aprende.
sosmarmenorofi --> Colectivo apartidista por la defensa del Mar Menor, un legado natural, contra todas las agresiones, vengan de donde vengan. ¡Paren los vertidos! #SOSMarMenor
ono_murcia --> ➖ 🚙 y ➕ 🚴 #LaMangaDelMarMenor.
SiemprefuenT --> #SOSMarMenor
😷
Asomada al balcón del Twitter con el chorrico limón justo.
De la Murcia que paró un AVE a pipazos...🤪.
#LOBBA
MariaLucha60 --> ... Y me levanto cada día y sonrío
YanFickerRuiz --> Graduat en Química UdG @NeilYoungNYA @obrintpas @skapoficial @mazonisongs @caritathumana @cupnacional @volemacollir @standingrockst @berniesanders @ceciliocean
FAVCAC1 --> Federación de Asociaciones de Vecinos de Cartagena y Comarca “Fernando Garrido”
MenorSos --> SOS Mar Menor está formado por los colectivos: FAVCAC, ANSE, ECOLOGISTAS EN ACCIÓN, PACTO POR EL MAR MENOR Y ASOCIACIÓN DE PESCADORES DEL MAR MENOR
fonsipoder --> Lorquino,alcazareño y adversario de la mala política.🌹Licenciado en #HistoriadelArte
#SOSMarMenor
Formadora de adultos.FPE. Trabajando con NEE.
Kaquele --> Simplemente Raquel.
jaortegagarcia --> Autor Libro: Llamando a la Tierra 🌎. #EnvironmentalMedicine #Infancia y #Medioambiente @csm_aep @aepediatria #NoEsInvisible #SosMarMenor #AireLimpio
NuestroMarMenor --> Desde 2018 proponiendo SOLUCIONES creativas y sostenibles para #MarMenor #LaManga.
212Propuestas desde CEIP La Asomada(Ct)
@NuestroMarMenor Instagram y Facebook
Strikebis --> Recuerda: no eres clase media. Eres clase obrera, asalariada y endeudada. #RepúblicaYa.
NO DM. RT no respalda.
antonioh2003 --> Bajo el cielo azul de la Región de Murcia ⛅, donde unos pocos prosperan a costa de unos muchos.
EcoenAccionRM --> Somos Ecologistas en Acción de la Región Murciana. Luchamos día a día por el #MedioAmbiente. ¿Nos ayudas? #EcológicaAplastante #ÚneteAEcologistas
cjimzdi --> Soy flamenca💃💃👏👏 Tócame las palmas y verás!! Todo es mas sencillo, no lo compliques. Ayúdanos 💚💚#sosmarmenor #MarMenor
Bernardo1962 --> Músico discontinuo, director de coro.
Discontinuous musician, choir conductor.
tweets_df.sort_values(by=['nretweets'], inplace=False, ascending=False).head(10)
top_10_df = tweets_df[["Username","ID","nretweets"]].sort_values(by=['nretweets'], inplace=False, ascending=False).head(10)
top_10_df
from IPython.display import HTML
import requests
# Muestra un tuit a partir de su id y del nombre del usuario
def show_tweet(user, tweet_id):
url = 'https://twitter.com/' + user + '/status/' + str(tweet_id)
url_to_json = 'https://publish.twitter.com/oembed?url=%s' % url
response = requests.get(url_to_json)
html = response.json()["html"]
display(HTML(html))
# recorrer dataframe top_10_df
for i in range(0,10):
show_tweet(top_10_df.iloc[i]["Username"], top_10_df.iloc[i]["ID"])
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from nltk import word_tokenize
tweets_pre = pd.read_csv("preprocesado.csv", parse_dates=['Datetime'])
tweets_pre.head(2)
from nltk.tokenize import word_tokenize
from nltk.tag import pos_tag
from nltk.corpus import stopwords
stop_words = stopwords.words('spanish')
tweets_pre.dropna(inplace=True)
tweets_pre["Text"].isnull().sum()
tweets_2019 = tweets_pre[(tweets_pre["Datetime"].dt.year == 2019) & (tweets_pre["Datetime"].dt.month == 10)]
tweets_2021 = tweets_pre[(tweets_pre["Datetime"].dt.year == 2021) & (tweets_pre["Datetime"].dt.month == 8)]
def sustantivos(df):
sustantivos = []
for text in df["Text"].iteritems():
word_sentence = text[1]
post_tag_sentences = pos_tag(word_tokenize(word_sentence))
post_tag_sentences = [word for word in post_tag_sentences if word[0] not in stop_words]
for word in post_tag_sentences:
if word[1] == "NN":
sustantivos.append(word[0])
return sustantivos
sustantivos_2019 = []
sustantivos_2021 = []
sustantivos_2019 = sustantivos(tweets_2019)
sustantivos_2021 = sustantivos(tweets_2021)
tweet_tokens = ' '.join(list(sustantivos_2019))
tweets_wc = WordCloud(width = 1200, height = 900, background_color = "white").generate(tweet_tokens)
plt.figure(figsize = (8,6), facecolor = 'k')
plt.imshow(tweets_wc)
plt.axis('off')
plt.tight_layout(pad = 0)
plt.show()
tweet_tokens = ' '.join(list(sustantivos_2021))
tweets_wc = WordCloud(width = 1200, height = 900, background_color = "white").generate(tweet_tokens)
plt.figure(figsize = (8,6), facecolor = 'k')
plt.imshow(tweets_wc)
plt.axis('off')
plt.tight_layout(pad = 0)
plt.show()
tweets_pre = pd.read_csv("preprocesado.csv", parse_dates=['Datetime'])
from gensim.corpora import Dictionary
from gensim.models import LdaModel
import gensim
from nltk import word_tokenize
from nltk.tokenize import ToktokTokenizer
tweets_pre.dropna(inplace=True)
tokenizer = ToktokTokenizer()
tweets_pre["Modelo"] = tweets_pre["Text"].apply(tokenizer.tokenize)
tweets_pre["Modelo"] = tweets_pre["Modelo"].apply(lambda x: [word for word in x if word not in stop_words])
tweets_pre["Modelo"]
tweets_pre["Modelo"][5][0:4]
diccionario = Dictionary(tweets_pre["Modelo"])
len(diccionario)
corpus = [diccionario.doc2bow(token) for token in tweets_pre.Modelo]
lda = LdaModel(corpus=corpus, id2word=diccionario,
num_topics=20, random_state=42,
chunksize=200, passes=10, alpha='auto')
topicos = lda.print_topics(num_words=5, num_topics=20)
for topico in topicos:
print(topico)
(0, '0.148*"hoy" + 0.097*"día" + 0.044*"murcianos" + 0.033*"natural" + 0.032*"debe"')
(1, '0.089*"aquí" + 0.087*"ley" + 0.064*"protección" + 0.060*"recuperar" + 0.053*"dely"')
(2, '0.068*"vergüenza" + 0.053*"vez" + 0.044*"verdad" + 0.043*"van" + 0.042*"soluciones"')
(3, '0.105*"ver" + 0.054*"nitratos" + 0.052*"iniciativa" + 0.039*"parece" + 0.039*"cómo"')
(4, '0.101*"hacer" + 0.080*"problema" + 0.076*"salvar" + 0.072*"bien" + 0.060*"playa"')
(5, '0.264*"si" + 0.095*"solo" + 0.030*"aguas" + 0.030*"rambla" + 0.022*"bueno"')
(6, '0.120*"medidas" + 0.072*"laguna" + 0.069*"todas" + 0.049*"agricultores" + 0.040*"realidad"')
(7, '0.101*"ser" + 0.052*"mientras" + 0.046*"dos" + 0.040*"elde" + 0.038*"nueva"')
(8, '0.377*"mar" + 0.306*"menor" + 0.039*"puede" + 0.020*"agricultura" + 0.020*"vertidos"')
(9, '0.100*"manga" + 0.075*"ely" + 0.045*"gestión" + 0.039*"pedro" + 0.037*"lay"')
(10, '0.121*"favor" + 0.038*"después" + 0.006*"caiga" + 0.005*"olvido" + 0.000*"popular"')
(11, '0.104*"the" + 0.094*"ecosistema" + 0.085*"europa" + 0.048*"único" + 0.045*"queda"')
(12, '0.171*"murcia" + 0.121*"región" + 0.053*"mañana" + 0.044*"medio" + 0.043*"política"')
(13, '0.137*"gobierno" + 0.091*"agua" + 0.084*"va" + 0.064*"falta" + 0.059*"toda"')
(14, '0.079*"ahora" + 0.074*"pp" + 0.057*"años" + 0.056*"hace" + 0.052*"políticos"')
(15, '0.105*"así" + 0.054*"mal" + 0.045*"poder" + 0.044*"tras" + 0.042*"trabajo"')
(16, '0.168*"gracias" + 0.093*"partido" + 0.088*"q" + 0.080*"regional" + 0.058*"muchas"')
(17, '0.068*"contaminación" + 0.053*"nuevo" + 0.040*"tarde" + 0.036*"haciendo" + 0.033*"actuar"')
(18, '0.119*"defensa" + 0.076*"apoyo" + 0.074*"gran" + 0.061*"sólo" + 0.061*"naturaleza"')
(19, '0.065*"comisión" + 0.058*"recuperación" + 0.046*"posible" + 0.038*"modelo" + 0.036*"elno"')
import random
indice_tweet = random.randint(0,len(tweets_pre))
tweet = tweets_pre.iloc[indice_tweet]
print("Tweet: " + tweet.Text)
print(tweet.Modelo)
Tweet: y nosotros sin paralizar la región llevar a san esteban unas toneladas de algas y fangos y que tiemblen de ver a la sociedad murciana harta y enseñando los dientes quizá nos merezcamos un poco esto
['paralizar', 'región', 'llevar', 'san', 'esteban', 'unas', 'toneladas', 'algas', 'fangos', 'tiemblen', 'ver', 'sociedad', 'murciana', 'harta', 'enseñando', 'dientes', 'quizá', 'merezcamos']
bow_tweet = corpus[indice_tweet]
distribucion_tweet = lda[bow_tweet]
# Indices de los topicos mas significativos
dist_indices = [topico[0] for topico in lda[bow_tweet]]
# Contribución de los topicos mas significativos
dist_contrib = [topico[1] for topico in lda[bow_tweet]]
distribucion_topicos = pd.DataFrame({'Topico':dist_indices,
'Contribucion':dist_contrib })
distribucion_topicos.sort_values('Contribucion',
ascending=False, inplace=True)
ax = distribucion_topicos.plot.bar(y='Contribucion',x='Topico',
rot=0, color="orange",
title = 'Tópicos mas importantes'
'de noticia ' + str(indice_tweet))
for i in range(1, 10):
plt.figure()
plt.imshow(WordCloud(background_color='white', prefer_horizontal=1.0)
.fit_words(dict(lda.show_topic(i, 20))))
plt.axis("off")
plt.title("Tópico " + str(i))
plt.show()