Python调用Etherscan API时时间戳转日期遇ValueError报错求助
问题分析
报错ValueError: unit='s' not valid with non-numerical val='2022-09-19 18:14:47'的核心原因是重复对timeStamp列执行时间戳转换:
- 第一次循环时,
df_main['timeStamp']是API返回的数字时间戳,转换后变成datetime类型; - 后续循环再次执行
pd.to_datetime(df_main['timeStamp'], unit='s')时,列中已经存在datetime对象/格式化后的日期字符串,无法再用unit='s'解析非数值内容,因此抛出错误。
同时原代码还存在逻辑问题:
- 分页逻辑混乱:
page_number全局递增会导致两个钱包的分页请求交叉(第一个钱包用page0,第二个用page1,下一轮第一个钱包直接用page2,跳过了page1的数据); - 终止条件无效:
if min(...) < datetime.date(2022,1,1): pass仅做判断但未终止循环,会持续请求无效数据; - 使用已弃用的
df.append()方法。
解决方案
修正思路
- 仅转换新获取的交易数据:只对每个请求返回的
df_temp中的timeStamp列做转换,避免修改已处理的df_main数据; - 每个钱包单独分页:为每个钱包维护独立的分页页码,确保数据获取完整;
- 正确终止循环:当获取的交易中最早时间早于
2022-01-01时,停止该钱包的请求,并过滤掉早于该日期的交易; - 替换
append为concat:遵循Pandas官方推荐的拼接方式。
修正后的代码
import requests import json import pandas as pd from datetime import datetime # 替换为你的Etherscan API密钥 ether_api = "YOUR_API_KEY" wallet_addresses = ['0xdafea492d9c6733ae3d56b7ed1adb60692c98bc5', '0xc508dbe4866528db024fb126e0eb97595668c288'] target_date = datetime(2022, 1, 1).date() df_main = pd.DataFrame() for address in wallet_addresses: page_number = 1 # Etherscan的page参数从1开始,每个钱包单独初始化分页 while True: # 构造API请求URL url = (f'https://api.etherscan.io/api?module=account&action=txlist&address={address}' f'&startblock=0&endblock=99999999&page={page_number}&offset=10&sort=asc&apikey={ether_api}') # 发送请求并解析结果 response = requests.get(url) data = json.loads(response.text) # 处理API返回错误(比如调用超限、密钥无效) if data['status'] != '1': print(f"获取地址{address}第{page_number}页数据失败:{data['message']}") break df_temp = pd.DataFrame(data['result']) if df_temp.empty: break # 没有更多数据,终止当前钱包的请求 # 仅转换当前页的时间戳为datetime df_temp['timeStamp'] = pd.to_datetime(df_temp['timeStamp'], unit='s') df_temp['wallet_address'] = address # 过滤早于目标日期的交易 df_temp = df_temp[df_temp['timeStamp'].dt.date >= target_date] # 如果过滤后无数据,终止当前钱包的请求 if df_temp.empty: break # 合并到主DataFrame df_main = pd.concat([df_main, df_temp], ignore_index=True) # 检查当前页最早的交易时间,若已早于目标日期,终止循环 earliest_date = df_temp['timeStamp'].dt.date.min() if earliest_date < target_date: break page_number += 1 # 输出最终结果 print(df_main)
关键说明
- API分页起始页:Etherscan的
txlist接口page参数从1开始,原代码的page_number=0会导致第一次请求返回空数据; - API错误处理:增加了对
status字段的判断,避免因API调用限制或密钥错误导致代码崩溃; - 数据过滤时机:在获取单页数据后立即过滤,减少不必要的数据拼接,提升效率;
- 循环终止逻辑:当单页数据过滤后为空,或最早交易时间早于目标日期时,停止当前钱包的请求,避免无效请求。
内容的提问来源于stack exchange,提问作者MathMan 99
相关产品推荐
相关产品推荐

