Professional Python client for XMLRiver API with Wordstat support
Project description
XMLRiver Pro
__ ____ __ _ ____ _ ____
\ \/ / \/ | | | _ \(_)_ _____ _ __ | _ \ _ __ ___
\ /| |\/| | | | |_) | \ \ / / _ \ '__| | |_) | '__/ _ \
/ \| | | | |___| _ <| |\ V / __/ | | __/| | | (_) |
/_/\_\_| |_|_____|_| \_\_| \_/ \___|_| |_| |_| \___/
Professional Python client for XMLRiver API with full coverage
Fork of KursHub-ru/xmlriver
🚀 Quick Start • 📚 Documentation • 🔧 Configuration • 💡 Examples
🎯 О проекте
XMLRiver Pro — это профессиональная Python библиотека для работы с API xmlriver.com. Расширенная версия с поддержкой всех типов поиска в Google и Yandex.
📊 Сравнение с оригинальной библиотекой
| Функция | Оригинал | XMLRiver Pro |
|---|---|---|
| 🔍 Органический поиск | ✅ | ✅ Улучшенный |
| 📰 Новости | ✅ | ✅ С фильтрами времени |
| 🖼️ Изображения | ✅ | ✅ Расширенные параметры |
| 🗺️ Карты | ✅ | ✅ С координатами |
| 📢 Реклама | ✅ | ✅ Верхние и нижние блоки |
| 🧩 Специальные блоки | ❌ | ✅ OneBox, Knowledge Graph |
| ⚡ Асинхронность | ❌ | ✅ Полная поддержка |
| 🔄 Retry механизм | ❌ | ✅ Экспоненциальный backoff |
| 🛡️ Ограничение потоков | ❌ | ✅ Максимум 10 одновременных |
| 📊 Типизация | ❌ | ✅ 100% типизирован |
| 🧪 Тесты | ❌ | ✅ 66 тестов, 57% покрытие |
Поддерживает все типы поиска:
- 🔍 Органический поиск
- 📰 Новости с фильтрами времени
- 🖼️ Изображения (размер, цвет, тип)
- 🗺️ Карты с координатами
- 📢 Рекламные блоки
- 🧩 Специальные блоки (OneBox, Knowledge Graph)
- 📊 Yandex Wordstat - частотность и динамика запросов
- ⚡ Асинхронная поддержка с ограничением потоков
✨ Ключевые особенности
- ⚡ Асинхронная поддержка с ограничением потоков (максимум 10)
- 🔄 Retry механизм с экспоненциальным backoff
- 🛡️ Валидация параметров и обработка ошибок
- 📊 Форматирование результатов поиска
- 🎯 100% покрытие API - все методы XMLRiver
- 🚀 Высокая производительность - оптимизированные запросы
- ✅ Полная типизация для Python 3.10+
- 🏛️ Модульная архитектура с четким разделением
- 🧪 66 тестов с покрытием 57%
📦 Установка
📦 Из PyPI (рекомендуется):
# Установка последней версии
pip install xmlriver-pro
# Установка конкретной версии
pip install xmlriver-pro==1.2.7
🔧 Из исходного кода:
git clone https://github.com/Eapwrk/xmlriver-pro.git
cd xmlriver-pro
pip install -e .
📋 Зависимости:
- Python 3.10+
- requests
- aiohttp (для асинхронных клиентов)
- xmltodict
- python-dotenv
🚀 Быстрый старт
🔑 Получение API ключей
- Зарегистрируйтесь на xmlriver.com
- Получите
user_idиapi_keyв личном кабинете - Пополните баланс для использования API
🔧 Переменные окружения
Создайте файл .env:
XMLRIVER_USER_ID=your_user_id_here
XMLRIVER_API_KEY=your_api_key_here
📝 Базовые примеры
Асинхронный поиск
import asyncio
from xmlriver_pro import AsyncGoogleClient, AsyncYandexClient
async def main():
# Google асинхронный поиск
async with AsyncGoogleClient(user_id=123, api_key="your_key") as google:
results = await google.search("python programming")
print(f"Найдено: {results.total_results} результатов")
# Yandex асинхронный поиск
async with AsyncYandexClient(user_id=123, api_key="your_key") as yandex:
results = await yandex.search("программирование python")
print(f"Найдено: {results.total_results} результатов")
asyncio.run(main())
Поиск новостей
import asyncio
from xmlriver_pro import AsyncGoogleClient, AsyncYandexClient
from xmlriver_pro.core.types import TimeFilter
async def main():
# Google новости
async with AsyncGoogleClient(user_id=123, api_key="your_key") as google:
results = await google.search_news("python", time_filter=TimeFilter.LAST_WEEK)
for news in results.results:
print(f"{news.title}: {news.url}")
# Yandex новости
async with AsyncYandexClient(user_id=123, api_key="your_key") as yandex:
results = await yandex.search_news("python")
for news in results.results:
print(f"{news.title}: {news.url}")
asyncio.run(main())
Поиск изображений
import asyncio
from xmlriver_pro import AsyncGoogleClient
async def main():
async with AsyncGoogleClient(user_id=123, api_key="your_key") as google:
results = await google.search_images("python logo", num_results=20)
for image in results.results:
print(f"{image.title}: {image.img_url}")
asyncio.run(main())
Поиск по картам
import asyncio
from xmlriver_pro import AsyncGoogleClient
async def main():
async with AsyncGoogleClient(user_id=123, api_key="your_key") as google:
results = await google.search_maps(
"python office",
coords=(37.7749, -122.4194),
zoom=12
)
for place in results.results:
print(f"{place.title}: {place.address}")
asyncio.run(main())
Рекламные блоки
import asyncio
from xmlriver_pro import AsyncGoogleClient, AsyncYandexClient
async def main():
# Google реклама
async with AsyncGoogleClient(user_id=123, api_key="your_key") as google:
results = await google.get_ads("python programming")
for ad in results.results:
print(f"{ad.title}: {ad.url}")
# Yandex реклама
async with AsyncYandexClient(user_id=123, api_key="your_key") as yandex:
results = await yandex.get_ads("программирование python")
for ad in results.results:
print(f"{ad.title}: {ad.url}")
asyncio.run(main())
Yandex Wordstat
import asyncio
from xmlriver_pro import AsyncWordstatClient
async def main():
async with AsyncWordstatClient(user_id=123, api_key="your_key") as client:
# Получение топов запросов
result = await client.get_words("python")
print(f"Associations: {len(result.associations)}")
print(f"Popular: {len(result.popular)}")
# Получение динамики
history = await client.get_history("python", period="month")
print(f"Total frequency: {history.total_value}")
# Получение частотности
frequency = await client.get_frequency("python")
print(f"Frequency: {frequency}")
asyncio.run(main())
🔧 Конфигурация
Основные параметры
| Параметр | Описание | По умолчанию |
|---|---|---|
user_id |
ID пользователя XMLRiver | Обязательный |
api_key |
API ключ XMLRiver | Обязательный |
timeout |
Таймаут запроса (сек) | 60 |
retry_count |
Количество повторов | 3 |
retry_delay |
Задержка между повторами (сек) | 1.0 |
max_concurrent |
Максимум одновременных запросов | 10 |
Пример конфигурации
import asyncio
from xmlriver_pro import AsyncGoogleClient
async def main():
async with AsyncGoogleClient(
user_id=123,
api_key="your_key",
timeout=60, # 60 секунд таймаут
max_retries=3, # 3 попытки
retry_delay=1.0, # 1 секунда между попытками
max_concurrent=5 # 5 одновременных запросов
) as client:
results = await client.search("python")
print(f"Найдено: {results.total_results}")
asyncio.run(main())
Переменные окружения
import os
import asyncio
from dotenv import load_dotenv
from xmlriver_pro import AsyncGoogleClient
load_dotenv()
async def main():
async with AsyncGoogleClient(
user_id=int(os.getenv("XMLRIVER_USER_ID")),
api_key=os.getenv("XMLRIVER_API_KEY")
) as client:
results = await client.search("python")
print(f"Найдено: {results.total_results}")
asyncio.run(main())
💡 Примеры использования
Мониторинг потоков (асинхронные клиенты)
async with AsyncGoogleClient(user_id=123, api_key="your_key") as client:
# Проверяем статус потоков
status = client.get_concurrent_status()
print(f"Активных запросов: {status['active_requests']}")
print(f"Доступных слотов: {status['available_slots']}")
Основные валидаторы
from xmlriver_pro.utils import validate_coords, validate_zoom, validate_url
# Валидация координат
coords = (55.7558, 37.6176)
if validate_coords(coords):
print("Координаты валидны")
# Валидация zoom
if validate_zoom(12):
print("Zoom валиден")
# Валидация URL
if validate_url("https://python.org"):
print("URL валиден")
Основные форматтеры
from xmlriver_pro.utils import format_search_response, format_ads_response
# Форматирование результатов поиска
formatted_results = format_search_response(search_results)
# Форматирование рекламных блоков
formatted_ads = format_ads_response(ads_response)
📊 Типы данных
Основные типы результатов
from xmlriver_pro.core.types import (
SearchResult, NewsResult, ImageResult, MapResult,
AdResult, AdsResponse, SearchResponse
)
# SearchResult - результат органического поиска
result = SearchResult(
rank=1,
url="https://python.org",
title="Python Programming Language",
snippet="Python is a programming language...",
content_type="organic",
stars=4.8
)
# NewsResult - результат поиска новостей
news = NewsResult(
rank=1,
url="https://news.example.com",
title="Python News",
snippet="Latest Python updates...",
pub_date="2024-01-15"
)
# ImageResult - результат поиска изображений
image = ImageResult(
rank=1,
url="https://example.com/image.jpg",
title="Python Logo",
snippet="Official Python logo",
image_url="https://example.com/logo.png",
image_size="large"
)
# MapResult - результат поиска по картам
map_result = MapResult(
rank=1,
url="https://maps.google.com/...",
title="Python Office",
snippet="Python Software Foundation office",
coords=(37.7749, -122.4194),
address="San Francisco, CA"
)
# AdResult - рекламный результат
ad = AdResult(
rank=1,
url="https://ad.example.com",
title="Python Course",
snippet="Learn Python programming",
ad_type="top"
)
Перечисления (Enums)
from xmlriver_pro.core.types import (
SearchType, TimeFilter, DeviceType, OSType
)
# Типы поиска
search_type = SearchType.ORGANIC # ORGANIC, NEWS, IMAGES, MAPS, ADS
# Фильтры времени для новостей
time_filter = TimeFilter.LAST_WEEK # LAST_DAY, LAST_WEEK, LAST_MONTH, LAST_YEAR
# Типы устройств
device = DeviceType.DESKTOP # DESKTOP, MOBILE, TABLET
# Операционные системы
os_type = OSType.WINDOWS # WINDOWS, MACOS, LINUX, ANDROID, IOS
⚠️ Обработка ошибок
import asyncio
import logging
from xmlriver_pro import AsyncGoogleClient
from xmlriver_pro.core import (
XMLRiverError, AuthenticationError, RateLimitError,
NoResultsError, NetworkError, ValidationError,
InsufficientFundsError, ServiceUnavailableError
)
logger = logging.getLogger(__name__)
async def main():
async with AsyncGoogleClient(user_id=123, api_key="key") as google:
try:
results = await google.search("python")
except AuthenticationError as e:
# Ошибка аутентификации (коды 31, 42, 45)
logger.error(f"Authentication failed: {e}")
except RateLimitError as e:
# Превышен лимит запросов (коды 110, 111, 115)
logger.warning(f"Rate limit exceeded: {e}")
except NoResultsError as e:
# Нет результатов поиска (код 15)
logger.info(f"No results found: {e}")
except InsufficientFundsError as e:
# Недостаточно средств (код 200)
logger.error(f"Insufficient funds: {e}")
except ServiceUnavailableError as e:
# Сервис недоступен (коды 101, 201)
logger.warning(f"Service unavailable: {e}")
except NetworkError as e:
# Ошибка сети (коды 500, 202) - требует повтора
logger.error(f"Network error: {e}")
except ValidationError as e:
# Ошибка валидации параметров (коды 2, 102-108, 120, 121)
logger.error(f"Validation error: {e}")
asyncio.run(main())
📊 Статистика и мониторинг
import asyncio
from xmlriver_pro import AsyncGoogleClient, AsyncYandexClient
async def main():
async with AsyncGoogleClient(user_id=123, api_key="your_key") as google:
# Получение баланса (один на весь аккаунт)
balance = await google.get_balance()
print(f"Баланс: {balance} руб.")
# Получение стоимости Google запросов
google_cost = await google.get_cost()
print(f"Стоимость Google: {google_cost} руб/1000 запросов")
async with AsyncYandexClient(user_id=123, api_key="your_key") as yandex:
# Получение стоимости Yandex запросов (разная для каждой системы)
yandex_cost = await yandex.get_cost()
print(f"Стоимость Yandex: {yandex_cost} руб/1000 запросов")
asyncio.run(main())
⚡ Ограничения API
🔢 Потоки и производительность:
- Максимум потоков: 10 для каждой системы (Google, Yandex, Wordstat)
- Дневные лимиты:
- Google: ~200,000 запросов/сутки
- Yandex: ~150,000 запросов/сутки
- Скорость ответа: 3-6 секунд (обычно), максимум 60 секунд
⏱️ Рекомендации по таймаутам:
import asyncio
from xmlriver_pro import AsyncGoogleClient
async def main():
# Используйте таймаут 60 секунд для надежности
async with AsyncGoogleClient(user_id=123, api_key="key", timeout=60) as google:
results = await google.search("python")
# При низком таймауте есть риск потерять ответы
# Деньги за запрос снимаются, но результат может не прийти
asyncio.run(main())
🚨 Обработка ошибок потоков:
import asyncio
from xmlriver_pro import AsyncGoogleClient
from xmlriver_pro.core import RateLimitError
async def main():
async with AsyncGoogleClient(user_id=123, api_key="key") as google:
try:
results = await google.search("python")
except RateLimitError as e:
if e.code in [110, 111, 115]:
# Временные ошибки потоков - повторите запрос
await asyncio.sleep(5) # Подождите 5 секунд
results = await google.search("python") # Повторите
asyncio.run(main())
🧪 Тестирование
✅ Безопасное тестирование (БЕЗ реальных API запросов)
# Запуск всех тестов (БЕЗ real_api, по умолчанию)
pytest
# Запуск с покрытием
pytest --cov=xmlriver_pro
# Запуск конкретных тестов
pytest tests/test_google.py
pytest tests/test_yandex.py
# Запуск с детальным выводом
pytest -v
✅ Эти команды БЕЗОПАСНЫ и НЕ требуют API ключей
⚠️ Real API тесты (требуют ключи и СТОЯТ ДЕНЕГ!)
# ⚠️ ВНИМАНИЕ: следующие команды делают реальные API запросы и ТРАТЯТ ДЕНЬГИ!
pytest -m real_api -v # Запуск ТОЛЬКО real_api тестов (~$5-10)
📖 Полная документация по тестированию: TESTING.md
- Подробное описание всех типов тестов
- Инструкции по настройке Real API тестов
- Защитные механизмы и best practices
📚 Документация
- README.md - основная документация (этот файл)
- docs/README.md - обзор всей документации
- docs/examples.md - детальные примеры всех методов
- docs/API_REFERENCE.md - полный справочник API
- docs/ADVANCED_USAGE.md - продвинутые сценарии
- docs/SPECIAL_BLOCKS_GUIDE.md - специальные блоки
- docs/WORDSTAT_GUIDE.md - руководство по Wordstat API
- docs/VALIDATORS_REFERENCE.md - все валидаторы
- docs/FORMATTERS_REFERENCE.md - все форматтеры
- docs/TROUBLESHOOTING.md - решение проблем
- Исходный код - полный код с комментариями
🤝 Вклад в проект
Issues и Pull Requests приветствуются на GitHub.
Установка для разработки
git clone https://github.com/Eapwrk/xmlriver-pro.git
cd xmlriver-pro
pip install -e ".[dev]"
pre-commit install
Запуск тестов
pytest
📄 Лицензия
MIT License. Подробности в LICENSE.
🙏 Благодарности
- xmlriver.com за предоставление API
- Python сообществу за экосистему
- Контрибьюторам проекта
📞 Поддержка
- 📧 Email: seo@controlseo.ru
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
📈 Статистика проекта
XMLRiver Pro - Professional Python client for XMLRiver API
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xmlriver_pro-2.1.0.tar.gz.
File metadata
- Download URL: xmlriver_pro-2.1.0.tar.gz
- Upload date:
- Size: 128.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a73456064f1e20ba43832b97a01645ea66460ab27edb59bab334965f6c0174e8
|
|
| MD5 |
fc299f30feb88f771257bb333e50bcb5
|
|
| BLAKE2b-256 |
bc5932af82ade7978fa251a013e4000a7760406595e814af7292b6c8237c2ef8
|
File details
Details for the file xmlriver_pro-2.1.0-py3-none-any.whl.
File metadata
- Download URL: xmlriver_pro-2.1.0-py3-none-any.whl
- Upload date:
- Size: 93.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f34c152df30ead9d8355e16d08e1bccdc1ebcc269ae886f4664088da1ec4533f
|
|
| MD5 |
8f08d4a67cfa57662c2295eee5f5cdde
|
|
| BLAKE2b-256 |
1349979ecd441cee637c6531cab7c8cd97616a1c37e7d4eaf4e49cc2ec6ababe
|