# Обход с разбором

> extract на каждой странице обхода: на выходе таблица объектов, а не гора разметки

Источник: https://docs.parreq.com/crawl-extract/

`extract` в обходе — тот же самый разбор, что и в
[Fetch](https://docs.parreq.com/fetch-extract): вы описываете словами, какие поля нужны, и получаете
готовый объект вместо разметки. Разница одна — описание задаётся **один раз на
задание**, а применяется к каждой пройденной странице.

Это и есть обычный сценарий обхода. Сотня карточек товара нужна не разметкой:
нужна таблица «название, цена, наличие», и собирать её из ста документов
руками — работа, которую разбор делает сам.

**Цена:** страница обхода с разбором стоит 5 кредитов — разметка 1, обход 1,
разбор 3. Арифметика целиком — на странице [Цена обхода](https://docs.parreq.com/crawl-pricing).

```python Python
res = client.crawl(
    url="https://books.toscrape.com/catalogue/category/books/mystery_3/index.html",
    pages=34,
    next="li.next a",
    follow=".product_pod h3 a",
    extract={
        "title": "Название книги",
        "price": "Цена числом, без валюты",
        "in_stock": "Есть ли в наличии",
    },
)

for page in res.pages:
    print(page["parsed"])
```

```javascript Node
const res = await client.crawl({
  url: "https://books.toscrape.com/catalogue/category/books/mystery_3/index.html",
  pages: 34,
  next: "li.next a",
  follow: ".product_pod h3 a",
  extract: {
    title: "Название книги",
    price: "Цена числом, без валюты",
    in_stock: "Есть ли в наличии",
  },
});

for (const page of res.pages) {
  console.log(page.parsed);
}
```

```bash cURL
curl -X POST https://api.parreq.com/v1/crawl \
  -H "Authorization: Bearer pr_ВАШКЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://books.toscrape.com/catalogue/category/books/mystery_3/index.html",
    "pages": 34,
    "next": "li.next a",
    "follow": ".product_pod h3 a",
    "extract": {"title": "Название книги",
                "price": "Цена числом, без валюты",
                "in_stock": "Есть ли в наличии"}
  }'
```

Каждая страница приходит в своей обычной форме — ответ Fetch целиком, —
поэтому `parsed` лежит там же, где вы привыкли его брать:

```json
{
  "pages": [
    {
      "fetch_metadata": {
        "final_url": "https://books.toscrape.com/catalogue/sharp-objects_997/index.html",
        "extract_note": "",
        "credits": 5
      },
      "parsed": { "title": "Sharp Objects", "price": 47.82, "in_stock": true }
    }
  ]
}
```

## Что стоит помнить

Разбор в обходе ведёт себя ровно так же, как в Fetch, — со всеми оговорками
той страницы:

- поля описываются фразой, до 25 полей, описание до 200 символов;
- ненайденное поле приходит `null`, а не пропадает из объекта;
- неудавшийся разбор **не списывается**: `parsed: null`, причина в
  `extract_note`, а в счёте за эту страницу остаются только разметка и обход —
  2 кредита вместо 5;
- ошибка в описании полей — `400 invalid_request` до старта задания, то есть
  бесплатно.

Разбирать листинги вместе с карточками смысла обычно нет: на странице каталога
двадцать товаров, а поля описаны для одного. Если карточки достаются по
`follow`, поля описывайте под карточку — листинг всё равно вернёт то, что
сумеет, но полезное лежит глубже.

> **Внимание.**
>   Страницу читает языковая модель, а не набор правил, и на сотне страниц это
>   заметнее, чем на одной: часть полей неизбежно придёт пустой или в другой
>   форме. Там, где нужна ровно та величина ровно из того блока, берите
>   [подрезку блоками](https://docs.parreq.com/fetch-tuning) в `fetch.select` — селектор либо совпал,
>   либо нет, и это видно по `matched` каждой страницы.

## Дальше

**[Разбор страницы в структуру](https://docs.parreq.com/fetch-extract)**
    Как описывать поля, что гарантируется и что нет.

**[Цена обхода](https://docs.parreq.com/crawl-pricing)**
    Сколько стоит сотня страниц с разбором.
