如何用Python提取网页元素 爬取Etherscan代币持有者地址
Etherscan代币持有者地址爬取方案
问题原因
你用requests拿到的HTML和浏览器元素面板看到的内容不一致,核心原因有两个:
requests默认发送的请求没有携带真实浏览器的特征标识,Etherscan的反爬机制会直接返回拦截页面,而非目标数据页面- 部分页面内容需要浏览器端执行JS渲染后才会生成,静态HTTP请求无法直接获取渲染后的内容
可行解决方法
方案1:优化requests请求(适合无严格人机校验的场景)
给请求添加模拟浏览器的请求头,绕过基础反爬校验,示例代码如下:
from bs4 import BeautifulSoup import requests # 构造模拟浏览器的请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } response = requests.get( "https://etherscan.io/token/generic-tokenholders2?a=0x57a204aa1042f6e66dd7730813f4024114d74f37&sid=&m=normal&s=3863&p=1", headers=headers ) holders_html = BeautifulSoup(response.text, 'lxml') # 接下来可定位表格中的持有者地址元素
如果该方案仍然返回拦截页面,说明触发了Cloudflare人机校验,改用方案2。
方案2:使用无头浏览器模拟真实访问(兼容性最强)
通过Selenium等工具模拟真实浏览器打开页面,等待JS渲染完成后直接获取完整DOM,和你在浏览器中看到的内容完全一致,示例代码如下:
- 先安装依赖:
pip install selenium webdriver-manager - 代码示例:
from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from bs4 import BeautifulSoup import time # 初始化Chrome浏览器 driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) # 打开目标页面 driver.get("https://etherscan.io/token/generic-tokenholders2?a=0x57a204aa1042f6e66dd7730813f4024114d74f37&sid=&m=normal&s=3863&p=1") # 等待页面渲染完成 time.sleep(3) # 获取渲染后的完整页面源码 page_source = driver.page_source holders_html = BeautifulSoup(page_source, 'lxml') # 定位持有者列表表格,提取第二列的地址信息 holder_table = holders_html.find("table", {"class": "table table-md-text-normal table-hover"}) if holder_table: rows = holder_table.find("tbody").find_all("tr") for row in rows: address = row.find_all("td")[1].find("a").text.strip() print(address) # 关闭浏览器 driver.quit()
注意事项
- Etherscan有明确的请求频率限制,爬取时控制请求间隔在3秒以上,避免IP被封禁
- 持有者列表为分页展示,爬取多页时只需更换URL中
p参数的数值即可 - 也可以直接在浏览器F12的网络面板中找到对应的数据接口,直接调用接口获取结构化JSON数据,解析效率比解析HTML更高
内容的提问来源于stack exchange,提问作者beyonson
相关产品推荐
相关产品推荐

