土狗你冲不冲,土狗你千万莫冲!
前言:
最近想要学习一点python,又找不到感兴趣的突破口,干脆就从爬虫开始吧。 那咱们干点啥,废话不多说,爬取BSC链上的交易吧。
目标
目标"土狗":
- 最新区块
- 创建时间<7天的token
- 买入金额大于100美金 满足目标: 写入txt文档
开始
装包
ini
# requirements.txt
web3==5.31.3
requests==2.28.2
python-dotenv==0.19.2
初始化一个监控类
在init方法里去初始化一些常量,包括bsc节点,apikey和监控条件
ini
class BSCMonitor:
def __init__(self):
# 多个BSC节点备用(提高稳定性)
self.base_urls = [
"https://bsc-dataseed.binance.org/",
"https://bsc-dataseed1.defibit.io/",
"https://bsc-dataseed1.ninicoin.io/",
"https://bsc-dataseed2.defibit.io/",
]
self.current_url_index = 0
# 需要取bscan网站里去申请一个APIkey,每天都有免费调用额度
self.api_key = "myAPIKey"
# 监控条件
self.min_usd_value = 100
self.max_token_age_days = 7
开启监控
python
def start_monitoring(self):
"""开始监控"""
print("🚀 启动BSC链监控...")
print(f"监控条件: 买入金额 > ${self.min_usd_value}, token年龄 < {self.max_token_age_days}天")
print("使用多个备用节点提高稳定性")
# 初始化文件(确保使用正确编码)
try:
with open('monitored_txs.txt', 'w', encoding='utf-8') as f:
f.write(f"BSC链监控记录 - 开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"监控条件: 买入金额 > ${self.min_usd_value}, token年龄 < {self.max_token_age_days}天\n")
f.write("="*80 + "\n")
print("✅ 初始化监控文件成功")
except Exception as e:
print(f"初始化文件失败: {e}")
# 检查连接
if not self.is_connected():
print("❌ 无法连接到任何BSC节点,请检查网络连接")
return
try:
# 监控代码具体实现看下面具体分析
except KeyboardInterrupt:
print("\n🛑 监控停止")
except Exception as e:
获取当前最新区块
注:
eth_blockNumber
是以太坊JSON-RPC API的一个方法,用于获取当前最新的区块号。BSC虽然不是以太坊,但是完全兼容以太坊的API标准。- JSON-RPC是一种轻量级的远程过程调用协议,使用JSON格式进行数据交换。
- 返回数据样例:
bash
block = {
"number": "0x12a45f",
"hash": "0x9a71c...",
"timestamp": "0x642a5a3d",
"transactions": [ # ← 这个就是我们要获取的
{交易1数据},
{交易2数据},
...
],
"miner": "0x...",
"gasUsed": "0x5208"
}
python
while True:
self.current_block = self.get_latest_block_number()
block = self.bsc_request("eth_getBlockByNumber", [hex(self.current_block), True])
if block:
transactions = block.get('transactions', [])
if transactions:
print(f"区块 {block_num} 有 {len(transactions)} 笔交易")
for tx in transactions:
self.analyze_transaction(tx, block_num)
self.processed_blocks.add(block_num)
def get_latest_block_number:
"""获取最新区块号"""
result = self.bsc_request("eth_blockNumber")
if result and 'result' in result:
block_number = int(result['result'], 16)
return block_number
return 0
def bsc_request(self, method, params=[]):
# 增加重试机制
max_retries = 3
for attempt in range(max_retries):
try:
payload = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": 1
}
response = requests.post(self.get_current_url(), json=payload, timeout=15)
return response.json()
except requests.exceptions.RequestException as e:
print(f"请求失败 (尝试 {attempt + 1}/{max_retries}): {e}")
if attempt < max_retries - 1:
self.switch_to_next_url()
time.sleep(2)
else:
return None
except Exception as e:
print(f"未知错误: {e}")
return None
return None
交易前置校验
- 为什么检查是否是DEX交易,过滤噪音(普通转账,NFT交易,合约部署,合约调用,授权操作)
- 获取交易收据,检查交易是否成功,0x1 = 交易成功 0x0 = 交易失败
python
def analyze_transaction(self, tx, block_number):
"""分析交易"""
try:
# 是否是DEX交易
if not self.is_dex_transaction(tx):
return
tx_hash = tx['hash']
print(f"🔍 分析DEX交易: {tx_hash[:10]}...")
# 获取交易收据
receipt = self.get_transaction_receipt(tx_hash)
if not receipt or receipt.get('status') != '0x1':
return
# 分析日志
logs = receipt.get('logs', [])
for log in logs:
if len(log.get('topics', [])) == 3:
self.process_transfer_log(log, tx, receipt, block_number)
except Exception as e:
print(f"分析交易失败: {e}")
获取token信息
获取token信息的JSON-RPC的返回示例
bash
{
'symbol': 'USDT', # 交易符号
'decimals': 18, # 小数位数
'name': 'Tether USD' # token全名
}
ini
def process_transfer_log(self, log, tx, receipt, block_number):
token_address = log['address']
# 获取token信息
token_info = self.get_token_info(token_address)
token_symbol = token_info['symbol']
token_name = token_info['name']
decimals = token_info['decimals']
def get_token_Info(token_address):
# 1. 先检查缓存
if token_address in self.token_cache:
return self.token_cache[token_address]
# 2. 通过JSON-RPC调用合约方法
symbol_data = {"to": token_address, "data": "0x95d89b41"} # symbol()
decimals_data = {"to": token_address, "data": "0x313ce567"} # decimals()
name_data = {"to": token_address, "data": "0x06fdde03"} # name()
# 3. 发送请求获取数据
symbol_result = self.bsc_request("eth_call", [symbol_data, "latest"])
decimals_result = self.bsc_request("eth_call", [decimals_data, "latest"])
name_result = self.bsc_request("eth_call", [name_data, "latest"])
# 4. 解析返回的16进制数据
symbol = self.parse_string_result(symbol_result)
decimals = self.parse_number_result(decimals_result)
name = self.parse_string_result(name_result)
return tokenInfo
是否是新TOKEN
1.提取合约创建交易的时间戳使用DexScreener的流动性池创建时间。 2.但是某些token不是第一笔交易创建的,所以增加一个else路线,使用DexScreener的流动性池创建时间。
ini
url = f"https://api.bscscan.com/api?module=account&action=txlist&address={token_address}&startblock=0&endblock=99999999&sort=asc&apikey={self.api_key}"
response = requests.get(url, timeout=10)
data = response.json()
if data.get('status') == '1' and data.get('result'):
first_tx = data['result'][0]
timestamp = int(first_tx['timeStamp'])
creation_time = datetime.fromtimestamp(timestamp)
return creation_time
else:
url = f"https://api.dexscreener.com/latest/dex/tokens/{token_address}"
response = requests.get(url, timeout=5)
data = response.json()
if 'pairs' in data and data['pairs']:
pair = data['pairs'][0]
if 'pairCreatedAt' in pair:
created_timestamp = pair['pairCreatedAt'] / 1000 # 转换为秒
creation_time = datetime.fromtimestamp(created_timestamp)
print(f"使用DexScreener的流动性池创建时间: {creation_time}")
return creation_time
获取价格,计算价值
ini
def get_token_price(token_address):
url = f"https://api.dexscreener.com/latest/dex/tokens/{token_address}"
response = requests.get(url, timeout=8)
data = response.json()
if 'pairs' in data and data['pairs']:
price = float(data['pairs'][0]['priceUsd'])
return price
发现token,告警
python
print(f"🎯 发现符合条件的交易!")
print(f" token: {token_symbol} ({token_name})")
print(f" 地址: {token_address[:8]}...")
print(f" 金额: {token_amount:.4f} {token_symbol} ≈ ${usd_value:.2f}")
print(f" 年龄: {token_age}天")


最后
愿我们在顶峰相遇~~手动狗头🐶🐶