ScavioScavio
ProductoPreciosDocumentación
Iniciar sesionComenzar
  1. Inicio
  2. Tutoriales
  3. Cómo extraer datos de directorios renderizados por JavaScript
Tutorial

Cómo extraer datos de directorios renderizados por JavaScript

Obtenga datos de directorios renderizados en JavaScript sin navegadores sin cabeza. Utilice una API de búsqueda para encontrar listados indexados y un punto final de extracción para páginas completas.

Obtener clave API gratisDocumentacion API

Los directorios renderizados en JavaScript como Yelp, Angi y los mercados SaaS modernos cargan datos de forma dinámica, lo que hace que el scraping tradicional falle. Necesita navegadores sin cabeza, esperar a que se hidrate y manejar medidas anti-bot. Un enfoque más rápido: use la búsqueda para encontrar listados indexados (Google ya representó el JS para usted), luego use el punto final de extracción para páginas específicas. La búsqueda de Scavio cuesta $0,005/solicitud y el punto final de extracción extrae el contenido renderizado de cualquier URL.

Requisitos previos

  • Python 3.9+ instalado
  • solicita biblioteca instalada
  • Una clave API de Scavio de scavio.dev
  • Comprensión básica de la extracción de datos web

Guia paso a paso

Paso 1: Buscar listados de directorios indexados

Google indexa páginas renderizadas en JS. Busque listados de directorios utilizando el sitio: consultas para obtener títulos y fragmentos pre-renderizados sin necesidad de un navegador.

Python
import os, requests, re

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
URL = 'https://api.scavio.dev/api/v1/search'
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}

def search_directory_listings(directory_domain: str, niche: str, num: int = 10) -> list:
    """Find directory listings via Google's index (already JS-rendered)."""
    resp = requests.post(URL, headers=H,
        json={'query': f'site:{directory_domain} {niche}',
              'country_code': 'us', 'num_results': num})
    resp.raise_for_status()
    results = resp.json().get('organic_results', [])
    return [{
        'title': r['title'],
        'url': r['link'],
        'snippet': r.get('snippet', ''),
        'rich_snippet': r.get('rich_snippet', {}),
    } for r in results]

# Search Yelp (heavily JS-rendered)
yelp_results = search_directory_listings('yelp.com', 'plumber San Francisco')
print(f'Yelp listings found: {len(yelp_results)}')
for r in yelp_results[:3]:
    print(f'  {r["title"][:60]}')
    print(f'    {r["snippet"][:100]}')

Paso 2: Extraiga datos de página completa con el punto final de extracción

Para listados donde el fragmento no es suficiente, utilice el punto final de extracción de Scavio para obtener el contenido completo de la página. Esto maneja la representación de JavaScript en el lado del servidor.

Python
EXTRACT_URL = 'https://api.scavio.dev/api/v1/extract'

def extract_page(url: str) -> dict:
    """Extract rendered content from a JS-heavy page."""
    resp = requests.post(EXTRACT_URL,
        headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
        json={'url': url})
    resp.raise_for_status()
    return resp.json()

def extract_listing_data(listing_url: str) -> dict:
    """Extract structured data from a directory listing page."""
    page = extract_page(listing_url)
    content = page.get('content', '')
    metadata = page.get('metadata', {})
    # Extract rating from content
    rating_match = re.search(r'(\d+\.\d+)\s*(?:star|/5|rating)', content, re.I)
    # Extract phone
    phone_match = re.search(r'\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}', content)
    return {
        'title': metadata.get('title', ''),
        'description': metadata.get('description', ''),
        'rating': float(rating_match.group(1)) if rating_match else None,
        'phone': phone_match.group(0) if phone_match else None,
        'url': listing_url,
        'content_length': len(content),
    }

# Extract data from a listing
if yelp_results:
    listing = extract_listing_data(yelp_results[0]['url'])
    print(f'Extracted: {listing["title"]}')
    print(f'  Rating: {listing["rating"]}')
    print(f'  Phone: {listing["phone"]}')
    print(f'  Content: {listing["content_length"]} chars')

Paso 3: Cree una canalización para varios directorios

Busque en varios directorios renderizados en JS y combine los resultados. Utilice la búsqueda para descubrimiento y el extracto selectivo para enriquecimiento.

Python
import time

def pipeline(niche: str, city: str, directories: list) -> list:
    """Search multiple JS-rendered directories."""
    all_listings = []
    for domain in directories:
        print(f'Searching {domain}...')
        listings = search_directory_listings(domain, f'{niche} {city}')
        for listing in listings:
            listing['directory'] = domain
        all_listings.extend(listings)
        time.sleep(0.3)
    # Enrich top results with extract (selective to save cost)
    enriched = []
    for listing in all_listings[:5]:  # Only extract top 5
        try:
            data = extract_listing_data(listing['url'])
            listing.update(data)
        except Exception as e:
            listing['extract_error'] = str(e)
        enriched.append(listing)
        time.sleep(0.5)
    return all_listings

results = pipeline('electrician', 'Seattle WA', ['yelp.com', 'angi.com', 'thumbtack.com'])
print(f'\nTotal listings: {len(results)}')
for r in results[:5]:
    rating = r.get('rating', 'N/A')
    print(f"  [{r['directory']}] {r['title'][:50]} (Rating: {rating})")
print(f'\nSearch cost: 3 x $0.005 = $0.015')
print(f'Extract cost: 5 x $0.005 = $0.025')
print(f'Total: $0.040')

Paso 4: Manejar la paginación y la limitación de velocidad

Para trabajos de extracción más grandes, implemente la paginación a través de los resultados de búsqueda y respete los límites de velocidad para evitar limitaciones.

Python
def paginated_search(domain: str, niche: str, max_pages: int = 3) -> list:
    """Search with pagination for more results."""
    all_results = []
    for page in range(max_pages):
        # Add page-specific terms to get different results
        suffixes = ['', 'reviews', 'top rated']
        suffix = suffixes[page] if page < len(suffixes) else f'page {page+1}'
        query = f'site:{domain} {niche} {suffix}'.strip()
        resp = requests.post(URL, headers=H,
            json={'query': query, 'country_code': 'us', 'num_results': 10})
        results = resp.json().get('organic_results', [])
        for r in results:
            # Deduplicate by URL
            if r['link'] not in [x['url'] for x in all_results]:
                all_results.append({
                    'title': r['title'],
                    'url': r['link'],
                    'snippet': r.get('snippet', ''),
                })
        time.sleep(0.5)
        if len(results) < 5:
            break  # No more results
    return all_results

results = paginated_search('yelp.com', 'plumber Portland OR', max_pages=3)
print(f'Paginated search: {len(results)} unique listings')
print(f'Cost: 3 pages x $0.005 = $0.015')

Ejemplo en Python

Python
import os, requests, re, time

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}

def search_dir(domain, query):
    resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
        json={'query': f'site:{domain} {query}', 'country_code': 'us', 'num_results': 10})
    return [{'title': r['title'], 'url': r['link'], 'snippet': r.get('snippet', '')}
            for r in resp.json().get('organic_results', [])]

def extract(url):
    resp = requests.post('https://api.scavio.dev/api/v1/extract', headers=H, json={'url': url})
    return resp.json()

listings = search_dir('yelp.com', 'plumber San Francisco')
print(f'Found {len(listings)} listings')
for l in listings[:3]:
    print(f"  {l['title'][:50]}")

Ejemplo en JavaScript

JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
const H = { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' };

async function searchDir(domain, query) {
  const resp = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST', headers: H,
    body: JSON.stringify({ query: `site:${domain} ${query}`, country_code: 'us', num_results: 10 })
  });
  return ((await resp.json()).organic_results || []).map(r => ({
    title: r.title, url: r.link, snippet: r.snippet || ''
  }));
}

async function extract(url) {
  const resp = await fetch('https://api.scavio.dev/api/v1/extract', {
    method: 'POST', headers: H, body: JSON.stringify({ url })
  });
  return resp.json();
}

searchDir('yelp.com', 'plumber San Francisco').then(l => {
  console.log(`Found ${l.length} listings`);
  l.slice(0, 3).forEach(x => console.log(`  ${x.title.slice(0, 50)}`));
});

Salida esperada

JSON
Searching yelp.com...
Searching angi.com...
Searching thumbtack.com...

Total listings: 24
  [yelp.com] Mike's Electric - Seattle, WA (Rating: 4.8)
  [yelp.com] Brennan Electric - Licensed Electrician (Rating: 4.9)
  [angi.com] Top Electricians in Seattle (Rating: N/A)
  [thumbtack.com] Seattle Electrician Services (Rating: 4.7)

Search cost: 3 x $0.005 = $0.015
Extract cost: 5 x $0.005 = $0.025
Total: $0.040

Tutoriales relacionados

  • Cómo obtener datos de Google Maps sin raspar
  • Cómo crear una canalización de datos de directorio B2B con n8n y una API de búsqueda
  • Cómo extraer datos comerciales locales sin código
  • Cómo recuperar datos de búsqueda web sin administrar servidores proxy

Preguntas frecuentes

La mayoria de los desarrolladores completan este tutorial en 15 a 30 minutos. Necesitaras una clave API de Scavio (el plan gratuito funciona) y un entorno de Python o JavaScript.

Python 3.9+ instalado. solicita biblioteca instalada. Una clave API de Scavio de scavio.dev. Comprensión básica de la extracción de datos web. Una clave API de Scavio te da 50 creditos gratuitos al registrarte.

Si. El plan gratuito incluye 50 creditos al registrarte, mas que suficiente para completar este tutorial y crear un prototipo funcional.

Scavio tiene un paquete nativo de LangChain (langchain-scavio), un servidor MCP y una API REST simple que funciona con cualquier cliente HTTP. Este tutorial usa the raw REST API, pero puedes adaptarlo al framework que prefieras.

Recursos relacionados

Best Of

Las mejores API de búsqueda después de los cambios en el modo AI de Google I/O 2026

Read more
Glossary

Panorama de proveedores de API de búsqueda (2026)

Read more
Best Of

Los mejores proveedores de API SERP clasificados por precio en 2026

Read more
Glossary

Comparación gratuita de niveles de API de búsqueda

Read more
Comparison

Search APIs (Scavio, Tavily, SerpAPI) vs Headless Browser (Playwright, Puppeteer, Browserbase)

Read more
Comparison

Google Places API vs SERP Local Pack API

Read more

Empieza a construir

Obtenga datos de directorios renderizados en JavaScript sin navegadores sin cabeza. Utilice una API de búsqueda para encontrar listados indexados y un punto final de extracción para páginas completas.

Obtener clave API gratuitaLeer la documentacion
ScavioScavio

API de busqueda en tiempo real para agentes de IA. Busca en todas las plataformas, no solo en Google.

Producto

  • Funciones
  • Precios
  • Panel
  • Afiliados

Desarrolladores

  • Documentacion
  • Referencia de API
  • Inicio rapido
  • Integracion MCP
  • Python SDK

Alternativas

  • Alternativa a Tavily
  • Alternativa a SerpAPI
  • Alternativa a Firecrawl
  • Alternativa a Exa

Herramientas

  • Formateador JSON
  • cURL a codigo
  • Contador de tokens
  • Todas las herramientas

© 2026 Scavio. Todos los derechos reservados.

Featured on TAAFT
Terminos de servicioPolitica de privacidad