Парсинг блокчейн-данных: от API до собственной ноды

При выгрузке истории с блокчейн-эксплореров мы сталкивались с жёсткими ограничениями: Etherscan отдаёт максимум 10000 записей на запрос, 5 запросов в секунду на бесплатном плане, нет стриминга. Если нужно собрать все транзакции контракта USDT за последние три года — это более 30 миллионов записей. Д

Направления блокчейн-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1451
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1309
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1005
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1270
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    719
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1011

При выгрузке истории с блокчейн-эксплореров мы сталкивались с жёсткими ограничениями: Etherscan отдаёт максимум 10000 записей на запрос, 5 запросов в секунду на бесплатном плане, нет стриминга. Если нужно собрать все транзакции контракта USDT за последние три года — это более 30 миллионов записей. Для анализа DeFi-стратегий или отслеживания транзакций китов нужны миллионы записей — стандартные API не справляются. Простое решение не работает: пагинация через page не даст больше 10000. Нужна стратегия, и мы её нашли: пагинация по блокам с последующей дедупликацией.

В этой статье разберём основные подходы: от прямого Etherscan API до использования Alchemy и Moralis, а также парсинг HTML и работу с собственной нодой. Каждый метод отличается по скорости, полноте и стоимости. Например, Alchemy позволяет получить все транзакции адреса одним запросом без лимита записей, а собственная нода даёт доступ к внутренним вызовам.

Alchemy обходит Etherscan по всем параметрам: в 5 раз выше rate limit, нет лимита записей благодаря pageKey, поддержка WebSocket стриминга и кросс-чейн запросов. Для проектов, требующих максимальной производительности, Alchemy — безальтернативный выбор.

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

Как обойти ограничение Etherscan API в 10000 записей?

Etherscan предоставляет параметры startblock и endblock. Пагинация по блокам позволяет вытянуть все транзакции. Код ниже перебирает блоки, увеличивая startblock до последнего встреченного:

import httpx import asyncio from typing import AsyncGenerator async def get_all_transactions( address: str, api_key: str, start_block: int = 0 ) -> AsyncGenerator[dict, None]: """Выгрузка ВСЕХ транзакций адреса через пагинацию по блокам""" base_url = "https://api.etherscan.io/api" current_block = start_block while True: async with httpx.AsyncClient() as client: resp = await client.get(base_url, params={ "module": "account", "action": "txlist", "address": address, "startblock": current_block, "endblock": 99999999, "sort": "asc", "apikey": api_key, "offset": 10000, "page": 1, }) data = resp.json() if data["status"] != "1" or not data["result"]: break txs = data["result"] for tx in txs: yield tx if len(txs) < 10000: break current_block = int(txs[-1]["blockNumber"]) + 1 await asyncio.sleep(0.2) 

Важный нюанс: если в одном блоке > 10000 транзакций на адрес — цикл зависнет. Для таких случаев нужна вложенная пагинация с параметром page внутри блока.

Почему стоит использовать Alchemy или Moralis вместо Etherscan?

Alchemy и Moralis снимают большинство ограничений Etherscan. Alchemy имеет rate limit 25 req/s, что в 5 раз превышает лимит Etherscan (5 req/s). Вот сравнение:

Параметр Etherscan (free) Alchemy (free tier) Moralis (free tier)
Лимит записей 10000 Нет (pageKey) Нет (cursor)
Rate limit 5 req/s 25 req/s 100 requests/min
Streaming Нет WebSocket (Enhanced API) WebSocket (Real-time)
Кросс-чейн Нет Да Да

Alchemy getAssetTransfers возвращает ETH + ERC-20 + ERC-721 одним вызовом.

import { Alchemy, Network } from 'alchemy-sdk'; const alchemy = new Alchemy({ apiKey: process.env.ALCHEMY_KEY, network: Network.ETH_MAINNET }); const transfers = await alchemy.core.getAssetTransfers({ fromAddress: '0x...', category: ['external', 'erc20', 'erc721', 'erc1155'], withMetadata: true, maxCount: 1000, }); if (transfers.pageKey) { const more = await alchemy.core.getAssetTransfers({ pageKey: transfers.pageKey, }); } 

Alchemy Asset Transfers API рекомендует использовать pageKey для пагинации. Moralis дополнительно отдаёт внутренние транзакции через getWalletTransactionsVerbose. Для быстрой оценки масштаба свяжитесь с нами — мы подготовим прототип за 2 дня.

Когда парсинг HTML-страниц оправдан?

Если API не отдаёт держателей токенов или verified-контракты, используем парсинг HTML. Следующий пример собирает держателей токена с Etherscan:

import httpx from bs4 import BeautifulSoup import asyncio async def get_token_holders(token_address: str, pages: int = 10) -> list[dict]: headers = { "User-Agent": "Mozilla/5.0", } holders = [] async with httpx.AsyncClient(headers=headers) as client: for page in range(1, pages + 1): resp = await client.get( f"https://etherscan.io/token/{token_address}", params={"a": "#holders", "p": page} ) soup = BeautifulSoup(resp.text, 'html.parser') table = soup.find('table', {'id': 'holdersTable'}) if not table: break for row in table.find_all('tr')[1:]: cols = row.find_all('td') if len(cols) >= 3: holders.append({ 'rank': cols[0].text.strip(), 'address': cols[1].find('a')['href'].split('/')[-1], 'quantity': cols[2].text.strip(), }) await asyncio.sleep(2) return holders 

Etherscan защищается Cloudflare — для объёмного сбора нужны резидентные прокси или официальное API. Парсинг BscScan и Solscan работает по аналогии.

Как избежать дублей при параллельном сборе?

При параллельном сборе из нескольких источников дубли неизбежны. Используем ON CONFLICT в PostgreSQL:

CREATE TABLE eth_transactions ( tx_hash CHAR(66) PRIMARY KEY, block_number BIGINT NOT NULL, from_address CHAR(42) NOT NULL, to_address CHAR(42), value NUMERIC(38) DEFAULT 0, gas_used BIGINT, status SMALLINT, ts TIMESTAMPTZ ); INSERT INTO eth_transactions VALUES (...) ON CONFLICT (tx_hash) DO NOTHING; 

Для событий уникальный ключ — (tx_hash, log_index).

Прямая работа с нодой

Для максимальной полноты (внутренние транзакции, storage slots, MEV) ставим собственную ноду с Erigon и --tracing. Это даёт:

  • Все internal transactions без лимитов
  • Трассировку вызовов
  • Данные из storage
curl -X POST $ETH_RPC_URL \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_getBlockReceipts","params":["0x1234567"],"id":1}' 

eth_getBlockReceipts EIP-1559 возвращает все receipts блока одним запросом — альтернатива N отдельных вызовов eth_getTransactionReceipt.

Какие этапы включает сбор данных?

Этап Описание Срок
Анализ источников Определение необходимых данных и их расположения (API, HTML, нода) 1-2 дня
Выбор инструментов Etherscan API, Alchemy, Moralis или собственная нода 1 день
Написание парсера Асинхронный сбор с учётом rate limit и пагинации 2-5 дней
Дедупликация и нормализация Склеивание данных в единую схему 1-2 дня
Тестирование на реальном объёме Миллионы транзакций, проверка на пропуски 2-3 дня
Деплой Контейнеризация, мониторинг, автоматический перезапуск 1-2 дня

Наш процесс занимает от 3 до 10 дней в зависимости от сложности.

Что входит в результат

  • Документация по схеме данных и методам сбора.
  • Готовый код на Python/TypeScript с поддержкой асинхронности.
  • Настройка пагинации под каждый эксплорер.
  • Деплой на сервер или в облако (AWS Lambda, Kubernetes).
  • Обучение команды работе с системой.
  • Поддержка в течение месяца после сдачи.

Наш опыт — более 30 проектов по сбору и анализу данных on-chain. Получите консультацию — мы поможем выбрать оптимальный инструмент под вашу задачу. Закажите проект, и мы настроим сбор данных любой сложности.