> ## 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.

# 抓取

> 抓取一个URL并获取所有子页面的内容

通过 Olostep 的 `/v1/crawls` 端点，你可以抓取一个网站并获取所有页面的内容。

* 抓取一个网站并获取所有子页面的内容（或限制抓取深度）
* 使用特殊模式抓取特定页面（例如 `/blog/**`）
* 传递一个 `webhook_url`，在抓取完成时收到通知
* 搜索查询仅查找特定页面并按相关性排序

有关API详情，请参阅 [抓取端点API参考](/api-reference/crawls/create)。

## 安装

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

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

  ```bash cURL theme={null}
  # curl 在 macOS、Linux 和 Windows 上默认可用
  ```

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

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

## 开始抓取

提供起始URL，包含/排除URL模式，以及 `max_pages`。可选项：`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>

由于 Olostep 中的所有内容都是对象，你将收到一个 `crawl` 对象作为响应。`crawl` 对象有一些属性，比如 `id` 和 `status`，你可以用来跟踪抓取。

## 检查抓取状态

轮询抓取以跟踪进度，直到 `status` 为 `completed`。

<CodeGroup>
  ```python Python theme={null}
  # 使用上一步的抓取对象
  info = crawl.info()
  print(info.status, info.pages_count)

  # 或者等待完成
  crawl.wait_till_done(check_every_n_secs=5)
  ```

  ```js Node theme={null}
  // 使用上一步的抓取对象
  const info = await crawl.info()
  console.log(info.status, info.pages_count)

  // 或者等待完成
  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>

或者，你可以在开始抓取时传递一个 `webhook_url`，以便在抓取完成时收到通知。

## 列出页面（使用游标分页/流）

获取页面并使用 `cursor` 和 `limit` 进行迭代。适用于抓取 `in_progress` 或 `completed` 状态。

<CodeGroup>
  ```python Python theme={null}
  # 迭代所有页面（自动等待抓取完成，处理分页）
  for page in crawl.pages():
      print(page.url, page.retrieve_id)
  ```

  ```js Node theme={null}
  // 迭代所有页面（自动等待抓取完成，处理分页）
  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>

## 搜索查询（限制到前 N 个相关）

在开始时使用 `search_query`，并可选择使用 `search_query` 过滤列表。使用 `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>

## 获取内容

使用每个页面的 `retrieve_id` 和 `/v1/retrieve` 来获取 `html_content` 和/或 `markdown_content`。

<CodeGroup>
  ```python Python theme={null}
  # 获取每个抓取页面的内容
  for page in crawl.pages():
      content = page.retrieve(["markdown"])
      print(content.markdown_content)
  ```

  ```js Node theme={null}
  // 获取每个抓取页面的内容
  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>

## 注意事项

* 分页是基于游标的；重复请求直到 `cursor` 不存在。
* `/v1/crawls/{crawl_id}/pages` 上的内容字段已弃用；请使用 `/v1/retrieve`。
* Webhooks：设置 `webhook_url` 以在抓取完成时接收POST。

## 价格

抓取每个页面消耗1个信用。
