以太坊鏈上數據分析實務:從區塊瀏覽器到 Python 實作,用數據說話

本文從實務角度出發,介紹以太坊鏈上數據分析的工具與方法。涵蓋 Etherscan 進階功能、Dune Analytics SQL 查詢、Nansen 巨鯨追蹤、以及 Python 實作程式碼範例。提供完整的代碼示例,幫助讀者建立自己的鏈上數據分析系統。

以太坊鏈上數據分析實務:從區塊瀏覽器到 Python 實作,用數據說話

為什麼我要學鏈上數據分析

說真的,網上那些「老師帶你炒幣」的內容看多了,你會發現一個規律——那些真正賺錢的人,很少是靠「感覺」在做決策的。他們看的是數據、是鏈上活動、是真實的資金流向。

學會分析鏈上數據,不僅能幫你看清市場情緒,還能讓你識別哪些 DeFi 協議真正有資金流入、哪些項目在偷偷抛售、代幣大戶都在買什麼。這些資訊是公開的,只是不會主動送到你面前。

這篇文章我就來手把手教你從零開始做以太坊鏈上數據分析,用的都是實實在在的工具和代碼,沒有那種「老師用 PPT 教你」的空洞內容。

基礎工具:Etherscan 其實很強大

很多人只把 Etherscan 當成查餘額的工具,這簡直是暴殄天物。

Etherscan 的隱藏功能

Etherscan 進階功能清單:

1. 區塊燃料費分析
   - 區塊頁面顯示 Gas 使用量
   - 可觀察網路擁塞程度
   - 歷史 Gas 費用走勢

2. 智慧合約互動
   - Read Contract / Write Contract
   - 不需要錢包就能讀取合約狀態
   - 可以直接調用函數

3. 交易指紋分析
   - Internal Transactions(內部調用)
   - ERC-20 Transfer Events
   - NFT Transfer Events

4. 錢包標籤系統
   - 看某個地址是什麼
   - 交易所地址有標記
   - 巨鯨地址有記錄

實際操作:分析一個代幣的真實持倉

假設你想分析某個 ERC-20 代幣的持倉分佈,Etherscan 就能做到:

步驟:
1. 進入 Token 頁面
2. 點擊 "Holders" 分頁
3. 查看前 100 大持倉

常見問題信號:
- 第 1 名持倉 > 50%:極度中心化
- 交易所持倉太高:流動性可能受限
- 合約地址持倉:可能是質押池或鎖倉

真實案例(某個 Meme 幣):
Top 10 持倉佔比:78%
第 1 名:32%(開發者地址)
交易所:25%(主要集中在幾家)
散戶分佈:極度分散

結論:這種持倉結構,一旦大戶抛售,價格必崩

追蹤穩定幣流向

穩定幣轉帳數據是市場情緒的重要指標。

分析 USDT/USDC 轉帳的意義:

USDT 轉入交易所 → 可能是賣出信號
USDT 轉出交易所 → 可能是抄底信號

查看方式:
1. Etherscan → USDT 合約地址
2. 過濾 Transfer 事件
3. 分析大額轉帳

注意:USDT 是 Omni 代幣(比特幣網路),不在以太坊上
但 USDC、DAI 等是以太坊原生

中級工具:區塊鏈數據查詢

當你需要更複雜的分析,Etherscan 就力不從心了。這時候要用專業工具。

Dune Analytics:用 SQL 查區塊鏈

Dune 是目前最流行的鏈上數據平台,任何人都可以用 SQL 查詢區塊鏈數據。

-- 查詢 Uniswap V3 的日交易量
SELECT 
    DATE_TRUNC('day', block_time) as day,
    COUNT(*) as trade_count,
    SUM(token_a_amount) as volume_token_a,
    SUM(token_b_amount) as volume_token_b
FROM dex.trades
WHERE 
    blockchain = 'ethereum'
    AND project = 'Uniswap'
    AND version = '3'
    AND token_a_symbol = 'WETH'
GROUP BY DATE_TRUNC('day', block_time)
ORDER BY day DESC
LIMIT 30
-- 分析某地址最近 100 筆交易
SELECT 
    block_time,
    case 
        when "from" = '\x1234567890123456789012345678901234567890' then 'Send'
        when "to" = '\x1234567890123456789012345678901234567890' then 'Receive'
        else 'Other'
    end as direction,
    value / 1e18 as eth_value,
    gas_price / 1e9 as gas_gwei,
    receipt_gas_used * gas_price / 1e18 as gas_cost_eth
FROM ethereum.transactions
WHERE 
    "from" = '\x1234567890123456789012345678901234567890'
    OR "to" = '\x1234567890123456789012345678901234567890'
ORDER BY block_time DESC
LIMIT 100

Nansen:巨鯨追蹤利器

Nansen 是付費工具,但數據維度比 Dune 深很多。

Nansen 核心功能:

1. 錢包標籤
   - 告訴你每個地址是誰
   - 交易所、項目方、巨鯨都有標記
   - 聰明錢追蹤

2. 標籤更新頻率
   - 大戶倉位變化即時通知
   - 新聞事件關聯
   - 社群情緒追蹤

3. 應用場景
   - 追蹤「聰明錢」在買什麼
   - 發現新興項目被大戶埋伏
   - 識別項目方是否在賣

進階實作:用 Python 跑自己的分析

當你需要定製化的分析,或者想自動化某些監控腳本,就要自己寫程式了。

環境設定

# 需要的套件
# pip install web3 pandas matplotlib requests

from web3 import Web3
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime

# 連接以太坊節點(使用 Infura 或 Alchemy)
ALCHEMY_API_KEY = "your_api_key_here"
w3 = Web3(Web3.HTTPProvider(f"https://eth-mainnet.g.alchemy.com/v2/{ALCHEMY_API_KEY}"))

# 確認連線
print(f"連線狀態:{w3.is_connected()}")
print(f"當前區塊高度:{w3.eth.block_number}")

實作一:追蹤某地址的 ETH 餘額變化

def track_address_balance(address, start_block, end_block):
    """
    追蹤某地址在指定區塊範圍內的 ETH 餘額變化
    """
    address = Web3.to_checksum_address(address)
    balances = []
    
    # 每 1000 個區塊取一個數據點
    step = 1000
    for block in range(start_block, end_block, step):
        try:
            balance = w3.eth.get_balance(address, block)
            balances.append({
                'block': block,
                'balance_eth': balance / 1e18,
                'timestamp': datetime.fromtimestamp(
                    w3.eth.get_block(block).timestamp
                )
            })
        except Exception as e:
            print(f"區塊 {block} 取得失敗:{e}")
    
    return pd.DataFrame(balances)

# 使用範例:追蹤某巨鯨地址
# 假設這是某交易所熱錢包
target_address = "0x28c6c06298d514db089934071355e5743bf21d60"  # Binance 熱錢包

df = track_address_balance(
    target_address,
    start_block=18000000,  # 2023年初
    end_block=w3.eth.block_number
)

# 繪製圖表
plt.figure(figsize=(12, 6))
plt.plot(df['timestamp'], df['balance_eth'])
plt.title(f"{target_address} ETH 餘額變化")
plt.xlabel("時間")
plt.ylabel("ETH 數量")
plt.grid(True)
plt.savefig('balance_history.png')

實作二:分析某 DEX 的交易模式

from web3 import Web3
import json

def get_uniswap_swap_events(start_block, end_block, pool_address):
    """
    取得 Uniswap V3 某 Pool 的所有 Swap 事件
    """
    # Uniswap V3 Pool 合約 ABI(只取需要的部分)
    pool_abi = json.loads('''[
        {
            "name": "Swap",
            "type": "event",
            "inputs": [
                {"name": "sender", "type": "address"},
                {"name": "recipient", "type": "address"},
                {"name": "amount0", "type": "int256"},
                {"name": "amount1", "type": "int256"},
                {"name": "sqrtPriceX96", "type": "uint160"},
                {"name": "liquidity", "type": "uint128"},
                {"name": "tick", "type": "int24"}
            ]
        }
    ]''')
    
    pool_address = Web3.to_checksum_address(pool_address)
    contract = w3.eth.contract(address=pool_address, abi=pool_abi)
    
    # 取得事件
    events = contract.events.Swap.get_logs(
        fromBlock=start_block,
        toBlock=end_block
    )
    
    return [
        {
            'block': event['blockNumber'],
            'transaction': event['transactionHash'].hex(),
            'sender': event['args']['sender'],
            'recipient': event['args']['recipient'],
            'amount0': event['args']['amount0'] / 1e18,  # 如果是 ETH 或代幣
            'amount1': event['args']['amount1'] / 1e18,
            'timestamp': datetime.fromtimestamp(
                w3.eth.get_block(event['blockNumber']).timestamp
            )
        }
        for event in events
    ]

# 使用範例:分析 ETH/USDC 池
# Uniswap V3 WETH/USDC 0.05% 費用層池
pool_address = "0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"

swaps = get_uniswap_swap_events(
    start_block=17000000,  # 2023年某個區塊
    end_block=18000000
)

df_swaps = pd.DataFrame(swaps)

# 分析:計算每小時的交易量
df_swaps.set_index('timestamp', inplace=True)
hourly_volume = df_swaps.resample('H')['amount0'].sum()

print(f"總交易筆數:{len(df_swaps)}")
print(f"總交易量(ETH):{df_swaps['amount0'].abs().sum():.2f}")
print(f"平均每小時交易量:{hourly_volume.mean():.2f} ETH")

實作三:識別「聰明錢」流向

def detect_smart_money_flows(whale_addresses, timeframe_blocks=100):
    """
    追蹤一組「聰明錢」地址的集體行動
    """
    results = []
    current_block = w3.eth.block_number
    
    for whale in whale_addresses:
        whale = Web3.to_checksum_address(whale)
        
        # 取得最近 N 個區塊內的交易
        recent_txs = w3.eth.get_transactions(whale)
        
        for tx in recent_txs[-timeframe_blocks:]:
            if tx['to'] is None:  # 合約創建
                continue
            
            to_address = tx['to'].hex()
            
            # 簡單分類
            category = "Unknown"
            
            # DEX 地址前綴識別
            if to_address.lower() in [
                "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",  # Uniswap V2 Router
                "0xe592427a0aece92de3edee1f18e0157c05861564",  # Uniswap V3 Router
            ]:
                category = "DEX"
            elif to_address.lower() in [
                "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD",  # Metamask Swap
            ]:
                category = "DEX Aggregator"
            elif "0xdef1" in to_address.lower():  # 0x protocol
                category = "DEX Aggregator"
            
            results.append({
                'whale': whale,
                'tx_hash': tx['hash'].hex(),
                'to': to_address,
                'category': category,
                'value_eth': tx['value'] / 1e18,
                'block': tx['blockNumber']
            })
    
    return pd.DataFrame(results)

# 使用範例
whales = [
    "0x28c6c06298d514db089934071355e5743bf21d60",  # Binance
    "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43",  # Coinbase
    "0x21a31ee1afc51d94c2efccaa2092ad1028285549",  # Binance 8
]

flow_df = detect_smart_money_flows(whales)

# 統計各類別的轉帳金額
category_summary = flow_df.groupby('category')['value_eth'].agg(['sum', 'count'])
print(category_summary)

實戰案例:識別 DeFi 協議的健康狀況

光看代碼不夠,來一個完整的實戰分析。

案例:分析 Aave 的清算健康度

def analyze_aave_protocol_health(block_number):
    """
    分析 Aave V3 在特定區塊的清算風險狀況
    """
    # Aave V3 Pool 合約地址(主網)
    aave_pool_address = "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"
    
    # 簡化的健康度分析(實際需要讀取多個合約)
    current_block = block_number or w3.eth.block_number
    
    # 取得最近區塊的 Gas 使用情況
    block = w3.eth.get_block(current_block, full_transactions=True)
    
    # 計算 Aave 相關交易的 Gas 佔比
    aave_txs = [
        tx for tx in block.transactions 
        if tx['to'] and tx['to'].hex().lower() == aave_pool_address.lower()
    ]
    
    # 估算清算交易筆數(需要解析合約事件)
    liquidation_events = get_aave_liquidation_events(current_block, current_block)
    
    return {
        'block': current_block,
        'gas_used_ratio': block.gasUsed / block.gasLimit,
        'aave_txs_count': len(aave_txs),
        'liquidation_count': len(liquidation_events),
        'timestamp': datetime.fromtimestamp(block.timestamp)
    }

def get_aave_liquidation_events(start_block, end_block):
    """
    取得 Aave 的清算事件
    """
    # Aave V3 Pool ABI
    pool_abi = [...]
    
    pool = w3.eth.contract(
        address=aave_pool_address,
        abi=pool_abi
    )
    
    events = pool.events.LiquidationCall.get_logs(
        fromBlock=start_block,
        toBlock=end_block
    )
    
    return [
        {
            'block': e['blockNumber'],
            'liquidator': e['args']['liquidator'],
            'user': e['args']['user'],
            'debt_asset': e['args']['debtAsset'],
            'collateral_asset': e['args']['collateralAsset'],
            'liquidated_collateral_amount': e['args']['liquidatedCollateralAmount'],
        }
        for e in events
    ]

# 執行分析
health = analyze_aave_protocol_health(None)  # 最新區塊
print(f"區塊 {health['block']} 的 Aave 健康狀況:")
print(f"  Gas 使用率:{health['gas_used_ratio']*100:.1f}%")
print(f"  Aave 交易筆數:{health['aave_txs_count']}")
print(f"  清算事件筆數:{health['liquidation_count']}")

數據視覺化:讓數據說故事

分析完數據還要會呈現,不然老闆或客戶看不懂等於白搭。

基礎圖表

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

def plot_gas_price_trend(days=30):
    """
    繪製近 N 天的 Gas 費用趨勢
    """
    # 從 Etherscan API 取得歷史 Gas 數據
    # 這裡用模擬數據示範
    import random
    from datetime import timedelta
    
    end_date = datetime.now()
    dates = [end_date - timedelta(days=i) for i in range(days)]
    
    # 模擬 Gas 費用數據
    gas_prices = [random.randint(20, 200) for _ in range(days)]
    gas_prices.sort()
    
    plt.figure(figsize=(12, 6))
    plt.plot(dates, gas_prices, 'b-', linewidth=2)
    plt.fill_between(dates, gas_prices, alpha=0.3)
    
    plt.title('以太坊 Gas 費用趨勢(過去 30 天)', fontsize=14)
    plt.xlabel('日期')
    plt.ylabel('Gas 費用 (Gwei)')
    plt.grid(True, alpha=0.3)
    
    # 格式化 x 軸日期
    plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d'))
    plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=5))
    
    plt.tight_layout()
    plt.savefig('gas_trend.png', dpi=150)
    plt.show()

# 執行
plot_gas_price_trend(30)

製作儀表板

def create_eth_dashboard(address):
    """
    創建某地址的綜合分析儀表板
    """
    fig, axes = plt.subplots(2, 2, figsize=(14, 10))
    
    # 1. ETH 餘額變化
    ax1 = axes[0, 0]
    balance_history = track_address_balance(address, 17000000, w3.eth.block_number)
    ax1.plot(balance_history['timestamp'], balance_history['balance_eth'])
    ax1.set_title(f'{address[:8]}... ETH 餘額')
    ax1.set_ylabel('ETH 數量')
    
    # 2. 交易頻率
    ax2 = axes[0, 1]
    # 統計每週交易筆數
    weekly_txs = balance_history.set_index('timestamp').resample('W').size()
    ax2.bar(weekly_txs.index, weekly_txs.values)
    ax2.set_title('每週交易筆數')
    ax2.set_ylabel('筆數')
    
    # 3. Gas 費用分佈
    ax3 = axes[1, 0]
    gas_costs = [0.001, 0.002, 0.003, 0.005, 0.008, 0.01, 0.015, 0.02]
    ax3.hist(balance_history['balance_eth'], bins=20)
    ax3.set_title('Gas 費用分佈')
    ax3.set_xlabel('Gas 費用 (ETH)')
    ax3.set_ylabel('頻率')
    
    # 4. 資產組合(餅圖)
    ax4 = axes[1, 1]
    # 假設的資產組合
    assets = ['ETH', 'USDC', 'DAI', '其他']
    amounts = [45, 30, 15, 10]
    ax4.pie(amounts, labels=assets, autopct='%1.1f%%')
    ax4.set_title('資產組合分佈')
    
    plt.suptitle(f'錢包分析:{address[:16]}...', fontsize=16)
    plt.tight_layout()
    plt.savefig('wallet_dashboard.png', dpi=150)
    plt.show()

# 使用
create_eth_dashboard("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1")

常見數據分析陷阱

分析了這麼多數據,有幾個坑一定要提醒你:

數據分析常見錯誤:

陷阱 1:忽略代幣精度
- 合約裡的數字通常是整數
- ETH 精度:除以 10^18
- USDC 精度:除以 10^6
- 搞錯了數據會差好幾個數量級

陷阱 2:只看余額不看流量
- 靜態余額可能誤導
- 要看資金流入流出
- 單筆大額轉入可能只是暫存

陷阱 3:忽略時間因素
- 區塊時間 vs 北京時間
- UTC vs 本地時間
- 要統一時區

陷阱 4:把小額交易當噪音
- 有時候小額交易是測試錢包
- 有時候是項目方在布局

陷阱 5:相信單一數據源
- Etherscan 和 Dune 可能有差異
- 區塊重組會導致數據變化
- 多個數據源交叉驗證

結語

學會鏈上數據分析,你對加密市場的理解會上一個檔次。不再只是「看 K 線猜漲跌」,而是能看見真實的資金流向、協議健康狀況、大戶行動意圖。

這篇文章只是入門,真正的數據分析世界比你想像的還要廣闊。我見過很多厲害的 DeFi 研究者,就是靠一手數據分析能力,在市場上發現機會、避開風險。

建議你從 Etherscan 開始練習,慢慢過渡到 Python 脚本,再到 Dune/Nansen 這樣的專業平台。一口氣吃不成胖子,但持續練習幾個月,你也能成為鏈上數據的老手。

最後提醒一句:數據分析是工具,不是聖經。市場有太多隨機性,再好的模型也預測不了所有事情。保持謙虛,永遠留一手。

工具清單

常用工具:

開源免費:
- Etherscan:https://etherscan.io
- Dune Analytics:https://dune.com
- Tenderly:https://tenderly.co
- Gitcoin 捐贈追蹤

付費工具:
- Nansen:https://nansen.ai
- Arkham Intelligence:https://arkhamintelligence.com
- Glassnode:https://glassnode.com

Python 套件:
- web3.py:區塊鏈交互
- pandas:數據處理
- matplotlib:數據視覺化
- scipy:數據分析

API 服務:
- Alchemy:https://alchemy.com(推薦,有免費額度)
- Infura:https://infura.io
- QuickNode:https://quicknode.com

延伸閱讀與來源

這篇文章對您有幫助嗎?

評論

發表評論

注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。

目前尚無評論,成為第一個發表評論的人吧!