ScavioScavio
ProduitTarifsDocumentation
ConnexionCommencer
  1. Accueil
  2. Tutoriels
  3. Comment extraire des données d'annuaires rendus en JavaScript
Tutoriel

Comment extraire des données d'annuaires rendus en JavaScript

Obtenez des données d'annuaires rendus en JavaScript sans navigateurs sans tête. Utilisez une API de recherche pour trouver des fiches indexées et un endpoint d'extraction pour les pages complètes.

Obtenez une clé API gratuiteDocumentation API

Les annuaires rendus en JavaScript comme Yelp, Angi et les places de marché SaaS modernes chargent les données dynamiquement, ce qui fait échouer le scraping traditionnel. Vous avez besoin de navigateurs sans tête, d'attendre l'hydratation et de gérer les mesures anti-bot. Une approche plus rapide : utilisez la recherche pour trouver des fiches indexées (Google a déjà rendu le JS pour vous), puis utilisez l'endpoint d'extraction pour des pages spécifiques. La recherche Scavio coûte 0,005 $/requête et l'endpoint d'extraction récupère le contenu rendu de n'importe quelle URL.

Prérequis

  • Python 3.9+ installé
  • bibliothèque requests installée
  • Une clé API Scavio de scavio.dev
  • Compréhension de base de l'extraction de données web

Parcours

Étape 1: Rechercher des fiches d'annuaire indexées

Google indexe les pages rendues en JS. Recherchez des fiches d'annuaire à l'aide de requêtes site: pour obtenir des titres et des extraits pré-rendus sans avoir besoin d'un navigateur.

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]}')

Étape 2: Extraire les données complètes d'une page avec l'endpoint d'extraction

Pour les fiches où l'extrait ne suffit pas, utilisez l'endpoint d'extraction Scavio pour obtenir le contenu complet de la page rendue. Cela gère le rendu JavaScript côté serveur.

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')

Étape 3: Construire un pipeline pour plusieurs annuaires

Recherchez dans plusieurs annuaires rendus en JS et combinez les résultats. Utilisez la recherche pour la découverte et l'extraction sélective pour l'enrichissement.

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')

Étape 4: Gérer la pagination et la limitation de débit

Pour des travaux d'extraction plus importants, implémentez la pagination via les résultats de recherche et respectez les limites de débit pour éviter d'être limité.

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')

Exemple 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]}")

Exemple 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)}`));
});

Sortie attendue

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

Tutoriels associés

  • Comment obtenir des données Google Maps sans scraping
  • Comment créer un pipeline de données d'annuaire B2B avec n8n et une API de recherche
  • Comment extraire des données d'entreprise locale sans code
  • Comment récupérer des données de recherche web sans gérer les proxies

Questions fréquentes

La plupart des développeurs terminent ce tutoriel en 15 à 30 minutes. Vous aurez besoin d'une clé API Scavio (l'offre gratuite suffit) et d'un environnement Python ou JavaScript fonctionnel.

Python 3.9+ installé. bibliothèque requests installée. Une clé API Scavio de scavio.dev. Compréhension de base de l'extraction de données web. Une clé API Scavio vous donne 50 crédits gratuits à l'inscription.

Oui. L'offre gratuite comprend 50 crédits à l'inscription, ce qui est largement suffisant pour terminer ce tutoriel et prototyper une solution fonctionnelle.

Scavio dispose d'un package natif LangChain (langchain-scavio), d'un serveur MCP et d'une API REST simple qui fonctionne avec tout client HTTP. Ce tutoriel utilise the raw REST API, mais vous pouvez l'adapter à votre framework de prédilection.

Ressources connexes

Best Of

Meilleures API de données TikTok sans scraping ni proxy en 2026

Read more
Best Of

Meilleures alternatives à l'automatisation de navigateur pour les données web (2026)

Read more
Comparison

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

Read more
Solution

Obtenez des données d'entreprises locales sans scraper Google Maps

Read more
Use Case

Remplacement d'API d'automatisation de navigateur

Read more
Comparison

Web Scraping in n8n (HTTP Request + HTML Extract) vs Search API in n8n (HTTP Request to search API)

Read more

Commencer

Obtenez des données d'annuaires rendus en JavaScript sans navigateurs sans tête. Utilisez une API de recherche pour trouver des fiches indexées et un endpoint d'extraction pour les pages complètes.

Obtenez une clé API gratuiteLire la documentation
ScavioScavio

API de recherche en temps réel pour agents IA. Recherchez sur toutes les plateformes, pas seulement Google.

Produit

  • Fonctionnalités
  • Tarifs
  • Tableau de bord
  • Affiliés

Développeurs

  • Documentation
  • Référence API
  • Démarrage rapide
  • Intégration MCP
  • SDK Python

Alternatives

  • Alternative à Tavily
  • Alternative à SerpAPI
  • Alternative à Firecrawl
  • Alternative à Exa

Outils

  • Formateur JSON
  • cURL vers code
  • Compteur de jetons
  • Tous les outils

© 2026 Scavio. Tous droits réservés.

Featured on TAAFT
Conditions d'utilisationPolitique de confidentialité