Skip to content

Instantly share code, notes, and snippets.

@IoTeacher
Last active May 29, 2026 00:54
Show Gist options
  • Select an option

  • Save IoTeacher/a57e0af3d02462cd237ca99b3c13643a to your computer and use it in GitHub Desktop.

Select an option

Save IoTeacher/a57e0af3d02462cd237ca99b3c13643a to your computer and use it in GitHub Desktop.
Cowork: Extracción de Google Classroom a PDF — Master prompt + script JS + proceso completo

📚 Cowork: Extracción de Google Classroom a PDF

Propósito: Prompt maestro para que Claude (en modo Cowork) extraiga automáticamente el contenido completo de cursos de Google Classroom y genere un PDF por curso. Incluye el muro de anuncios, listado de actividades por unidad, y las descripciones/instrucciones nivel 0 de cada actividad (sin seguir links externos).

Herramientas requeridas: Claude Cowork + Chrome MCP (extensión Claude in Chrome activa) + cuenta Google con acceso a los cursos.


MASTER PROMPT — Extracción Google Classroom → PDF

Tengo N cursos en Google Classroom y quiero un PDF por curso con 3 niveles de contenido:

1. MURO (stream): fecha, texto del anuncio, nombres de archivos adjuntos
2. ACTIVIDADES: lista por unidad/tema con nombre de cada actividad
3. DESCRIPCIÓN NIVEL 0: el texto de instrucciones dentro de cada actividad 
   (lo que aparece al abrir "Editar" — NO seguir links externos, eso es nivel 1)

Mis cursos son:
- Nombre: [NOMBRE]  |  courseId: [ID]
- (repetir para cada curso)

Para encontrar el courseId: abre el curso en Classroom, 
la URL es classroom.google.com/u/0/c/[courseId]

Script JS para extracción de descripciones

Pegar en javascript_tool del Chrome MCP estando en la página /w/[courseId]/t/all:

const sleep = ms => new Promise(r => setTimeout(r, ms));
async function extractAll() {
  window._results = []; window._extractionDone = false;
  const actBtns = [...document.querySelectorAll('button')].filter(b => {
    const label = b.getAttribute('aria-label') || '';
    return label.startsWith('Opciones de') && !label.startsWith('Opciones de temas para');
  });
  for (let i = 0; i < actBtns.length; i++) {
    const btn = actBtns[i];
    const name = btn.getAttribute('aria-label')
      .replace(/^Opciones de (la tarea|del material|de la pregunta)\s*/i, '').trim();
    try {
      btn.scrollIntoView({behavior:'instant', block:'center'}); await sleep(300);
      btn.click(); await sleep(500);
      const editarItem = [...document.querySelectorAll('[role="menuitem"]')]
        .find(el => el.textContent?.trim() === 'Editar');
      if (!editarItem) {
        window._results.push({name, description:'[no Editar]'});
        document.dispatchEvent(new KeyboardEvent('keydown',{key:'Escape',bubbles:true}));
        await sleep(300); continue;
      }
      editarItem.click(); await sleep(1500);
      const editors = [...document.querySelectorAll('textarea,[contenteditable="true"],[role="textbox"]')];
      const texts = editors.map(e => e.textContent?.trim()).filter(t => t && t.length > 2);
      const description = texts.length > 1 ? texts[1] : (texts[0] || '');
      window._results.push({
        name,
        description: description.replace(/https?:\/\/\S+/g, '[ENLACE]')
      });
      const closeBtn = [...document.querySelectorAll('button')]
        .find(b => (b.getAttribute('aria-label') || '').toLowerCase().includes('cerrar'));
      if (closeBtn) closeBtn.click(); else history.back();
      await sleep(1000);
    } catch(e) {
      window._results.push({name, description:'[error:' + e.message + ']'});
      await sleep(500);
    }
    window._progress = i+1 + '/' + actBtns.length;
  }
  window._extractionDone = true;
}
extractAll();

Leer resultados en batches

window._results.slice(0,3).map(r=>r.name+'|||'+r.description).join('\n---\n')

Verificar progreso

window._progress + ' | done: ' + window._extractionDone

Proceso completo

  1. Navegar a classroom.google.com/w/[courseId]/t/all por cada curso
  2. Expandir actividades si hay botón "Ver más publicaciones"
  3. Ejecutar el script JS con javascript_tool
  4. Leer resultados en batches de 3-4 hasta terminar
  5. Guardar en courseN_data.txt con formato ##NombreActividad\nDescripcion\n---
  6. Generar PDFs con Python reportlab (Platypus)

Bloqueos conocidos y soluciones

Problema Causa Solución
BLOCKED: Cookie/query string data JSON con URLs .replace(/https?://\S+/g,'[ENLACE]') antes de retornar
BLOCKED: Base64 encoded data btoa() bloqueado No usar base64, leer en batches
CDP timeout (45s) navigator.clipboard.writeText() async Usar document.execCommand('copy')
Form Editar no cierra con Escape Pantalla completa, no modal Buscar botón aria-label "cerrar"
Salida truncada Tool limita ~1500 chars Batches de 3-4 items máximo

Formato PDF recomendado (reportlab)

from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, HRFlowable
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors

styles.add(ParagraphStyle('ActivityItem',
    fontSize=10, fontName='Helvetica-Bold', spaceAfter=1, spaceBefore=6))
styles.add(ParagraphStyle('ActivityDesc',
    fontSize=9, fontName='Helvetica', leftIndent=28, leading=13,
    textColor=colors.HexColor('#455a64')))

Nota: Los courseId se obtienen de la URL del curso. Ejemplo: classroom.google.com/u/0/c/ODQxMTcxODYxMTk5 → courseId = ODQxMTcxODYxMTk5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment