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

При вивантаженні історії з блокчейн-експлорерів ми стикалися з жорсткими обмеженнями: Etherscan віддає максимум 10 000 записів на запит, 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 віддає максимум 10 000 записів на запит, 5 запитів на секунду на безкоштовному плані, немає стрімінгу. Якщо потрібно зібрати всі транзакції контракту USDT за останні три роки — це понад 30 мільйонів записів. Для аналізу DeFi-стратегій або відстеження транзакцій китів потрібні мільйони записів — стандартні API не справляються. Просте рішення не працює: пагінація через page не дасть більше 10 000. Потрібна стратегія, і ми її знайшли: пагінація по блоках з подальшою дедуплікацією.

У цій статті розберемо основні підходи: від прямого Etherscan API до використання Alchemy та Moralis, а також парсинг HTML і роботу з власною нодою. Кожен метод відрізняється за швидкістю, повнотою та вартістю. Наприклад, Alchemy дозволяє отримати всі транзакції адреси одним запитом без ліміту записів, а власна нода дає доступ до внутрішніх викликів.

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

Якщо вам потрібно зібрати історичні дані для аналізу — зв'яжіться з нами, ми підберемо оптимальний інструмент за один день.

Як обійти обмеження Etherscan API у 10 000 записів?

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) 

Важливий нюанс: якщо в одному блоці > 10 000 транзакцій на адресу — цикл зависне. Для таких випадків потрібна вкладена пагінація з параметром 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. Отримайте консультацію — ми допоможемо вибрати оптимальний інструмент під ваше завдання. Замовте проект, і ми налаштуємо збір даних будь-якої складності.