Metadata-Version: 2.5
Name: parreq
Version: 1.1.0
Summary: Клиент Parreq: поисковая выдача Google и Яндекса в JSON
Project-URL: Documentation, https://req.akuraq.dev/docs
Project-URL: Homepage, https://req.akuraq.dev
License: MIT
License-File: LICENSE
Keywords: google,scraping,search-api,serp,yandex
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# parreq

Клиент [Parreq](https://req.akuraq.dev) — поисковая выдача Google и Яндекса в
JSON. Без зависимостей, только стандартная библиотека.

```bash
pip install parreq
```

```python
from parreq import Parreq

client = Parreq("pr_ВАШКЛЮЧ")

res = client.yandex("кофемашина", gl="by", hl="ru", include=["ads", "shopping"])
print(len(res.organic), "органических,", len(res.ads), "объявлений")

for item in res.organic:
    print(item["position"], item["title"], item["link"])
```

`engine` обязателен, поэтому у общего метода он позиционно-именованный, а для
двух движков есть сахар:

```python
client.search("coffee machine", engine="google", gl="us", hl="en")
client.google("coffee machine", gl="us")
client.yandex("кофемашина", gl="by", hl="ru")
```

## Секции

По умолчанию приходит только органика. Остальное — через `include`:

```python
res = client.google("купить кофемашину", gl="by", hl="ru",
                    include=["ads", "shopping", "videos", "related_searches"])
res.ads, res.shopping, res.videos, res.related
```

Доступно: `ads`, `shopping`, `local`, `knowledge_graph`, `ai_overview`,
`answer_box`, `people_also_ask`, `related_searches`, `images`, `videos`, `news`,
`total_results`, либо `include="all"`.

## Ошибки

```python
from parreq import Parreq, RateLimited, NoWorkers, SearchBlocked, ParreqError

try:
    res = client.google("coffee", gl="us")
except NoWorkers as exc:          # 503: нет прогретого профиля под движок
    print("повторить через", exc.retry_after, "с")
except RateLimited as exc:        # 429: частота, квота или одновременность
    print(exc.code, exc.retry_after)
except SearchBlocked:             # 502: защиту обойти не удалось
    ...
except ParreqError as exc:        # всё остальное
    print(exc.status, exc.code, exc.request_id)
```

Клиент **сам повторяет** то, что лечится повтором (429, 502, 503, 504), выжидая
столько, сколько просит сервер в `Retry-After`. По умолчанию три попытки:

```python
client = Parreq("pr_…", retries=0)      # выключить повторы
client = Parreq("pr_…", timeout=240)    # запрос с решением капчи бывает долгим
```

## Свой расход

```python
u = client.usage()
print(u["used_today"], "из", u["limits"]["daily"])
```
