
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@soblend/scraper
Advanced tools
@soblend/scraper es una colección completa de 13 scrapers robustos y verificados, diseñados para extraer datos de diferentes fuentes web. Cada scraper está optimizado para su caso de uso específico, incluye manejo robusto de errores, reintentos automáticos y una API consistente.
La librería está construida con arquitectura modular, permitiéndote importar únicamente los scrapers que necesitas, reduciendo el tamaño del bundle y mejorando el rendimiento de tu aplicación.
npm install @soblend/scraper
import { MetaDataFinder, CryptoPriceWatcher } from '@soblend/scraper';
// Extraer metadatos de un sitio web
const metaFinder = new MetaDataFinder();
const metadata = await metaFinder.scrape('https://example.com');
console.log(metadata.metadata.basic.title);
// Obtener precios de criptomonedas
const crypto = new CryptoPriceWatcher();
const top10 = await crypto.getTopCryptos(10);
console.log(top10.cryptos);
Scraper especializado para descargar imágenes de páginas web con capacidad de filtrado por dimensiones y formato.
Casos de uso:
Opciones de configuración:
{
timeout: 10000, // Tiempo máximo de espera por request (ms)
maxImages: 100, // Número máximo de imágenes a extraer
minWidth: 0, // Ancho mínimo en píxeles
minHeight: 0, // Alto mínimo en píxeles
formats: ['.jpg', '.png'], // Formatos de imagen aceptados
userAgent: 'custom-agent', // User agent personalizado
retries: 3, // Número de reintentos en caso de fallo
downloadPath: './images' // Ruta de descarga
}
Métodos:
scrape(url) - Extrae información de todas las imágenes de la URL
url (string) - URL de la página a scrapearsuccess, total, images[], sourceUrldownload(images, outputPath) - Descarga las imágenes al sistema de archivos
images (array) - Array de objetos de imagenoutputPath (string, opcional) - Ruta de destinoEjemplo:
import { ImageCollector } from '@soblend/scraper';
const collector = new ImageCollector({
maxImages: 50,
minWidth: 800,
minHeight: 600,
formats: ['.jpg', '.png', '.webp']
});
const result = await collector.scrape('https://example.com/gallery');
if (result.success) {
console.log(`Encontradas ${result.total} imágenes`);
const downloads = await collector.download(result.images, './my-images');
console.log(`Descargadas: ${downloads.filter(d => d.success).length}`);
}
Extractor completo de metadatos web incluyendo SEO, Open Graph, Twitter Cards y JSON-LD.
Casos de uso:
Opciones de configuración:
{
timeout: 10000,
userAgent: 'Mozilla/5.0...',
retries: 3
}
Métodos:
scrape(url) - Extrae todos los metadatos de la URL
success, url, metadata, scrapedAtmetadata incluye: basic, openGraph, twitter, jsonLd, additionalEjemplo:
import { MetaDataFinder } from '@soblend/scraper';
const finder = new MetaDataFinder();
const result = await finder.scrape('https://example.com');
if (result.success) {
console.log('Título:', result.metadata.basic.title);
console.log('Descripción:', result.metadata.basic.description);
console.log('Imagen OG:', result.metadata.openGraph.image);
console.log('Twitter Card:', result.metadata.twitter.card);
console.log('JSON-LD:', result.metadata.jsonLd);
}
Estructura de datos retornada:
basic: title, description, keywords, canonical, favicon, etc.openGraph: title, type, url, image, description, site_name, etc.twitter: card, site, creator, title, description, image, etc.jsonLd: Array de objetos JSON-LD estructuradosadditional: lang, charset, viewport, robots, author, generatorScraper para descubrir y catalogar fuentes tipográficas de múltiples fuentes.
Fuentes soportadas:
Métodos:
scrapeGoogleFonts(query) - Busca fuentes en Google Fonts
query (string, opcional) - Término de búsquedascrapeDaFont(category) - Extrae fuentes de DaFont
category (string) - Categoría (ej: 'popular', 'new')scrapeFromCSS(url) - Analiza fuentes usadas en un sitio web
url (string) - URL del sitio a analizarEjemplo:
import { FontHunter } from '@soblend/scraper';
const hunter = new FontHunter();
// Buscar en Google Fonts
const googleFonts = await hunter.scrapeGoogleFonts('Roboto');
console.log(`Encontradas ${googleFonts.total} fuentes`);
// Obtener fuentes populares de DaFont
const dafonts = await hunter.scrapeDaFont('popular');
// Analizar fuentes de un sitio web
const siteFonts = await hunter.scrapeFromCSS('https://example.com');
console.log('Fuentes usadas:', siteFonts.fonts);
Monitor de precios para sitios de e-commerce con historial de precios integrado.
Plataformas soportadas:
Métodos:
scrapeAmazon(productUrl) - Extrae datos de producto Amazon
scrapeMercadoLibre(productUrl) - Extrae datos de MercadoLibre
scrapeAliExpress(productUrl) - Extrae datos de AliExpress
getPriceHistory(url) - Obtiene historial de precios de un producto
getPriceComparison(url) - Análisis comparativo de precios
Ejemplo:
import { ProductWatcher } from '@soblend/scraper';
const watcher = new ProductWatcher();
const product = await watcher.scrapeAmazon('https://amazon.com/dp/...');
console.log(`${product.product.title}: $${product.product.price}`);
// Consultar después de un tiempo
const comparison = watcher.getPriceComparison(productUrl);
console.log(`Cambio: ${comparison.changePercent}%`);
console.log(`Precio más bajo histórico: $${comparison.lowest}`);
Scraper de cotizaciones de criptomonedas en tiempo real.
Fuentes de datos:
Métodos:
scrapeCoinMarketCap(symbols) - Obtiene datos de CoinMarketCap
symbols (array) - Símbolos de criptomonedas (ej: ['BTC', 'ETH'])scrapeBinance(pairs) - Obtiene datos de Binance
pairs (array) - Pares de trading (ej: ['BTCUSDT', 'ETHUSDT'])getCryptoBySymbol(symbol) - Busca una criptomoneda específica
symbol (string) - Símbolo (ej: 'BTC')getTopCryptos(limit) - Obtiene las top N criptomonedas
limit (number) - Cantidad (default: 10)Ejemplo:
import { CryptoPriceWatcher } from '@soblend/scraper';
const crypto = new CryptoPriceWatcher({ currency: 'USD' });
// Top 10 criptomonedas
const top10 = await crypto.getTopCryptos(10);
top10.cryptos.forEach(coin => {
console.log(`${coin.symbol}: $${coin.price} (${coin.change24h})`);
});
// Buscar Bitcoin específicamente
const btc = await crypto.getCryptoBySymbol('BTC');
console.log(`Bitcoin: $${btc.crypto.price}`);
// Obtener de Binance
const binance = await crypto.scrapeBinance(['BTCUSDT', 'ETHUSDT']);
Extractor de posts, comentarios y datos de subreddits usando la API JSON pública de Reddit.
IMPORTANTE: Reddit puede bloquear requests sin autenticación OAuth. Para uso en producción, se recomienda usar la API oficial de Reddit con credenciales OAuth.
Métodos:
scrape(subreddit, options) - Extrae posts de un subreddit
subreddit (string) - Nombre del subreddit (sin 'r/')options (object):
sort: 'hot', 'new', 'top', 'rising', 'controversial'limit: Número de posts (default: 25)timeframe: 'hour', 'day', 'week', 'month', 'year', 'all' (para top/controversial)getComments(subreddit, postId) - Obtiene comentarios de un post
searchSubreddit(subreddit, query, options) - Busca posts en un subreddit
scrape() con parámetro query adicionalEjemplo:
import { RedditPostGrabber } from '@soblend/scraper';
const reddit = new RedditPostGrabber({ limit: 25 });
// Posts hot de r/javascript
const posts = await reddit.scrape('javascript', {
sort: 'hot',
limit: 25
});
posts.posts.forEach(post => {
console.log(`${post.title} (${post.score} upvotes)`);
console.log(`${post.numComments} comentarios`);
});
// Obtener comentarios
const comments = await reddit.getComments('javascript', 'abc123');
console.log(`Total comentarios: ${comments.total}`);
// Buscar posts
const search = await reddit.searchSubreddit('javascript', 'react hooks');
Extractor de estadísticas públicas de redes sociales.
Plataformas soportadas:
Métodos:
scrapeInstagram(username) - Estadísticas de perfil Instagram
scrapeTikTok(username) - Estadísticas de perfil TikTok
scrapeTwitter(username) - Estadísticas de perfil Twitter/X
scrapeYouTube(channelId) - Estadísticas de canal YouTube
Ejemplo:
import { SocialStats } from '@soblend/scraper';
const social = new SocialStats();
const instagram = await social.scrapeInstagram('username');
if (instagram.success) {
console.log(`Seguidores: ${instagram.stats.followers}`);
console.log(`Posts: ${instagram.stats.posts}`);
}
const youtube = await social.scrapeYouTube('UCxxxxxxxx');
console.log(`Suscriptores: ${youtube.stats.subscribers}`);
Limitaciones: Muchas redes sociales requieren autenticación para acceder a estadísticas completas. Los datos disponibles sin autenticación son limitados.
Scraper para descubrir proyectos trending de GitHub y buscar repositorios.
Métodos:
scrapeTrending(language, timeframe) - Repositorios trending
language (string) - Lenguaje de programación (ej: 'javascript', 'python', '' para todos)timeframe (string) - 'daily', 'weekly', 'monthly'scrapeRepository(owner, repo) - Detalles de un repositorio
searchRepositories(query, options) - Buscar repositorios
query (string) - Término de búsquedaoptions (object): sort ('stars', 'forks'), order ('desc', 'asc'), languageEjemplo:
import { GitHubTrends } from '@soblend/scraper';
const github = new GitHubTrends();
// Trending diario de JavaScript
const trending = await github.scrapeTrending('javascript', 'daily');
trending.repositories.forEach(repo => {
console.log(`${repo.fullName}: ${repo.stars} ⭐ (+${repo.todayStars} hoy)`);
});
// Detalles de un repo específico
const repo = await github.scrapeRepository('facebook', 'react');
console.log(repo.repository.description);
// Buscar repos de machine learning
const search = await github.searchRepositories('machine learning', {
sort: 'stars',
order: 'desc'
});
Agregador de ofertas de trabajo de múltiples plataformas.
Plataformas soportadas:
Métodos:
scrapeIndeed(query, location, options) - Buscar en Indeed
query (string) - Término de búsquedalocation (string) - Ubicaciónoptions.limit (number) - Máximo de resultadosscrapeLinkedIn(query, location) - Buscar en LinkedIn (limitado)
scrapeComputrabajo(query, location) - Buscar en Computrabajo
location puede ser: 'mexico', 'argentina', 'colombia', etc.scrapeRemoteOK(query) - Buscar trabajos remotos en RemoteOK
Ejemplo:
import { JobScraper } from '@soblend/scraper';
const jobs = new JobScraper();
// Buscar en Indeed
const indeed = await jobs.scrapeIndeed('javascript developer', 'New York', {
limit: 20
});
indeed.jobs.forEach(job => {
console.log(`${job.title} - ${job.company}`);
console.log(`${job.location} | ${job.salary}`);
});
// Trabajos remotos
const remote = await jobs.scrapeRemoteOK('developer');
console.log(`${remote.total} trabajos remotos encontrados`);
Scraper especializado para MyAnimeList con búsqueda y exploración de anime.
Métodos:
scrapeMyAnimeList(query) - Buscar anime
query (string) - Término de búsquedascrapeAnimeDetails(malId) - Detalles completos de un anime
malId (number) - ID de MyAnimeListscrapeTopAnime(type, limit) - Top anime
type (string) - 'anime', 'airing', 'upcoming', 'tv', 'movie', etc.limit (number) - Cantidad (default: 20)scrapeSeasonal(year, season) - Anime de la temporada
year (number) - Año (ej: 2025)season (string) - 'winter', 'spring', 'summer', 'fall'Ejemplo:
import { AnimeFinder } from '@soblend/scraper';
const anime = new AnimeFinder();
// Buscar anime
const search = await anime.scrapeMyAnimeList('one piece');
console.log(`Encontrados ${search.total} resultados`);
// Top anime
const top = await anime.scrapeTopAnime('anime', 20);
top.animes.forEach(a => {
console.log(`${a.rank}. ${a.title} - Score: ${a.score}`);
});
// Anime de temporada actual
const seasonal = await anime.scrapeSeasonal(2025, 'winter');
console.log(`${seasonal.total} animes esta temporada`);
Descubridor de eventos de múltiples plataformas.
Plataformas soportadas:
Métodos:
scrapeEventbrite(query, location) - Buscar eventos en Eventbrite
scrapeMeetup(topic, location) - Buscar meetups (requiere autenticación para datos completos)
scrapeTicketmaster(query, location) - Buscar eventos en Ticketmaster
scrapeLocalEvents(city, country) - Agrega eventos de múltiples fuentes
Ejemplo:
import { EventScraper } from '@soblend/scraper';
const events = new EventScraper();
// Eventos tech en San Francisco
const eventbrite = await events.scrapeEventbrite('tech', 'San Francisco');
eventbrite.events.forEach(event => {
console.log(`${event.title} - ${event.date}`);
console.log(`${event.location} | ${event.price}`);
});
// Todos los eventos locales
const local = await events.scrapeLocalEvents('Austin', 'US');
console.log(`${local.total} eventos encontrados`);
Scraper de datos meteorológicos de múltiples fuentes.
Fuentes soportadas:
Métodos:
scrapeWeatherCom(location) - Datos de Weather.com
scrapeWttr(location) - Datos de wttr.in (recomendado)
location (string) - Ciudad o coordenadasscrapeOpenMeteo(latitude, longitude) - Datos de Open-Meteo API
getWeather(location, source) - Wrapper genérico
location (string) - Ubicaciónsource (string) - 'wttr' o 'weather.com'Ejemplo:
import { WeatherScraper } from '@soblend/scraper';
const weather = new WeatherScraper();
// Usar wttr.in (recomendado)
const wttr = await weather.scrapeWttr('London');
console.log(`${wttr.location.name}, ${wttr.location.country}`);
console.log(`Temperatura: ${wttr.current.temperature}`);
console.log(`Condición: ${wttr.current.condition}`);
console.log(`Humedad: ${wttr.current.humidity}`);
// Pronóstico
wttr.forecast.forEach(day => {
console.log(`${day.date}: ${day.high} / ${day.low}`);
});
// Por coordenadas
const coords = await weather.scrapeOpenMeteo(51.5074, -0.1278);
console.log(coords.current);
Scraper de listas de proxies gratuitos con validación opcional.
Fuentes:
Métodos:
scrapeFreeProxyList() - Scrape de free-proxy-list.net
scrapeProxyScrape() - Scrape de proxyscrape.com
scrapeProxyNova() - Scrape de proxynova.com
getAllProxies() - Agrega proxies de todas las fuentes
validateProxy(proxy) - Valida si un proxy funciona
working (true/false) y responseTimevalidateProxies(proxies, concurrency) - Valida múltiples proxies
proxies (array) - Array de proxies a validarconcurrency (number) - Validaciones simultáneas (default: 5)Ejemplo:
import { ProxyFinder } from '@soblend/scraper';
const finder = new ProxyFinder({
validateProxies: false,
validationTimeout: 5000
});
// Obtener todos los proxies
const all = await finder.getAllProxies();
console.log(`Encontrados ${all.total} proxies únicos`);
all.proxies.slice(0, 10).forEach(proxy => {
console.log(`${proxy.ip}:${proxy.port} (${proxy.country}) - ${proxy.protocol}`);
});
// Validar proxies
const validated = await finder.validateProxies(all.proxies.slice(0, 20), 5);
console.log(`${validated.working} de ${validated.total} funcionando`);
validated.workingProxies.forEach(proxy => {
console.log(`${proxy.ip}:${proxy.port} - ${proxy.responseTime}ms`);
});
Todos los scrapers aceptan un objeto de opciones en su constructor para personalizar el comportamiento:
const scraper = new AnyScraper({
timeout: 15000, // Tiempo máximo de espera en milisegundos (default: 10000)
userAgent: 'CustomAgent/1.0', // User agent personalizado
retries: 3 // Número de reintentos ante fallos (default: 3)
});
Algunos scrapers tienen opciones adicionales específicas:
ImageCollector:
maxImages: Límite de imágenes a extraerminWidth, minHeight: Dimensiones mínimasformats: Array de extensiones permitidasdownloadPath: Ruta de descargaProductWatcher:
priceHistory: Array para almacenar historial de preciosCryptoPriceWatcher:
currency: Moneda de referencia (default: 'USD')RedditPostGrabber:
limit: Número de posts por request (default: 25)sort: Ordenamiento por defecto ('hot', 'new', 'top', etc.)ProxyFinder:
validateProxies: Validar automáticamente (default: false)validationTimeout: Timeout para validación (default: 5000ms)Todos los scrapers retornan un objeto de respuesta estandarizado:
{
success: boolean, // Indica si la operación fue exitosa
data: object | array, // Datos extraídos (varía por scraper)
error: string, // Mensaje de error si success es false
scrapedAt: string // Timestamp ISO 8601 de la extracción
}
Ejemplo de manejo de errores:
const result = await scraper.scrape(url);
if (result.success) {
// Procesar datos
console.log(result.data);
} else {
// Manejar error
console.error('Error:', result.error);
}
La librería tiene dependencias mínimas y ligeras:
La mayoría de sitios web implementan límites de peticiones. Recomendaciones:
robots.txtAlgunos scrapers tienen limitaciones sin autenticación:
| Servicio | Limitación | Solución |
|---|---|---|
| Bloqueo 403 sin OAuth | Usar API oficial con credenciales | |
| Datos limitados | Requiere login para estadísticas completas | |
| TikTok | Acceso restringido | API oficial requerida |
| Scraping bloqueado | Usar LinkedIn API oficial | |
| Twitter/X | Muy limitado | API oficial con autenticación |
Los scrapers basados en HTML pueden fallar si los sitios cambian su estructura. Monitoreamos y actualizamos regularmente, pero:
import { CryptoPriceWatcher } from '@soblend/scraper';
const crypto = new CryptoPriceWatcher();
const updateDashboard = async () => {
const top10 = await crypto.getTopCryptos(10);
// Actualizar UI con top10.cryptos
};
setInterval(updateDashboard, 60000); // Actualizar cada minuto
import { JobScraper } from '@soblend/scraper';
const jobs = new JobScraper();
const allJobs = [];
const indeed = await jobs.scrapeIndeed('developer', 'Remote');
const remote = await jobs.scrapeRemoteOK('developer');
allJobs.push(...indeed.jobs, ...remote.jobs);
// Almacenar en base de datos
import { ProductWatcher } from '@soblend/scraper';
const watcher = new ProductWatcher();
const checkPrice = async (productUrl, targetPrice) => {
const result = await watcher.scrapeAmazon(productUrl);
if (result.success && result.product.price <= targetPrice) {
// Enviar alerta (email, SMS, etc.)
sendAlert(`Precio bajo: $${result.product.price}`);
}
};
setInterval(() => checkPrice(url, 50), 3600000); // Cada hora
La librería incluye ejemplos y tests de demostración:
# Ejecutar demo completo
npm start
# Ejecutar tests básicos
npm test
Las contribuciones son bienvenidas. Para contribuir:
git checkout -b feature/nuevo-scraper)git commit -m 'Add: NuevoScraper')git push origin feature/nuevo-scraper)Si encuentras un bug o tienes una sugerencia:
Características planeadas para futuras versiones:
MIT © Soblend
Para preguntas, problemas o sugerencias:
/examplesDesarrollado para la comunidad de desarrolladores
FAQs
Librería robusta de scrapers para múltiples servicios y casos de uso
We found that @soblend/scraper demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.