Muestra las diferencias entre dos versiones de la página.
Próxima revisión | Revisión previa | ||
ia:desinformadores [2025/01/26 06:07] anonimo creado |
ia:desinformadores [2025/02/01 03:57] (actual) anonimo |
||
---|---|---|---|
Línea 1: | Línea 1: | ||
+ | 1º Tomar como base los principales desinformadores de España, que son los que proporcionan una información más heterogenea en datos\\ | ||
+ | 2º Extraer los títulos de los vídeos,shorts y directos de youtube mediante web scrapping\\ | ||
+ | 3º Limpiarlos de caracteres extraños, tildes, artículos y preposiciones que no sirven para el propósito mediante el editor de textos sed\\ | ||
+ | 4º Hacer pruebas midiendo el grado de similitud ideológica de diferentes usuarios/seguidores respecto a dichos desinformadores\\ | ||
+ | |||
+ | |||
+ | **Extraemos los títulos de los vídeos, shorts y directos mediante web scrapping** | ||
<code python> | <code python> | ||
- | <!--- | + | """ |
MIT License | MIT License | ||
Línea 22: | Línea 29: | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | SOFTWARE. | ||
- | --> | + | """ |
from selenium import webdriver | from selenium import webdriver | ||
from selenium.webdriver.common.by import By | from selenium.webdriver.common.by import By | ||
Línea 29: | Línea 36: | ||
import time | import time | ||
- | def obtener_videos_con_scroll(url_canal): | + | def manejar_mensaje_cookies(driver): |
- | # Inicializa el navegador (asegúrate de tener el driver de Chrome o Firefox) | + | #Maneja el mensaje de cookies en YouTube. |
- | driver = webdriver.Chrome() # O webdriver.Firefox(), dependiendo de tu elección | + | try: |
+ | # Espera hasta que el botón de cookies sea visible | ||
+ | boton_cookies = WebDriverWait(driver, 10).until( | ||
+ | EC.element_to_be_clickable((By.XPATH, '//button[.//span[text()="Aceptar todo"]]')) | ||
+ | ) | ||
+ | boton_cookies.click() # Haz clic en el botón | ||
+ | print("Mensaje de cookies cerrado.") | ||
+ | except Exception as e: | ||
+ | print(f"No se encontró el mensaje de cookies o hubo un error: {e}") | ||
- | # Navega a la página del canal | + | def iniciar_driver(): |
+ | """Inicializa el navegador de Selenium.""" | ||
+ | options = webdriver.ChromeOptions() | ||
+ | options.add_argument('--headless') # Modo sin interfaz gráfica (opcional) | ||
+ | options.add_argument('--disable-gpu') | ||
+ | options.add_argument('--no-sandbox') | ||
+ | options.add_argument('--disable-dev-shm-usage') | ||
+ | return webdriver.Chrome(options=options) | ||
+ | |||
+ | def obtener_videos_con_scroll(url_canal): | ||
+ | driver = iniciar_driver() | ||
driver.get(url_canal) | driver.get(url_canal) | ||
- | time.sleep(5) # Espera un poco más para que la página cargue completamente | + | time.sleep(5) # Espera un poco para que la página cargue completamente |
- | # Simula el scroll hacia abajo para cargar más videos | + | # Manejar el mensaje de cookies |
- | SCROLL_PAUSE_TIME = 4 # Aumenta el tiempo de pausa | + | manejar_mensaje_cookies(driver) |
+ | |||
+ | SCROLL_PAUSE_TIME = 4 | ||
last_height = driver.execute_script("return document.documentElement.scrollHeight") | last_height = driver.execute_script("return document.documentElement.scrollHeight") | ||
- | | + | videos_cargados = set() |
- | videos_cargados = set() # Usamos un conjunto para evitar duplicados | + | |
while True: | while True: | ||
- | # Desplaza hacia abajo | ||
driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);") | driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);") | ||
time.sleep(SCROLL_PAUSE_TIME) | time.sleep(SCROLL_PAUSE_TIME) | ||
- | |||
- | # Calcula la nueva altura de la página y compara con la anterior | ||
- | new_height = driver.execute_script("return document.documentElement.scrollHeight") | ||
- | | ||
- | # Recoge los videos visibles usando el nuevo selector | ||
videos = driver.find_elements(By.XPATH, '//ytd-rich-grid-media//yt-formatted-string[@id="video-title"]') | videos = driver.find_elements(By.XPATH, '//ytd-rich-grid-media//yt-formatted-string[@id="video-title"]') | ||
- | | ||
- | # Depurar: Imprimir cuántos videos se encontraron en esta iteración | ||
print(f"Videos encontrados en esta iteración: {len(videos)}") | print(f"Videos encontrados en esta iteración: {len(videos)}") | ||
- | | + | |
for video in videos: | for video in videos: | ||
- | title = video.text # Usar .text para obtener el título visible | + | try: |
- | link = video.find_element(By.XPATH, './ancestor::ytd-rich-grid-media//a').get_attribute('href') # Obtener el enlace | + | title = video.text |
- | # Añade a un conjunto para evitar duplicados | + | link = video.find_element(By.XPATH, './ancestor::ytd-rich-grid-media//a').get_attribute('href') |
- | videos_cargados.add((title, link)) | + | videos_cargados.add((title, link)) |
+ | except Exception as e: | ||
+ | print(f"Error al extraer un video: {e}") | ||
- | # Si la altura no cambia, hemos llegado al final | + | new_height = driver.execute_script("return document.documentElement.scrollHeight") |
if new_height == last_height: | if new_height == last_height: | ||
break | break | ||
- | | ||
last_height = new_height | last_height = new_height | ||
driver.quit() | driver.quit() | ||
- | | ||
- | # Convertir el conjunto a lista de diccionarios | ||
lista_videos = [{'titulo': title, 'link': link} for title, link in videos_cargados] | lista_videos = [{'titulo': title, 'link': link} for title, link in videos_cargados] | ||
- | | ||
- | # Depurar: imprimir la cantidad total de videos recogidos | ||
print(f"Total de videos recogidos: {len(lista_videos)}") | print(f"Total de videos recogidos: {len(lista_videos)}") | ||
- | | ||
return lista_videos | return lista_videos | ||
def obtener_shorts_con_scroll(url_canal): | def obtener_shorts_con_scroll(url_canal): | ||
- | # Inicializa el navegador (asegúrate de tener el driver de Chrome o Firefox) | + | driver = iniciar_driver() |
- | driver = webdriver.Chrome() # O webdriver.Firefox(), dependiendo de tu elección | + | |
- | + | ||
- | # Navega a la página de Shorts del canal | + | |
driver.get(url_canal) | driver.get(url_canal) | ||
- | time.sleep(5) # Espera un poco para que la página cargue completamente | + | time.sleep(5) |
+ | |||
+ | # Manejar el mensaje de cookies | ||
+ | manejar_mensaje_cookies(driver) | ||
- | # Simula el scroll hacia abajo para cargar más shorts | ||
SCROLL_PAUSE_TIME = 3 | SCROLL_PAUSE_TIME = 3 | ||
last_height = driver.execute_script("return document.documentElement.scrollHeight") | last_height = driver.execute_script("return document.documentElement.scrollHeight") | ||
- | | + | shorts_cargados = set() |
- | shorts_cargados = set() # Usamos un conjunto para evitar duplicados | + | |
while True: | while True: | ||
- | # Desplaza hacia abajo | ||
driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);") | driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);") | ||
time.sleep(SCROLL_PAUSE_TIME) | time.sleep(SCROLL_PAUSE_TIME) | ||
- | + | shorts = driver.find_elements(By.XPATH, '//a[contains(@class, "shortsLockupViewModelHostEndpoint")]') | |
- | # Esperar explícitamente hasta que los elementos de shorts estén presentes | + | |
- | shorts = WebDriverWait(driver, 10).until( | + | |
- | EC.presence_of_all_elements_located((By.XPATH, '//a[contains(@class, "shortsLockupViewModelHostEndpoint")]')) | + | |
- | ) | + | |
- | + | ||
- | # Depurar: Imprimir cuántos shorts se encontraron en esta iteración | + | |
print(f"Shorts encontrados en esta iteración: {len(shorts)}") | print(f"Shorts encontrados en esta iteración: {len(shorts)}") | ||
for short in shorts: | for short in shorts: | ||
try: | try: | ||
- | # Extraer título y enlace de cada short | ||
title = short.get_attribute('title') | title = short.get_attribute('title') | ||
link = "https://www.youtube.com" + short.get_attribute('href') | link = "https://www.youtube.com" + short.get_attribute('href') | ||
- | # Añadir al conjunto | ||
shorts_cargados.add((title, link)) | shorts_cargados.add((title, link)) | ||
except Exception as e: | except Exception as e: | ||
print(f"Error al extraer un short: {e}") | print(f"Error al extraer un short: {e}") | ||
- | # Calcular la nueva altura y compararla con la anterior | ||
new_height = driver.execute_script("return document.documentElement.scrollHeight") | new_height = driver.execute_script("return document.documentElement.scrollHeight") | ||
if new_height == last_height: | if new_height == last_height: | ||
Línea 123: | Línea 125: | ||
driver.quit() | driver.quit() | ||
- | | ||
- | # Convertir el conjunto a lista de diccionarios | ||
lista_shorts = [{'titulo': title, 'link': link} for title, link in shorts_cargados] | lista_shorts = [{'titulo': title, 'link': link} for title, link in shorts_cargados] | ||
- | | ||
- | # Depurar: imprimir la cantidad total de shorts recogidos | ||
print(f"Total de shorts recogidos: {len(lista_shorts)}") | print(f"Total de shorts recogidos: {len(lista_shorts)}") | ||
- | | ||
return lista_shorts | return lista_shorts | ||
- | |||
- | |||
- | |||
def obtener_streams_con_scroll(url_canal): | def obtener_streams_con_scroll(url_canal): | ||
- | # Inicializa el navegador (asegúrate de tener el driver de Chrome o Firefox) | + | driver = iniciar_driver() |
- | driver = webdriver.Chrome() # O webdriver.Firefox(), dependiendo de tu elección | + | |
- | + | ||
- | # Navega a la página de Streams del canal | + | |
driver.get(url_canal) | driver.get(url_canal) | ||
- | time.sleep(4) # Espera un poco más para que la página cargue completamente | + | time.sleep(5) |
- | # Simula el scroll hacia abajo para cargar más streams | + | # Manejar el mensaje de cookies |
- | SCROLL_PAUSE_TIME = 3 # Aumenta el tiempo de pausa | + | manejar_mensaje_cookies(driver) |
+ | |||
+ | SCROLL_PAUSE_TIME = 3 | ||
last_height = driver.execute_script("return document.documentElement.scrollHeight") | last_height = driver.execute_script("return document.documentElement.scrollHeight") | ||
- | | + | streams_cargados = set() |
- | streams_cargados = set() # Usamos un conjunto para evitar duplicados | + | |
while True: | while True: | ||
- | # Desplaza hacia abajo | ||
driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);") | driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);") | ||
time.sleep(SCROLL_PAUSE_TIME) | time.sleep(SCROLL_PAUSE_TIME) | ||
- | |||
- | # Calcula la nueva altura de la página y compara con la anterior | ||
- | new_height = driver.execute_script("return document.documentElement.scrollHeight") | ||
- | | ||
- | # Recoge los streams visibles usando el nuevo selector | ||
streams = driver.find_elements(By.XPATH, '//a[@id="video-title-link"]') | streams = driver.find_elements(By.XPATH, '//a[@id="video-title-link"]') | ||
- | | ||
- | # Depurar: Imprimir cuántos streams se encontraron en esta iteración | ||
print(f"Streams encontrados en esta iteración: {len(streams)}") | print(f"Streams encontrados en esta iteración: {len(streams)}") | ||
- | | + | |
for stream in streams: | for stream in streams: | ||
- | title = stream.get_attribute('title') # Obtener el título | + | try: |
- | link = "https://www.youtube.com" + stream.get_attribute('href') # Obtener el enlace completo | + | title = stream.get_attribute('title') |
- | # Añade a un conjunto para evitar duplicados | + | link = "https://www.youtube.com" + stream.get_attribute('href') |
- | streams_cargados.add((title, link)) | + | streams_cargados.add((title, link)) |
+ | except Exception as e: | ||
+ | print(f"Error al extraer un stream: {e}") | ||
- | # Si la altura no cambia, hemos llegado al final | + | new_height = driver.execute_script("return document.documentElement.scrollHeight") |
if new_height == last_height: | if new_height == last_height: | ||
break | break | ||
- | | ||
last_height = new_height | last_height = new_height | ||
driver.quit() | driver.quit() | ||
- | | ||
- | # Convertir el conjunto a lista de diccionarios | ||
lista_streams = [{'titulo': title, 'link': link} for title, link in streams_cargados] | lista_streams = [{'titulo': title, 'link': link} for title, link in streams_cargados] | ||
- | | ||
- | # Depurar: imprimir la cantidad total de streams recogidos | ||
print(f"Total de streams recogidos: {len(lista_streams)}") | print(f"Total de streams recogidos: {len(lista_streams)}") | ||
- | | ||
return lista_streams | return lista_streams | ||
- | # URL del canal (videos, shorts, streams) | + | # URLs de ejemplo |
url_videos = "https://www.youtube.com/@geoestratego_oficial/videos" | url_videos = "https://www.youtube.com/@geoestratego_oficial/videos" | ||
url_shorts = "https://www.youtube.com/@geoestratego_oficial/shorts" | url_shorts = "https://www.youtube.com/@geoestratego_oficial/shorts" | ||
url_streams = "https://www.youtube.com/@geoestratego_oficial/streams" | url_streams = "https://www.youtube.com/@geoestratego_oficial/streams" | ||
- | # Obtener videos, shorts y streams | ||
- | titulos_shorts = obtener_shorts_con_scroll(url_shorts) | ||
titulos_videos = obtener_videos_con_scroll(url_videos) | titulos_videos = obtener_videos_con_scroll(url_videos) | ||
+ | titulos_shorts = obtener_shorts_con_scroll(url_shorts) | ||
titulos_streams = obtener_streams_con_scroll(url_streams) | titulos_streams = obtener_streams_con_scroll(url_streams) | ||
- | # Combinar resultados | + | for titulo in titulos_videos + titulos_shorts + titulos_streams: |
- | titulos_totales = titulos_videos + titulos_shorts + titulos_streams | + | |
- | + | ||
- | # Imprimir los títulos y enlaces de los videos, shorts y streams | + | |
- | for titulo in titulos_totales: | + | |
print(f"Título: {titulo['titulo']}, Enlace: {titulo['link']}") | print(f"Título: {titulo['titulo']}, Enlace: {titulo['link']}") | ||
+ | |||
| | ||
python3 raspado.py > geoestratego.txt | python3 raspado.py > geoestratego.txt | ||
</code> | </code> | ||
+ | El resultado está en éste archivo {{ :ia:desinformadores.gz |}}\\ | ||
+ | **El .txt hay que prepararlo y no lo está, ésto contienen las 4 primeras líneas** | ||
<code bash> | <code bash> | ||
- | cat geoestratego.txt | grep Título | sed '/^Título: ,/d;s/^Título: //g;s/, Enlace: .*$//g;s/[A-Z]/\L&/g;y/áéíóú/aeiou/;s/[^a-zñ ]//g;s/ \{2,\}/ /g' | + | cat geoestratego.txt | sed -n '1,4p' |
+ | Shorts encontrados en esta iteración: 192 | ||
+ | Shorts encontrados en esta iteración: 288 | ||
+ | Shorts encontrados en esta iteración: 384 | ||
+ | Shorts encontrados en esta iteración: 480 | ||
+ | </code> | ||
+ | **Limpiamos, sólo quedamos lo que sirve, los títulos, sin caracteres raros, acentos y con minúsculas todo** | ||
+ | <code bash> | ||
+ | cat geoestratego.txt | grep Título | sed '/^Título: ,/d;s/^Título: //g;s/, Enlace: .*$//g;s/[A-Z]/\L&/g;y/áéíóú/aeiou/;s/[^a-zñ0-9 ]/ /g;s/ \+/ /g' | perl -ple 's/[^a-zñÑ0-9 ]//gi' | perl -ple '$_=lc' | sed 's/ \+/ /g;s/^ //g' > geoestratego_.txt | ||
+ | </code> | ||
+ | **volvemos a limpiar**\\ | ||
+ | <code bash> | ||
+ | sed -Ei 's/ de / /g;s/ la / /g;s/ los / /g;s/ las / /g;s/ y / /g;s/ el / /g;s/ del / /g;s/ al / /g;s/ a / /g;s/^el |^la |^los |^las //g;s/^lo //g;s/ en / /g;s/ un / /g;s/^ //g;' geoestratego_.txt | ||
+ | </code> | ||
+ | **El .txt ya está preparado, éstas son las 4 primeras líneas** | ||
+ | <code bash> | ||
+ | cat geoestratego_.txt | sed -n '1,4p' | ||
+ | plan final biden para desestabilizar mundo | ||
+ | marcha militar coronel pedro baños | ||
+ | pedro baños geopolitica 2 3 | ||
+ | medios comunicacion pierden control | ||
+ | |||
+ | |||
+ | cat geoestratego_.txt | wc -l | ||
+ | 781 | ||
+ | </code> | ||
+ | Los 781 vídeos que tiene publicados\\ | ||
+ | |||
+ | **Preparación de los datos**\\ | ||
+ | <code python> | ||
+ | """ | ||
+ | MIT License | ||
+ | |||
+ | Copyright (c) 2025 wiki.acosadores.net | ||
+ | |||
+ | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ | of this software and associated documentation files (the "Software"), to deal | ||
+ | in the Software without restriction, including without limitation the rights | ||
+ | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ | copies of the Software, and to permit persons to whom the Software is | ||
+ | furnished to do so, subject to the following conditions: | ||
+ | |||
+ | The above copyright notice and this permission notice shall be included in all | ||
+ | copies or substantial portions of the Software. | ||
+ | |||
+ | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
+ | SOFTWARE. | ||
+ | """ | ||
+ | from sklearn.feature_extraction.text import TfidfVectorizer | ||
+ | from sklearn.metrics.pairwise import cosine_similarity | ||
+ | |||
+ | # 1. Leer los archivos .txt | ||
+ | with open("usuario.txt", "r", encoding="utf-8") as f1, open("geoestratego_.txt", "r", encoding="utf-8") as f2: | ||
+ | frases1 = f1.readlines() # Frases de usuario.txt | ||
+ | frases2 = f2.readlines() # Frases de geoestratego.txt | ||
+ | |||
+ | # 2. Vectorizar las frases de ambos ficheros con TF-IDF | ||
+ | vectorizer = TfidfVectorizer() | ||
+ | tfidf_matrix1 = vectorizer.fit_transform(frases1) # Matriz TF-IDF para fichero1 | ||
+ | tfidf_matrix2 = vectorizer.transform(frases2) # Transformamos fichero2 con el mismo modelo | ||
+ | |||
+ | # 3. Calcular la similitud coseno entre frases de fichero1 y fichero2 | ||
+ | cosine_sim = cosine_similarity(tfidf_matrix1, tfidf_matrix2) | ||
+ | |||
+ | # 4. Mostrar los resultados | ||
+ | print("Similitudes Coseno entre las frases de usuario.txt y geoestratego_.txt:") | ||
+ | for i in range(len(frases1)): | ||
+ | for j in range(len(frases2)): | ||
+ | print(f"Similitud entre frase {i + 1} de usuario y frase {j + 1} de geoestratego_: {cosine_sim[i, j]:.2f}") | ||
</code> | </code> |