Temas generados a partir de los hashtags de YouTube
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
"""Genera index.html a partir del feed RSS del canal (se ejecuta cada 15 min en el contenedor)."""
|
||||
import html
|
||||
import os
|
||||
import re
|
||||
import unicodedata
|
||||
from collections import Counter
|
||||
import shutil
|
||||
import sys
|
||||
import urllib.request
|
||||
@@ -11,7 +14,8 @@ from PIL import Image, ImageStat
|
||||
OUT = os.environ.get('SITE_DIR', 'public')
|
||||
FEED = os.environ.get('FEED_URL', 'https://www.youtube.com/feeds/videos.xml?channel_id=UC8gVtzB3Lqm7nnfMhMvXGxQ')
|
||||
MAX_VIDEOS = 15
|
||||
NS = {'a': 'http://www.w3.org/2005/Atom', 'y': 'http://www.youtube.com/xml/schemas/2015'}
|
||||
NS = {'a': 'http://www.w3.org/2005/Atom', 'y': 'http://www.youtube.com/xml/schemas/2015',
|
||||
'm': 'http://search.yahoo.com/mrss/'}
|
||||
MESES = ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic']
|
||||
YT = 'https://www.youtube.com/@andaquenosabesna'
|
||||
TT = 'https://www.tiktok.com/@andaquenosabesna'
|
||||
@@ -37,6 +41,7 @@ for e in root.findall('a:entry', NS)[:MAX_VIDEOS]:
|
||||
'id': e.find('y:videoId', NS).text,
|
||||
'title': e.find('a:title', NS).text,
|
||||
'date': f'{int(d[2])} {MESES[int(d[1]) - 1]} {d[0]}',
|
||||
'desc': e.find('m:group/m:description', NS).text or '',
|
||||
})
|
||||
|
||||
def sync_thumbs(vids):
|
||||
@@ -72,6 +77,44 @@ def is_short(vid):
|
||||
return ImageStat.Stat(im.crop((0, 0, int(w * .18), h))).stddev[0] < 25
|
||||
|
||||
|
||||
# --- Temas: hashtags de las descripciones de YouTube -------------------------------------------
|
||||
STOP = {'podcast', 'podcastclips', 'andaquenosabesna', 'andaquenosabesna', 'aqnsn', 'shorts', 'short', 'fyp',
|
||||
'viral', 'parati', 'galaxoide', 'youtube', 'video', 'clips'}
|
||||
LABELS = { # clave normalizada -> texto a mostrar (sinónimos incluidos)
|
||||
'egipto': 'Egipto', 'egiptomania': 'Egipto', 'educacion': 'Educación', 'arabe': 'Lengua árabe',
|
||||
'lenguas': 'Lenguas', 'religion': 'Religiones', 'religiones': 'Religiones', 'magia': 'Magia',
|
||||
'burocracia': 'Burocracia', 'poligamia': 'Poligamia', 'economia': 'Economía',
|
||||
'gastronomia': 'Gastronomía', 'comidaegipcia': 'Comida egipcia', 'robotica': 'Robótica',
|
||||
'tecnologia': 'Tecnología', 'agricultura': 'Agricultura', 'curiosidades': 'Curiosidades',
|
||||
}
|
||||
PINNED = ['Cultura granaína', 'Entrevistas'] # siempre presentes
|
||||
MAX_TOPICS = 12
|
||||
|
||||
|
||||
def norm(tag):
|
||||
t = unicodedata.normalize('NFKD', tag.lower())
|
||||
return ''.join(c for c in t if not unicodedata.combining(c))
|
||||
|
||||
|
||||
def topics(vids):
|
||||
count, raw = Counter(), {}
|
||||
for v in vids:
|
||||
seen = set()
|
||||
for tag in re.findall(r'#(\w+)', v['desc']):
|
||||
k = norm(tag)
|
||||
if k in STOP or k in seen:
|
||||
continue
|
||||
seen.add(k)
|
||||
label = LABELS.get(k) or (tag[0].upper() + tag[1:])
|
||||
raw[label] = label
|
||||
count[label] += 1
|
||||
ranked = [t for t, _ in sorted(count.items(), key=lambda kv: (-kv[1], kv[0]))]
|
||||
out = [t for t in ranked if t not in PINNED][:max(MAX_TOPICS - len(PINNED), 0)]
|
||||
return out + PINNED
|
||||
|
||||
|
||||
chips = ''.join(f'<li>{html.escape(t)}</li>' for t in topics(videos))
|
||||
|
||||
esc = html.escape
|
||||
featured, rest = videos[0], videos[1:] # el feed viene del más nuevo al más antiguo
|
||||
|
||||
@@ -157,9 +200,7 @@ page = f'''<!doctype html>
|
||||
<section id="programa" class="about wrap reveal">
|
||||
<h2>De qué va</h2>
|
||||
<p>Un programa de noche, con tertulia y sin prisa. Cada semana entra gente distinta, con su oficio y su manía, y se habla de lo que sale: de cómo se educa a un adolescente, de la vida en las calles de El Cairo, de si el árabe es tan antiguo como dicen, de qué tienen en común las religiones o de cómo se hace un truco de cartas.</p>
|
||||
<ul class="chips" aria-label="Temas">
|
||||
<li>Educación</li><li>Egipto</li><li>Lengua árabe</li><li>Religiones</li><li>Magia</li><li>Cultura granaína</li><li>Entrevistas</li>
|
||||
</ul>
|
||||
<ul class="chips" aria-label="Temas">{chips}</ul>
|
||||
</section>
|
||||
|
||||
<section id="seguir" class="follow wrap reveal">
|
||||
|
||||
Reference in New Issue
Block a user