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.
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]
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();window._results.slice(0,3).map(r=>r.name+'|||'+r.description).join('\n---\n')window._progress + ' | done: ' + window._extractionDone- Navegar a classroom.google.com/w/[courseId]/t/all por cada curso
- Expandir actividades si hay botón "Ver más publicaciones"
- Ejecutar el script JS con javascript_tool
- Leer resultados en batches de 3-4 hasta terminar
- Guardar en courseN_data.txt con formato ##NombreActividad\nDescripcion\n---
- Generar PDFs con Python reportlab (Platypus)
| 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 |
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