You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()方法。
解决方案

修正思路

  1. 仅转换新获取的交易数据:只对每个请求返回的df_temp中的timeStamp列做转换,避免修改已处理的df_main数据;
  2. 每个钱包单独分页:为每个钱包维护独立的分页页码,确保数据获取完整;
  3. 正确终止循环:当获取的交易中最早时间早于2022-01-01时,停止该钱包的请求,并过滤掉早于该日期的交易;
  4. 替换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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:15:14