手把手教你解析 ETH 区块并批量导出交易数据

·

以太坊数据研究离不开区块解析交易记录抓取。本文将用纯 Python 代码,带你从零开始抓取每一条 ETH 交易数据,并以本地文件形式持久化存储,既满足日常分析,也为学术研究省下高昂的接口费用。


准备环境:一句话装好所有依赖

pip install web3 pandas tqdm python-dotenv
一条命令完成环境部署,避开繁琐的依赖噩梦。

1. 快速理解:以太坊交易长什么样?

在动手前,先弄清两个最常被提起的概念:

下图仅演示数据层级,帮助你建立直观印象:

区块
└─ 交易数组
   ├─ 交易0 {hash, from, to, value, gasPrice, ...}
   ├─ 交易1 {...}
   └─ ...

2. 三行代码连接主网并验证节点

from web3 import Web3
w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/<你的ProjectID>'))
print("已连接主网:", w3.isConnected())   # True 表示成功

出现 True 即可继续;如果返回 False,多半是节点 URL 或网络配置出了问题。


3. 抓取单个区块的全部交易详情

以太坊本身提供了 w3.eth.get_block 方法,但返回的是字典,在数据分析场景不够直观。为此,我们封装一个 区块解析器(BlockParser)

def fetch_block_txs(block_number):
    block = w3.eth.get_block(block_number, full_transactions=True)
    return [
        {
            "hash": tx["hash"].hex(),
            "block_number": tx["blockNumber"],
            "from": tx["from"],
            "to": tx["to"],
            "value": w3.fromWei(tx["value"], "ether"),
            "gas": tx["gas"],
            "gas_price": w3.fromWei(tx["gasPrice"], "gwei"),
        }
        for tx in block.transactions
    ]

跑一次看看:

print(fetch_block_txs(18000000))

4. 批量导出:按时间区间缓存为 CSV

实验总不能只取一个区块。下面方法支持 连续区间 自动下载,并实时展示进度:

import pandas as pd, os, tqdm

def export_range(start, end, out_dir='eth_txs'):
    os.makedirs(out_dir, exist_ok=True)
    for n in tqdm.tqdm(range(start, end+1), desc="抓取区块"):
        df = pd.DataFrame(fetch_block_txs(n))
        df.to_csv(f"{out_dir}/block_{n}.csv", index=False)
    print("全部导出完成,数据已保存在", out_dir)

调用:

# 抓取 18000200 ~ 18000210 共 11 个区块
export_range(18000200, 18000210)

5. 进阶技巧:只保留特定合约或地址的交易

如果你只要研究 USDT 或某条 DeFi 协议,可在解析阶段就过滤:

TARGET = "0xdAC17F958D2ee523a2206206994597C13D831ec7".lower()  # USDT 合约

def fetch_filtered(block_number, addr=TARGET):
    records = fetch_block_txs(block_number)
    return [tx for tx in records if (tx["to"] and tx["to"].lower() == addr)]

6. 性能优化:循环阻塞式 → 并发异步

单机带宽和时间有限,推荐把 HTTP 请求改为 asyncio + aiohttp,实现 10 倍以上 提速。只需在原函数外加一层并发即可,完整代码放入附录,有需要点击下面链接查看。

👉 这里获取完整并发源码与提速案例


FAQ:你最可能遇到的 5 个问题

问:免费节点有速率限制,如何判断自己被限流?
答:多线程短时间触发 429 或空响应就是信号,建议自备 Alchemy 或自建节点。

问:Infura 的免费额度够跑多少区块?
答:每天 10 万次调用,每个区块消耗 2 次,大约 5 万区块/天,约 7 天历史。

问:CSV 太多不好合并,有没有一键合并方案?
答:pandas.concat([pd.read_csv(f) for f in glob]) 一行搞定。

问:gasPrice 字段单位是 Gwei,如何与当前 GasNow 网站实时对比?
答:直接读取 w3.eth.gas_price 即可换算成 Gwei。

问:出现“replacement transaction underpriced”怎么办?
答:那是签名阶段才出现的链上错误,跟纯抓取脚本无关,放心跳过。


7. 漂移检测:实时验证数据完整性

抓取过程中,节点可能回滚,导致同一块号出现“孤块”。最简单的 漂移检测 逻辑:记录已保存的最大块号的 hash,若与节点再次请求的不一致,则重新抓取,保证 ETH 交易数据 的完整性。


8. 全盘可视化:三行代码做出交易量热力图

import matplotlib.pyplot as plt, seaborn as sns
df = pd.concat([pd.read_csv(f) for f in os.listdir('eth_txs') if f.endswith('.csv')])
sns.histplot(df['value'].astype(float), bins=50)
plt.title("交易量分布(区块 18,000,200–18,000,210)")
plt.show()

实验结果可直接复制到研究报告中,方便非技术人员阅读。


9. 实战案例:如何通过 1000 万个区块回答 3 个商业问题

商业问题字段与思路
每日 USDT 发行量过滤 to == USDT 合约input.startswith('0xa9059cbb')
链上活跃地址数对 from、to 做去重
Gas 价格战高发时段统计每区块平均 gasPrice 波动

👉 下载真实脱敏样本数据集,复现以上案例


10. 小结与下一步

通过 区块解析 + 交易记录导出 的组合拳,你已经拥有离线 ETH 交易数据 的完整链路。下一步可以从模型角度出发:

研究路上,有数据就有无限可能。祝探索愉快!