Sección "Lo más visto": vídeos y Shorts populares con contador de vistas
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TSyR5Zw5eGj6oPTRVjvP1b
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
7b4c8a4d27
commit
e8b1f765c8
@@ -14,6 +14,10 @@ CHANNEL = 'UC8gVtzB3Lqm7nnfMhMvXGxQ'
|
|||||||
# YouTube separa cada tipo en su propia lista: UULF = solo vídeos, UUSH = solo Shorts
|
# YouTube separa cada tipo en su propia lista: UULF = solo vídeos, UUSH = solo Shorts
|
||||||
FEED_VIDEOS = os.environ.get('FEED_VIDEOS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UULF{CHANNEL[2:]}')
|
FEED_VIDEOS = os.environ.get('FEED_VIDEOS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UULF{CHANNEL[2:]}')
|
||||||
FEED_SHORTS = os.environ.get('FEED_SHORTS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UUSH{CHANNEL[2:]}')
|
FEED_SHORTS = os.environ.get('FEED_SHORTS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UUSH{CHANNEL[2:]}')
|
||||||
|
FEED_POP_VIDEOS = os.environ.get('FEED_POP_VIDEOS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UULP{CHANNEL[2:]}')
|
||||||
|
FEED_POP_SHORTS = os.environ.get('FEED_POP_SHORTS_URL', f'https://www.youtube.com/feeds/videos.xml?playlist_id=UUPS{CHANNEL[2:]}')
|
||||||
|
POP_VIDEOS_SHOWN = 4
|
||||||
|
POP_SHORTS_SHOWN = 6
|
||||||
VIDEOS_SHOWN = 8 # además del destacado
|
VIDEOS_SHOWN = 8 # además del destacado
|
||||||
SHORTS_SHOWN = 12
|
SHORTS_SHOWN = 12
|
||||||
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',
|
||||||
@@ -40,16 +44,22 @@ def read_feed(url):
|
|||||||
'title': e.find('a:title', NS).text,
|
'title': e.find('a:title', NS).text,
|
||||||
'date': f'{int(d[2])} {MESES[int(d[1]) - 1]} {d[0]}',
|
'date': f'{int(d[2])} {MESES[int(d[1]) - 1]} {d[0]}',
|
||||||
'desc': e.find('m:group/m:description', NS).text or '',
|
'desc': e.find('m:group/m:description', NS).text or '',
|
||||||
|
'views': int((e.find('m:group/m:community/m:statistics', NS).attrib.get('views') or 0)
|
||||||
|
if e.find('m:group/m:community/m:statistics', NS) is not None else 0),
|
||||||
})
|
})
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
videos, shorts = read_feed(FEED_VIDEOS), read_feed(FEED_SHORTS)
|
videos, shorts = read_feed(FEED_VIDEOS), read_feed(FEED_SHORTS)
|
||||||
|
pop_videos, pop_shorts = read_feed(FEED_POP_VIDEOS), read_feed(FEED_POP_SHORTS)
|
||||||
except Exception as exc: # sin red o feed caído: se conserva la web anterior
|
except Exception as exc: # sin red o feed caído: se conserva la web anterior
|
||||||
print('feed no disponible, se mantiene index.html:', exc, file=sys.stderr)
|
print('feed no disponible, se mantiene index.html:', exc, file=sys.stderr)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
videos, shorts = videos[:VIDEOS_SHOWN + 1], shorts[:SHORTS_SHOWN]
|
videos, shorts = videos[:VIDEOS_SHOWN + 1], shorts[:SHORTS_SHOWN]
|
||||||
|
# la lista de populares de YouTube no viene ordenada por vistas: se ordena aquí
|
||||||
|
pop_videos = sorted(pop_videos, key=lambda v: -v['views'])[:POP_VIDEOS_SHOWN]
|
||||||
|
pop_shorts = sorted(pop_shorts, key=lambda v: -v['views'])[:POP_SHORTS_SHOWN]
|
||||||
|
|
||||||
|
|
||||||
def sync_thumbs(vids):
|
def sync_thumbs(vids):
|
||||||
@@ -73,10 +83,12 @@ def sync_thumbs(vids):
|
|||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
|
||||||
ok = sync_thumbs(videos + shorts)
|
ok = sync_thumbs(videos + shorts + pop_videos + pop_shorts)
|
||||||
okids = {v['id'] for v in ok}
|
okids = {v['id'] for v in ok}
|
||||||
videos = [v for v in videos if v['id'] in okids]
|
videos = [v for v in videos if v['id'] in okids]
|
||||||
shorts = [v for v in shorts if v['id'] in okids]
|
shorts = [v for v in shorts if v['id'] in okids]
|
||||||
|
pop_videos = [v for v in pop_videos if v['id'] in okids]
|
||||||
|
pop_shorts = [v for v in pop_shorts if v['id'] in okids]
|
||||||
if not videos:
|
if not videos:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
@@ -128,24 +140,30 @@ def url(v):
|
|||||||
return f"https://www.youtube.com/watch?v={v['id']}"
|
return f"https://www.youtube.com/watch?v={v['id']}"
|
||||||
|
|
||||||
|
|
||||||
def card(v, n):
|
def vistas(v):
|
||||||
|
return f"{v['views']:,}".replace(',', '.') + ' vistas' if v['views'] else ''
|
||||||
|
|
||||||
|
|
||||||
|
def card(v, n, show_views=False):
|
||||||
return f'''
|
return f'''
|
||||||
<a class="card reveal" style="--d:{(n % 3) * 70}ms" href="{url(v)}" target="_blank" rel="noopener">
|
<a class="card reveal" style="--d:{(n % 3) * 70}ms" href="{url(v)}" target="_blank" rel="noopener">
|
||||||
<span class="thumb"><img src="img/{v['id']}.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
<span class="thumb"><img src="img/{v['id']}.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
<span class="meta"><time>{esc(v['date'])}</time><strong>{esc(v['title'])}</strong></span>
|
<span class="meta"><time>{esc(v['date'])}{' · ' + vistas(v) if show_views and v['views'] else ''}</time><strong>{esc(v['title'])}</strong></span>
|
||||||
</a>'''
|
</a>'''
|
||||||
|
|
||||||
|
|
||||||
def short_card(v, n):
|
def short_card(v, n, show_views=False):
|
||||||
return f'''
|
return f'''
|
||||||
<a class="scard reveal" style="--d:{(n % 6) * 50}ms" href="https://www.youtube.com/shorts/{v['id']}" target="_blank" rel="noopener">
|
<a class="scard reveal" style="--d:{(n % 6) * 50}ms" href="https://www.youtube.com/shorts/{v['id']}" target="_blank" rel="noopener">
|
||||||
<span class="thumb"><img src="img/{v['id']}.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
<span class="thumb"><img src="img/{v['id']}.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
<span class="meta"><strong>{esc(v['title'])}</strong></span>
|
<span class="meta"><strong>{esc(v['title'])}</strong>{'<time>' + vistas(v) + '</time>' if show_views and v['views'] else ''}</span>
|
||||||
</a>'''
|
</a>'''
|
||||||
|
|
||||||
|
|
||||||
cards = ''.join(card(v, i) for i, v in enumerate(rest))
|
cards = ''.join(card(v, i) for i, v in enumerate(rest))
|
||||||
scards = ''.join(short_card(v, i) for i, v in enumerate(shorts))
|
scards = ''.join(short_card(v, i) for i, v in enumerate(shorts))
|
||||||
|
pcards = ''.join(card(v, i, True) for i, v in enumerate(pop_videos))
|
||||||
|
pscards = ''.join(short_card(v, i, True) for i, v in enumerate(pop_shorts))
|
||||||
|
|
||||||
page = f'''<!doctype html>
|
page = f'''<!doctype html>
|
||||||
<html lang="es">
|
<html lang="es">
|
||||||
@@ -223,6 +241,19 @@ page = f'''<!doctype html>
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="populares" class="wrap">
|
||||||
|
<div class="sec-head reveal">
|
||||||
|
<h2>Lo más <em>visto</em></h2>
|
||||||
|
<a class="more" href="{YT}/videos?view=0&sort=p" target="_blank" rel="noopener">Ver populares en YouTube →</a>
|
||||||
|
</div>
|
||||||
|
<h3 class="sub reveal">Vídeos</h3>
|
||||||
|
<div class="grid">{pcards}
|
||||||
|
</div>
|
||||||
|
<h3 class="sub reveal">Shorts</h3>
|
||||||
|
<div class="shorts">{pscards}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="programa" class="about wrap reveal">
|
<section id="programa" class="about wrap reveal">
|
||||||
<h2>De qué va</h2>
|
<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>
|
<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>
|
||||||
|
|||||||
@@ -154,6 +154,59 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="populares" class="wrap">
|
||||||
|
<div class="sec-head reveal">
|
||||||
|
<h2>Lo más <em>visto</em></h2>
|
||||||
|
<a class="more" href="https://www.youtube.com/@andaquenosabesna/videos?view=0&sort=p" target="_blank" rel="noopener">Ver populares en YouTube →</a>
|
||||||
|
</div>
|
||||||
|
<h3 class="sub reveal">Vídeos</h3>
|
||||||
|
<div class="grid">
|
||||||
|
<a class="card reveal" style="--d:0ms" href="https://www.youtube.com/watch?v=_-VaTy2fazY" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/_-VaTy2fazY.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><time>18 oct 2026 · 385 vistas</time><strong>DOMESTICAR ADOLESCENTES, PLANTAR TOMATES Y CONSTRUIR MINIATURAS | AQNSN Programa 3 - Galaxoide</strong></span>
|
||||||
|
</a>
|
||||||
|
<a class="card reveal" style="--d:70ms" href="https://www.youtube.com/watch?v=A2v_T2CCupo" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/A2v_T2CCupo.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><time>4 oct 2026 · 252 vistas</time><strong>¿Cómo es la vida nocturna y callejera en Egipto?</strong></span>
|
||||||
|
</a>
|
||||||
|
<a class="card reveal" style="--d:140ms" href="https://www.youtube.com/watch?v=rp9j_Ph9XvI" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/rp9j_Ph9XvI.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><time>16 sep 2026 · 219 vistas</time><strong>ISA BECERRIL NOS PRESENTA SU NOVELA "HIALURÓNICO" | AQNSN Episodio Piloto 0</strong></span>
|
||||||
|
</a>
|
||||||
|
<a class="card reveal" style="--d:0ms" href="https://www.youtube.com/watch?v=mxP0dvn2HD4" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/mxP0dvn2HD4.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><time>6 oct 2026 · 195 vistas</time><strong>Árabe formal VS Árabe de la calle, ¿qué diferencias hay?</strong></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<h3 class="sub reveal">Shorts</h3>
|
||||||
|
<div class="shorts">
|
||||||
|
<a class="scard reveal" style="--d:0ms" href="https://www.youtube.com/shorts/zJ_x4iA8OSs" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/zJ_x4iA8OSs.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><strong>El árabe que se estudia y el que se habla en las calles son diferentes</strong><time>1.547 vistas</time></span>
|
||||||
|
</a>
|
||||||
|
<a class="scard reveal" style="--d:50ms" href="https://www.youtube.com/shorts/nvF7P_S081o" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/nvF7P_S081o.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><strong>😌 "Solo vi a una persona morir sonriendo..."</strong><time>1.545 vistas</time></span>
|
||||||
|
</a>
|
||||||
|
<a class="scard reveal" style="--d:100ms" href="https://www.youtube.com/shorts/Wfq5vjJ6sQU" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/Wfq5vjJ6sQU.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><strong>"Recoger a un niño ahogado de dos años, eso..."</strong><time>1.257 vistas</time></span>
|
||||||
|
</a>
|
||||||
|
<a class="scard reveal" style="--d:150ms" href="https://www.youtube.com/shorts/XKSVhuk_lQI" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/XKSVhuk_lQI.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><strong>Poligamia en Egipto, de la antigüedad a la actualidad</strong><time>1.207 vistas</time></span>
|
||||||
|
</a>
|
||||||
|
<a class="scard reveal" style="--d:200ms" href="https://www.youtube.com/shorts/p5trUANcq_c" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/p5trUANcq_c.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><strong>El número 13 y su relación con la muerte #podcast #granada #misterio #latenight #andaquenosabesna</strong><time>1.043 vistas</time></span>
|
||||||
|
</a>
|
||||||
|
<a class="scard reveal" style="--d:250ms" href="https://www.youtube.com/shorts/7PRSukQTCwI" target="_blank" rel="noopener">
|
||||||
|
<span class="thumb"><img src="img/7PRSukQTCwI.jpg" alt="" loading="lazy" width="480" height="360"><span class="play" aria-hidden="true"></span></span>
|
||||||
|
<span class="meta"><strong>¿Cómo puede meterte miedo un Tanatopractor? 😖</strong><time>886 vistas</time></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="programa" class="about wrap reveal">
|
<section id="programa" class="about wrap reveal">
|
||||||
<h2>De qué va</h2>
|
<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>
|
<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>
|
||||||
|
|||||||
@@ -222,3 +222,7 @@ footer { margin-top: 40px; border-top: 1px solid var(--line); background: var(--
|
|||||||
.scard:hover img { transform: scale(1.06); }
|
.scard:hover img { transform: scale(1.06); }
|
||||||
.scard:hover .play { opacity: 1; }
|
.scard:hover .play { opacity: 1; }
|
||||||
.scard .play::after { width: 44px; height: 44px; }
|
.scard .play::after { width: 44px; height: 44px; }
|
||||||
|
|
||||||
|
/* lo más visto */
|
||||||
|
.sub { margin: 26px 0 14px; font-size: .8rem; letter-spacing: .22em; text-transform: uppercase; color: var(--amber); font-weight: 700; }
|
||||||
|
.scard .meta time { color: var(--muted); font-size: .8rem; }
|
||||||
|
|||||||
Reference in New Issue
Block a user