Skip to main content

Professional Python client for XMLRiver API with full coverage

Project description

XMLRiver Pro

Python Version License Coverage

Fork of KursHub-ru/xmlriver

Python библиотека для работы с API xmlriver.com. Расширенная версия с поддержкой всех типов поиска.

Поддерживает все типы поиска в Google и Yandex: органический поиск, новости, изображения, карты, реклама и специальные блоки.

✨ Что умеет

  • 🔍 Органический поиск в Google и Yandex
  • 📰 Поиск по новостям с фильтрами времени
  • 🖼️ Поиск по изображениям (размер, цвет, тип)
  • 🗺️ Поиск по картам с координатами
  • 📢 Рекламные блоки (верхние и нижние)
  • 🧩 Специальные блоки (OneBox, Knowledge Graph)
  • Асинхронная поддержка с aiohttp
  • 🔄 Параллельные запросы с asyncio

🏗️ Особенности

  • ✅ Полная типизация для Python 3.10+
  • 🏛️ Модульная архитектура
  • 🧪 66 тестов с покрытием 57%
  • ⚠️ Специализированные исключения
  • ✔️ Валидация параметров
  • Синхронные и асинхронные клиенты
  • 🔄 Поддержка многопоточности и параллелизма

📦 Установка

📦 Из PyPI (рекомендуется):

# Установка последней версии
pip install xmlriver-pro

# Установка конкретной версии
pip install xmlriver-pro==1.1.1

# Обновление до последней версии
pip install --upgrade xmlriver-pro

🚀 Из GitHub:

# Установка последней версии
pip install git+https://github.com/Eapwrk/xmlriver-pro.git

# Установка конкретной версии
pip install git+https://github.com/Eapwrk/xmlriver-pro.git@v1.1.1

# Обновление до последней версии
pip install --upgrade git+https://github.com/Eapwrk/xmlriver-pro.git

🔍 Проверка версии:

python -c "import xmlriver_pro; print(xmlriver_pro.__version__)"

🔄 Обновления

📋 Как узнать об обновлениях:

📚 История изменений:

  • 📄 CHANGELOG.md - полная история изменений
  • 🏷️ GitHub Releases - релизы с описанием
  • 🔄 Semantic Versioning - мажорные.минорные.патч версии

🚀 Как обновляться:

# Проверить текущую версию
pip show xmlriver-pro

# Обновить до последней версии
pip install --upgrade xmlriver-pro

# Обновить до конкретной версии
pip install xmlriver-pro==1.1.0

Для разработки:

git clone https://github.com/Eapwrk/xmlriver-pro.git
cd xmlriver-pro
pip install -e .

🔧 Зависимости

Основные:

  • requests - HTTP запросы к API
  • xmltodict - парсинг XML ответов
  • aiohttp - асинхронные HTTP запросы

Для разработки:

  • pytest - тестирование
  • black - форматирование кода
  • pylint - анализ кода
  • mypy - проверка типов

⚙️ Конфигурация

Переменные окружения

Для удобства тестирования и разработки можно использовать переменные окружения:

# Создайте файл .env в корне проекта
XMLRIVER_USER_ID=6881
XMLRIVER_API_KEY=your_api_key_here
import os
from dotenv import load_dotenv

# Загружаем переменные окружения
load_dotenv()

# Используем в коде
user_id = int(os.getenv("XMLRIVER_USER_ID", "0"))
api_key = os.getenv("XMLRIVER_API_KEY", "")

client = GoogleClient(user_id, api_key)

Все клиенты поддерживают настройку retry механизма и таймаутов:

Параметры конфигурации:

Параметр Тип По умолчанию Описание
timeout int 60 Таймаут запроса в секундах (максимум 60)
max_retries int 3 Максимальное количество попыток повтора
retry_delay float 1.0 Базовая задержка между попытками в секундах
enable_retry bool True Включить автоматические повторы
max_concurrent int 10 Максимум одновременных запросов (жесткое ограничение)

Экспоненциальный backoff:

При включенном retry используется экспоненциальная задержка:

  • 1-я попытка: retry_delay * 1 = 1.0 сек
  • 2-я попытка: retry_delay * 2 = 2.0 сек
  • 3-я попытка: retry_delay * 4 = 4.0 сек
  • 4-я попытка: retry_delay * 8 = 8.0 сек

Примеры конфигурации:

# Стандартная конфигурация (рекомендуется)
client = GoogleClient(user_id=123, api_key="key")

# Кастомные настройки retry
client = GoogleClient(
    user_id=123, 
    api_key="key",
    timeout=120,        # 2 минуты
    max_retries=5,      # 5 попыток
    retry_delay=2.0,    # базовая задержка 2 сек
    max_concurrent=5    # максимум 5 одновременных запросов
)

# Отключить retry для продвинутых пользователей
client = GoogleClient(
    user_id=123, 
    api_key="key",
    enable_retry=False  # без повторов
)

# Асинхронный клиент с настройками
async with AsyncGoogleClient(
    user_id=123,
    api_key="key", 
    max_retries=3,
    retry_delay=1.5,
    max_concurrent=8
) as client:
    result = await client.search("python")

🚀 Быстрый старт

from xmlriver_pro import GoogleClient, YandexClient

# Инициализация клиентов
google = GoogleClient(user_id=123, api_key="your_google_key")
yandex = YandexClient(user_id=123, api_key="your_yandex_key")

# Органический поиск
google_results = google.search("python programming")
yandex_results = yandex.search("программирование на python")

# Результаты поиска
google_count = google_results.total_results
yandex_count = yandex_results.total_results

⚡ Асинхронное использование

Базовый асинхронный поиск

import asyncio
from xmlriver_pro import AsyncGoogleClient, AsyncYandexClient

async def main():
    # Google поиск
    async with AsyncGoogleClient(user_id=123, api_key="your_google_key") as google:
        results = await google.search("python programming")
        print(f"Google: {results.total_results} результатов")
    
    # Yandex поиск
    async with AsyncYandexClient(user_id=123, api_key="your_yandex_key") as yandex:
        results = await yandex.search("программирование на python")
        print(f"Yandex: {results.total_results} результатов")

# Запуск
asyncio.run(main())

Параллельные запросы

import asyncio
from xmlriver_pro import AsyncGoogleClient

async def parallel_search():
    async with AsyncGoogleClient(user_id=123, api_key="your_key") as google:
        # Создаем задачи для параллельного выполнения
        tasks = [
            google.search("python programming"),
            google.search("machine learning"),
            google.search("data science")
        ]
        
        # Выполняем все задачи параллельно
        results = await asyncio.gather(*tasks)
        
        for i, result in enumerate(results):
            print(f"Запрос {i+1}: {result.total_results} результатов")

asyncio.run(parallel_search())

Смешанный поиск Google + Yandex

import asyncio
from xmlriver_pro import AsyncGoogleClient, AsyncYandexClient

async def mixed_search():
    query = "программирование на python"
    
    async with AsyncGoogleClient(user_id=123, api_key="google_key") as google, \
             AsyncYandexClient(user_id=123, api_key="yandex_key") as yandex:
        
        # Поиск в обеих системах параллельно
        google_task = google.search(query)
        yandex_task = yandex.search(query)
        
        google_results, yandex_results = await asyncio.gather(
            google_task, yandex_task
        )
        
        print(f"Google: {google_results.total_results} результатов")
        print(f"Yandex: {yandex_results.total_results} результатов")

asyncio.run(mixed_search())

📰 Поиск по новостям

from xmlriver_pro import GoogleNews, YandexNews
from xmlriver_pro.core.types import TimeFilter

google_news = GoogleNews(user_id=123, api_key="your_key")
news_results = google_news.search_news("python", time_filter=TimeFilter.LAST_WEEK)

yandex_news = YandexNews(user_id=123, api_key="your_key")
yandex_news_results = yandex_news.search_news_last_day("python новости")

🖼️ Поиск по изображениям

from xmlriver_pro import GoogleImages

images = GoogleImages(user_id=123, api_key="your_key")

image_results = images.search_images("python logo", count=20)
large_images = images.search_images_by_size("python logo", "large")
color_images = images.search_images_by_color("python logo", "blue")

🗺️ Поиск по картам

from xmlriver_pro import GoogleMaps

maps = GoogleMaps(user_id=123, api_key="your_key")

map_results = maps.search_maps(
    query="кафе Москва",
    zoom=12,
    coords=(55.7558, 37.6176)
)

nearby_cafes = maps.search_nearby("кафе", coords=(55.7558, 37.6176), radius=1000)

📢 Рекламные блоки

from xmlriver_pro import GoogleAds, YandexAds

google_ads = GoogleAds(user_id=123, api_key="your_key")
ads_response = google_ads.get_ads("python programming")

yandex_ads = YandexAds(user_id=123, api_key="your_key")
yandex_ads_response = yandex_ads.get_ads("программирование python")

🧩 Специальные блоки

from xmlriver_pro import GoogleSpecialBlocks, YandexSpecialBlocks

# Google специальные блоки
google_special = GoogleSpecialBlocks(user_id=123, api_key="your_key")

# OneBox документы
onebox_docs = google_special.get_onebox_documents("python", ["organic", "video"])

# Knowledge Graph
kg = google_special.get_knowledge_graph("Python programming language")

# Калькулятор
calc_result = google_special.get_calculator("2 + 2")

# Yandex колдунщики
yandex_special = YandexSpecialBlocks(user_id=123, api_key="your_key")

# Погода
weather = yandex_special.get_weather("погода Москва")

# Переводчик
translation = yandex_special.get_translator("hello world")

🔧 Расширенные возможности

✔️ Валидация параметров

from xmlriver_pro.utils import validate_coords, validate_zoom, validate_url

# Валидация координат
coords = (55.7558, 37.6176)
if validate_coords(coords):
    # Координаты валидны

# Валидация zoom
if validate_zoom(12):
    # Zoom валиден

# Валидация URL
if validate_url("https://python.org"):
    # 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 import (
    XMLRiverError, AuthenticationError, RateLimitError, 
    NoResultsError, NetworkError, ValidationError,
    InsufficientFundsError, ServiceUnavailableError
)

try:
    results = 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}")

📊 Статистика и мониторинг

# Получение баланса (один на весь аккаунт)
balance = google.get_balance()  # или yandex.get_balance() - результат одинаковый

# Получение стоимости (разная для каждой системы)
google_cost = google.get_cost()  # Стоимость Google запросов
yandex_cost = yandex.get_cost()  # Стоимость Yandex запросов

# Получение информации об ограничениях API
limits = google.get_api_limits()
print(f"Максимум потоков: {limits['max_concurrent_streams']}")
print(f"Дневной лимит Google: {limits['daily_limits']['google']:,} запросов")
print(f"Дневной лимит Yandex: {limits['daily_limits']['yandex']:,} запросов")

# Проверка индексации
is_indexed = google.check_indexing("https://python.org")

# Проверка доверия к домену
is_trusted = google.is_trust_domain("python.org")

⚡ Ограничения API

🔢 Потоки и производительность:

  • Максимум потоков: 10 для каждой системы (Google, Yandex, Wordstat)
  • Дневные лимиты:
    • Google: ~200,000 запросов/сутки
    • Yandex: ~150,000 запросов/сутки
  • Скорость ответа: 3-6 секунд (обычно), максимум 60 секунд

⏱️ Рекомендации по таймаутам:

# Используйте таймаут 60 секунд для надежности
google = GoogleClient(user_id=123, api_key="key", timeout=60)

# При низком таймауте есть риск потерять ответы
# Деньги за запрос снимаются, но результат может не прийти

🚨 Обработка ошибок потоков:

try:
    results = google.search("python")
except RateLimitError as e:
    if e.code in [110, 111, 115]:
        # Временные ошибки потоков - повторите запрос
        time.sleep(5)  # Подождите 5 секунд
        results = google.search("python")  # Повторите

🧪 Тестирование

# Запуск всех тестов
pytest

# Запуск с покрытием
pytest --cov=xmlriver_pro

# Запуск конкретных тестов
pytest tests/test_google.py
pytest tests/test_yandex.py

# Запуск с детальным выводом
pytest -v

📚 Документация

🤝 Вклад в проект

Issues и Pull Requests приветствуются на GitHub.

Установка для разработки

git clone https://github.com/Eapwrk/xmlriver-pro.git
cd xmlriver-pro
pip install -e ".[dev]"
pre-commit install

Запуск тестов

pytest
black xmlriver_pro tests
pylint xmlriver_pro
mypy xmlriver_pro

📄 Лицензия

MIT License. Подробности в LICENSE.

🙏 Благодарности

  • xmlriver.com за предоставление API
  • Python сообществу за экосистему
  • Контрибьюторам проекта

📞 Поддержка


XMLRiver Pro - Python клиент для API xmlriver.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xmlriver_pro-1.2.4.tar.gz (64.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xmlriver_pro-1.2.4-py3-none-any.whl (71.2 kB view details)

Uploaded Python 3

File details

Details for the file xmlriver_pro-1.2.4.tar.gz.

File metadata

  • Download URL: xmlriver_pro-1.2.4.tar.gz
  • Upload date:
  • Size: 64.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.8

File hashes

Hashes for xmlriver_pro-1.2.4.tar.gz
Algorithm Hash digest
SHA256 e7dcac68a72514f0584e6605fd150f12f80e5171534e6e1e07bc0bdc06c13428
MD5 49c94a7db9b11bf302eea1f91709fda9
BLAKE2b-256 45c48257743f11b0e0dd1c802f2efecd33c64698f0e2293c951ac03766b8d9fc

See more details on using hashes here.

File details

Details for the file xmlriver_pro-1.2.4-py3-none-any.whl.

File metadata

  • Download URL: xmlriver_pro-1.2.4-py3-none-any.whl
  • Upload date:
  • Size: 71.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.8

File hashes

Hashes for xmlriver_pro-1.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 e96cfbd1beed5c8d06edb6ada2d465c1941847baf283422a7ccd58364c89d520
MD5 13312f5f2d21ced0d8d3843504486afe
BLAKE2b-256 335469c9e7d881d9502c531ac9501ad3eff509bf3319213ef89b583ebb80bcea

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page