> ## Documentation Index
> Fetch the complete documentation index at: https://docs.olostep.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Crawl

> Crawler une URL et obtenir le contenu de toutes les sous-pages

Grâce à l’endpoint Olostep `/v1/crawls`, tu peux crawler un site web et obtenir le contenu de toutes les pages.

* Crawler un site web et obtenir le contenu de toutes les sous-pages (ou limiter la profondeur du crawl)
* Utiliser des motifs spéciaux pour crawler des pages spécifiques (par exemple, `/blog/**`)
* Passer une `webhook_url` pour être notifié lorsque le crawl est terminé
* Requête de recherche pour ne trouver que des pages spécifiques et trier par pertinence

Pour les détails de l'API, voir la [Référence de l'API de l'Endpoint Crawl](/api-reference/crawls/create).

## Installation

<CodeGroup>
  ```python Python theme={null}
  pip install olostep
  ```

  ```javascript Node theme={null}
  npm install olostep
  ```

  ```bash cURL theme={null}
  # curl est disponible par défaut sur macOS, Linux et Windows
  ```

  ```javascript Node (API) theme={null}
  npm install node-fetch
  ```

  ```bash Python (API) theme={null}
  pip install requests
  ```
</CodeGroup>

## Démarrer un crawl

Fournis l'URL de départ, inclure/exclure des motifs d'URL, et `max_pages`. Optionnel : `max_depth`, `include_external`, `include_subdomain`, `search_query`, `top_n`, `webhook_url`, `timeout`.

<CodeGroup>
  ```python Python theme={null}
  from olostep import Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  crawl = client.crawls.create(
      start_url="https://olostep.com",
      max_pages=100,
      include_urls=["/**"],
      exclude_urls=["/collections/**"],
      include_external=False,
  )

  print(crawl.id, crawl.status)
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const crawl = await client.crawls.create({
    url: 'https://olostep.com',
    maxPages: 100,
    includeUrls: ['/**'],
    excludeUrls: ['/collections/**'],
    includeExternal: false,
  })

  console.log(crawl.id, crawl.status)
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.olostep.com/v1/crawls" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "start_url": "https://olostep.com",
      "max_pages": 100,
      "include_urls": ["/**"],
      "exclude_urls": ["/collections/**"]
    }'
  ```

  ```js Node (API) theme={null}
  const API_URL = 'https://api.olostep.com'
  const res = await fetch(`${API_URL}/v1/crawls`, {
    method: 'POST',
    headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      start_url: 'https://olostep.com',
      max_pages: 100,
      include_urls: ['/**'],
      exclude_urls: ['/collections/**']
    })
  })
  console.log(await res.json())
  ```

  ```python Python (API) theme={null}
  import time, json

  API_URL = 'https://api.olostep.com'
  API_KEY = '<YOUR_API_KEY>'
  HEADERS = { 
      'Content-Type': 'application/json',
      'Authorization': f'Bearer {API_KEY}' 
  }

  data = {
    "start_url": "https://olostep.com",
    "max_pages": 100,
    "include_urls": ["/**"],
    "exclude_urls": ["/collections/**"],
    "include_external": False
  }

  res = requests.post(f"{API_URL}/v1/crawls", headers=HEADERS, json=data)
  crawl = res.json()
  print(json.dumps(crawl, indent=2))
  ```
</CodeGroup>

Puisque tout dans Olostep est un objet, tu recevras un objet `crawl` en réponse. L'objet `crawl` a quelques propriétés comme `id` et `status`, que tu peux utiliser pour suivre le crawl.

## Vérifier le statut du crawl

Interroge le crawl pour suivre la progression jusqu'à ce que `status` soit `completed`.

<CodeGroup>
  ```python Python theme={null}
  # En utilisant l'objet crawl de l'étape précédente
  info = crawl.info()
  print(info.status, info.pages_count)

  # Ou attendre jusqu'à ce que ce soit terminé
  crawl.wait_till_done(check_every_n_secs=5)
  ```

  ```js Node theme={null}
  // En utilisant l'objet crawl de l'étape précédente
  const info = await crawl.info()
  console.log(info.status, info.pages_count)

  // Ou attendre jusqu'à ce que ce soit terminé
  await crawl.waitTillDone({ checkEveryNSecs: 5 })
  ```

  ```bash cURL theme={null}
  curl -s -X GET "https://api.olostep.com/v1/crawls/<CRAWL_ID>" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY"
  ```

  ```js Node (API) theme={null}
  const crawlId = '<CRAWL_ID>'
  const status = await fetch(`${API_URL}/v1/crawls/${crawlId}`, {
    headers: { 'Authorization': 'Bearer <YOUR_API_KEY>' }
  }).then(r => r.json())
  console.log(status)
  ```

  ```python Python (API) theme={null}
  import time

  def get_crawl_info(crawl_id):
      return requests.get(f'{API_URL}/v1/crawls/{crawl_id}', headers=HEADERS).json()

  crawl_id = crawl['id']
  while True:
      info = get_crawl_info(crawl_id)
      print(info['status'], info.get('pages_count'))
      if info['status'] == 'completed':
          break
      time.sleep(5)
  ```
</CodeGroup>

Alternativement, tu peux passer une `webhook_url` lors du démarrage du crawl pour être notifié lorsque le crawl est terminé.

## Lister les pages (pagination/flux avec curseur)

Récupère les pages et itère en utilisant `cursor` et `limit`. Fonctionne pendant que le crawl est `in_progress` ou `completed`.

<CodeGroup>
  ```python Python theme={null}
  # Itérer sur toutes les pages (attend automatiquement la fin du crawl, gère la pagination)
  for page in crawl.pages():
      print(page.url, page.retrieve_id)
  ```

  ```js Node theme={null}
  // Itérer sur toutes les pages (attend automatiquement la fin du crawl, gère la pagination)
  for await (const page of crawl.pages()) {
    console.log(page.url, page.retrieve_id)
  }
  ```

  ```bash cURL theme={null}
  curl -s -G "https://api.olostep.com/v1/crawls/<CRAWL_ID>/pages" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    --data-urlencode "cursor=0" \
    --data-urlencode "limit=10"
  ```

  ```js Node (API) theme={null}
  let cursor = 0
  while (true) {
    const pages = await fetch(`${API_URL}/v1/crawls/${crawlId}/pages?cursor=${cursor}&limit=10`, {
      headers: { 'Authorization': 'Bearer <YOUR_API_KEY>' }
    }).then(r => r.json())
    pages.pages.forEach(p => console.log(p.url, p.retrieve_id))
    if (pages.cursor === undefined) break
    cursor = pages.cursor
  }
  ```

  ```python Python (API) theme={null}
  def get_pages(crawl_id, cursor=None, limit=10, search_query=None):
      params = { 
          'cursor': cursor, 
          'limit': limit
      }
      return requests.get(f'{API_URL}/v1/crawls/{crawl_id}/pages', headers=HEADERS, params=params).json()

  cursor = 0
  while True:
      page_batch = get_pages(crawl_id, cursor=cursor, limit=10)
      for page in page_batch['pages']:
          print(page['url'], page['retrieve_id'])
      if 'cursor' not in page_batch:
          break
      cursor = page_batch['cursor']
      time.sleep(5)
  ```
</CodeGroup>

## Requête de recherche (limiter aux N plus pertinents)

Utilise `search_query` au départ, et filtre éventuellement la liste avec `search_query`. Limite l'exploration par page avec `top_n`.

<CodeGroup>
  ```python Python theme={null}
  from olostep import Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  crawl = client.crawls.create(
      start_url="https://olostep.com",
      max_pages=100,
      include_urls=["/**"],
      search_query="contact us",
      top_n=5,
  )

  for page in crawl.pages(search_query="contact us"):
      print(page.url)
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const crawl = await client.crawls.create({
    url: 'https://olostep.com',
    maxPages: 100,
    includeUrls: ['/**'],
    searchQuery: 'contact us',
    topN: 5,
  })

  for await (const page of crawl.pages()) {
    console.log(page.url)
  }
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.olostep.com/v1/crawls" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "start_url": "https://olostep.com",
      "max_pages": 100,
      "include_urls": ["/**"],
      "search_query": "contact us",
      "top_n": 5
    }'
  ```

  ```js Node (API) theme={null}
  await fetch(`${API_URL}/v1/crawls`, { method: 'POST', headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' }, body: JSON.stringify({ start_url: 'https://olostep.com', max_pages: 100, include_urls: ['/**'], search_query: 'contact us', top_n: 5 }) })
  ```

  ```python Python (API) theme={null}
  data = {
    "start_url": "https://olostep.com",
    "max_pages": 100,
    "include_urls": ["/**"],
    "search_query": "contact us",
    "top_n": 5
  }
  crawl = requests.post(f'{API_URL}/v1/crawls', headers=HEADERS, json=data).json()
  pages = requests.get(f"{API_URL}/v1/crawls/{crawl['id']}/pages", headers=HEADERS, params={'search_query': 'contact us'}).json()
  print(len(pages['pages']))
  ```
</CodeGroup>

## Récupérer le contenu

Utilise le `retrieve_id` de chaque page avec `/v1/retrieve` pour récupérer `html_content` et/ou `markdown_content`.

<CodeGroup>
  ```python Python theme={null}
  # Récupérer le contenu pour chaque page crawlée
  for page in crawl.pages():
      content = page.retrieve(["markdown"])
      print(content.markdown_content)
  ```

  ```js Node theme={null}
  // Récupérer le contenu pour chaque page crawlée
  for await (const page of crawl.pages()) {
    const content = await client.retrieve.get(page.retrieve_id, ['markdown'])
    console.log(content.markdown_content)
  }
  ```

  ```bash cURL theme={null}
  curl -s -G "https://api.olostep.com/v1/retrieve" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    --data-urlencode "retrieve_id=<RETRIEVE_ID>"
  ```

  ```js Node (API) theme={null}
  const retrieved = await fetch(`${API_URL}/v1/retrieve?retrieve_id=<RETRIEVE_ID>`, { headers: { 'Authorization': 'Bearer <YOUR_API_KEY>' } }).then(r => r.json())
  console.log(retrieved.markdown_content)
  ```

  ```python Python (API) theme={null}
  def retrieve_content(retrieve_id):
      return requests.get(f"{API_URL}/v1/retrieve", headers=HEADERS, params={"retrieve_id": retrieve_id}).json()

  for page in get_pages(crawl['id'], limit=5)['pages']:
      retrieved = retrieve_content(page['retrieve_id'])
      print(retrieved.get('markdown_content'))
  ```
</CodeGroup>

## Remarques

* La pagination est basée sur un curseur ; répète les requêtes jusqu'à ce que le `cursor` soit absent.
* Les champs de contenu sur `/v1/crawls/{crawl_id}/pages` sont obsolètes ; préfère `/v1/retrieve`.
* Webhooks : définis `webhook_url` pour recevoir un POST lorsque le crawl est terminé.

## Tarification

Le crawl coûte 1 crédit par page crawlée.
