Guía intermedia
Guía de Procesamiento por Lotes
Escale el scraping web a miles de URL con una gestión de colas eficiente, recuperación ante errores y estrategias de optimización del rendimiento.
Uso de la herramienta batch_scrape
Gestión de colas
Recuperación ante errores
Optimización del rendimiento
1. Uso de la herramienta batch_scrape
La herramienta batch_scrape gestiona hasta 50 URL de forma concurrente con limitación de tasa integrada y notificaciones por webhook.
Scraping por lotes básico
1 credit por URL (50 URL = 50 credits)
Bash
curl -X POST https://crawlforge.dev/api/v1/tools/batch_scrape \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://example.com/page1",
"https://example.com/page2",
"https://example.com/page3"
],
"formats": ["markdown"],
"maxConcurrency": 5,
"onlyMainContent": true
}'Procesamiento asíncrono con webhooks
Ideal para lotes grandes (100+ URL): reciba una notificación cuando finalice
Typescript
// Start batch job with webhook
const response = await fetch('https://crawlforge.dev/api/v1/tools/batch_scrape', {
method: 'POST',
headers: {
'X-API-Key': process.env.CRAWLFORGE_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
urls: largeUrlList, // 100+ URLs
formats: ['markdown'],
webhook: 'https://yourapp.com/webhook/batch-complete',
maxConcurrency: 10
}),
});
const { jobId } = await response.json();
console.log(`Batch job started: ${jobId}`);
// Webhook handler (Express.js example)
app.post('/webhook/batch-complete', (req, res) => {
const { jobId, status, results, errors } = req.body;
if (status === 'completed') {
console.log(`Job ${jobId} completed!`);
console.log(`Success: ${results.length} pages`);
console.log(`Errors: ${errors.length} pages`);
// Process results
results.forEach(result => {
saveToDatabase(result.url, result.content);
});
}
res.sendStatus(200);
});2. Gestión de colas
Procese miles de URL dividiéndolas en lotes y gestionando una cola.
Estrategia de división en fragmentos
Divida listas grandes de URL en lotes manejables
Typescript
// Chunk array into batches of 50
function chunkArray<T>(array: T[], size: number): T[][] {
const chunks: T[][] = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
// Process all URLs in batches
async function processBatches(urls: string[]) {
const batches = chunkArray(urls, 50); // Max 50 URLs per batch
const allResults: any[] = [];
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
console.log(`Processing batch ${i + 1}/${batches.length}...`);
const response = await fetch('https://crawlforge.dev/api/v1/tools/batch_scrape', {
method: 'POST',
headers: {
'X-API-Key': process.env.CRAWLFORGE_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
urls: batch,
formats: ['markdown'],
maxConcurrency: 10
}),
});
const data = await response.json();
allResults.push(...data.data.results);
// Wait between batches to respect rate limits
if (i < batches.length - 1) {
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
return allResults;
}
// Usage
const urls = [...]; // 500 URLs
const results = await processBatches(urls);
console.log(`Scraped ${results.length} total pages`);Consejo profesional: Use Redis o una base de datos para almacenar su cola. Esto le permite reanudar el procesamiento si su script falla o necesita reiniciarse.
3. Recuperación ante errores
Gestione los fallos con elegancia mediante lógica de reintentos y seguimiento de errores.
Gestión robusta de errores
Typescript
interface BatchResult {
successful: any[];
failed: { url: string; error: string }[];
}
async function batchScrapeWithRetry(
urls: string[],
maxRetries = 3
): Promise<BatchResult> {
const successful: any[] = [];
const failed: { url: string; error: string }[] = [];
let remainingUrls = [...urls];
let retries = 0;
while (remainingUrls.length > 0 && retries <= maxRetries) {
try {
const response = await fetch('https://crawlforge.dev/api/v1/tools/batch_scrape', {
method: 'POST',
headers: {
'X-API-Key': process.env.CRAWLFORGE_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
urls: remainingUrls,
formats: ['markdown'],
maxConcurrency: 5
}),
});
const data = await response.json();
// Separate successful and failed results
const batchSuccessful = data.data.results.filter((r: any) => r.success);
const batchFailed = data.data.results.filter((r: any) => !r.success);
successful.push(...batchSuccessful);
// Only retry failed URLs
remainingUrls = batchFailed.map((r: any) => r.url);
if (remainingUrls.length > 0) {
console.log(`Retrying ${remainingUrls.length} failed URLs...`);
retries++;
await new Promise(resolve => setTimeout(resolve, 2000 * retries));
}
} catch (error) {
console.error('Batch request failed:', error);
retries++;
if (retries > maxRetries) {
// Mark all remaining URLs as failed
failed.push(...remainingUrls.map(url => ({
url,
error: String(error)
})));
break;
}
await new Promise(resolve => setTimeout(resolve, 2000 * retries));
}
}
return { successful, failed };
}
// Usage
const { successful, failed } = await batchScrapeWithRetry(urls);
console.log(`Success: ${successful.length}, Failed: ${failed.length}`);
// Save failed URLs for manual review
if (failed.length > 0) {
fs.writeFileSync('failed-urls.json', JSON.stringify(failed, null, 2));
}4. Optimización del rendimiento
Maximice el rendimiento y minimice los costos con estas estrategias de optimización.
Optimice la concurrencia
Comience con
maxConcurrency: 5 y auméntelo a 10 para los planes Professional/BusinessUse onlyMainContent
Establezca
onlyMainContent: true para reducir el tamaño de la respuesta entre un 60 y un 80%Elija formatos mínimos
Use
formats: ["markdown"] en lugar de varios formatos (html, text, screenshot)Almacene los resultados en caché
Guarde los datos extraídos en Redis o en una base de datos para evitar volver a hacer scraping de las mismas URL
Evite el exceso de lotes
No supere las 50 URL por lote; divídalas en varias solicitudes en su lugar
No ignore los límites de tasa
Respete los límites de tasa de su plan (Free: 5/s, Hobby: 10/s, Pro: 50/s, Business: 100/s)
Rendimiento esperado
| Escenario | Tiempo | Configuración |
|---|---|---|
| Lote pequeño (10 URL) | ~5 segundos | maxConcurrency: 5 |
| Lote mediano (50 URL) | ~15 segundos | maxConcurrency: 10 |
| Lote grande (500 URL) | ~3 minutos | 10 lotes × 50 URL |
| Lote masivo (5,000 URL) | ~30 minutos | 100 lotes × 50 URL |
Próximos pasos
Continúe aprendiendo con más guías avanzadas