在区块链开发中,我们习惯了使用 MetaMask 或者 Etherscan 浏览器来查看资产。但如果你是一名量化开发者、数据分析师,或者正在构建一个自动化的 DApp 后端,手动查询显然是不现实的。你需要的是程序化地获取数据。
今天这篇实战教程,将带你使用 Python 生态中最强大的库——Web3.py,通过连接 Infura 节点,只需几行代码就能读取任意 ERC20 代币的余额。
一、准备工作
在开始之前,请确保你的环境满足以下条件:
1.Python 环境:建议 Python 3.7+。
2.Infura API Key:Infura 是以太坊的基础设施服务商,提供免费且稳定的节点接入服务。去 infura.io 注册个账号,创建一个 Project,复制你的 Mainnet Endpoint(通常是 https://mainnet.infura.io/v3/YOUR_PROJECT_ID)。
3.安装 Web3.py:在终端运行以下命令:
二、核心原理:ABI 与合约交互
要查询代币余额,本质上是在调用智能合约上的 balanceOf 函数。
- ERC20 标准:绝大多数代币都遵循 ERC20 标准,其中包含一个标准的
balanceOf(address) 方法。 - ABI (Application Binary Interface):这是 Python 与链上合约沟通的“字典”。我们需要告诉 Web3.py 这个函数的长相(输入是什么,输出是什么),它才能正确编码请求并解码返回的数据。
对于简单的余额查询,我们不需要完整的 ABI,只需要包含 balanceOf 的那一小段 JSON 即可。
三、实战代码:查询 USDT 余额
下面的代码演示了如何连接以太坊主网,并查询指定地址的 USDT 余额。
from web3 import Web3# 1. 配置连接信息# 请将下方的 YOUR_INFURA_PROJECT_ID 替换为你自己的 Infura 项目 IDINFURA_URL = "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"# 初始化 Web3 对象w3 = Web3(Web3.HTTPProvider(INFURA_URL))# 检查连接状态if w3.is_connected(): print("✅ 成功连接到以太坊主网")else: print("❌ 连接失败,请检查网络或 API Key") exit()# 2. 定义目标信息# 这里以 USDT 为例 (Ethereum Mainnet)target_address = "0xdAC17F958D2ee523a2206206994597C13D831ec7" # USDT 合约地址wallet_address = "0x5754284f345afc66a98fbB0a0Afe71e0F007B949" # 你想查询的钱包地址 (例如 Binance 热钱包)# 3. 定义 ERC20 的 balanceOf 函数 ABI# 这是一个最小化的 ABI,仅包含查询余额所需的信息abi_balance_of = [ { "constant": True, "inputs": [{"name": "_owner", "type": "address"}], "name": "balanceOf", "outputs": [{"name": "balance", "type": "uint256"}], "type": "function" }]# 4. 创建合约实例并调用contract = w3.eth.contract(address=target_address, abi=abi_balance_of)# 调用函数获取原始数值 (Wei单位,即最小精度单位)raw_balance = contract.functions.balanceOf(wallet_address).call()# 5. 格式化输出# USDT 的 decimals 是 6,所以我们要除以 10^6decimals = 6human_readable_balance = raw_balance / (10 ** decimals)print(f"🔍 查询地址: {wallet_address}")print(f"💰 USDT 余额: {human_readable_balance}")
四、代码解析与注意事项
关于 Decimals(精度)
这是新手最容易踩坑的地方。
- ETH 本身有 18 位小数。
- USDT 和 USDC 通常只有 6 位小数。
- WBTC 只有 8 位小数。在展示给用户看之前,务必根据代币的实际
decimals 进行除法运算,否则你会看到一个天文数字。如果需要更严谨的代码,可以先调用 contract.functions.decimals().call() 动态获取精度。
关于 Gas 费
注意,.call() 方法是一个只读操作(View/Pure function)。它只是在本地节点模拟执行,不会向区块链发送交易,因此不需要消耗 Gas 费,也不需要私钥签名。这使得它非常适合用于高频的数据抓取。
扩展应用
掌握了这个基础,你可以进一步扩展:
- 批量监控:轮询多个巨鲸地址的余额变动。
- 价格预言机:结合 Uniswap 的池子合约,计算实时代币价格。
- 自动化脚本:当余额低于某个阈值时,自动触发报警或补仓逻辑。
五、总结
Web3.py 是 Python 开发者进入区块链世界的钥匙。通过简单的 HTTP 请求和 ABI 调用,你就拥有了直接对话以太坊的能力。
下次别再手动刷新浏览器了,让你的 Python 脚本替你盯着链上数据吧!
(注:本文代码仅供学习交流,请在合规前提下使用。)