本文目录导读:

- 基础工具安装
- 方法一:使用websocket-client库(同步)
- 方法二:使用websockets库(异步)
- 方法三:抓取加密交易所WebSocket示例
- 方法四:使用Selenium模拟浏览器WebSocket
- 高级特性:自动重连与数据持久化
- 注意事项
我来详细说明如何使用Python爬虫抓取WebSocket数据。
基础工具安装
# 安装websocket客户端库 pip install websocket-client pip install websockets # 异步版本 # 可选工具 pip install aiohttp # 异步HTTP客户端,支持WebSocket pip install ws4py # 另一种WebSocket客户端
使用websocket-client库(同步)
import websocket
import json
import threading
def on_message(ws, message):
"""收到消息时的回调"""
data = json.loads(message)
print(f"收到数据: {data}")
# 这里处理你的数据,如保存到文件或数据库
def on_error(ws, error):
"""错误处理"""
print(f"错误: {error}")
def on_close(ws, close_status_code, close_msg):
"""连接关闭处理"""
print(f"连接关闭: {close_status_code} - {close_msg}")
def on_open(ws):
"""连接成功建立"""
print("WebSocket连接已建立")
# 发送订阅消息
subscribe_msg = {
"event": "subscribe",
"channel": "ticker",
"symbol": "BTC/USDT"
}
ws.send(json.dumps(subscribe_msg))
def connect_websocket():
"""建立WebSocket连接"""
# 禁用SSL验证(如果需要)
websocket.enableTrace(False)
# 连接WebSocket
ws = websocket.WebSocketApp(
"wss://your-websocket-url.com/ws", # 替换为实际URL
on_open=on_open,
on_message=on_message,
on_error=on_error,
on_close=on_close
)
# 运行连接(会阻塞)
ws.run_forever()
# 启动连接
connect_websocket()
使用websockets库(异步)
import asyncio
import websockets
import json
async def subscribe_market_data():
"""订阅市场数据"""
uri = "wss://your-websocket-url.com/ws" # 替换为实际URL
async with websockets.connect(uri) as websocket:
# 发送订阅请求
subscribe_msg = {
"event": "subscribe",
"channel": "ticker",
"symbol": "BTC/USDT"
}
await websocket.send(json.dumps(subscribe_msg))
# 持续接收数据
while True:
try:
response = await websocket.recv()
data = json.loads(response)
print(f"收到数据: {data}")
# 数据处理逻辑
# save_to_database(data)
except websockets.exceptions.ConnectionClosed:
print("连接已关闭,尝试重连...")
break
except Exception as e:
print(f"错误: {e}")
break
async def main():
"""主函数"""
# 创建重连机制
while True:
try:
await subscribe_market_data()
except Exception as e:
print(f"连接失败: {e}")
await asyncio.sleep(5) # 等待5秒重试
# 运行
asyncio.run(main())
抓取加密交易所WebSocket示例
import websocket
import json
import threading
import time
from datetime import datetime
class CryptoWebSocket:
"""加密货币WebSocket抓取器"""
def __init__(self, url, channels=None):
self.url = url
self.channels = channels or []
self.ws = None
self.running = False
self.reconnect_count = 0
def on_message(self, ws, message):
"""处理接收到的消息"""
try:
data = json.loads(message)
# 根据数据类型处理
if 'channel' in data:
channel = data['channel']
if channel == 'ticker':
self.handle_ticker(data)
elif channel == 'trade':
self.handle_trade(data)
elif channel == 'orderbook':
self.handle_orderbook(data)
except json.JSONDecodeError:
print(f"无法解析的JSON数据: {message[:100]}")
def handle_ticker(self, data):
"""处理ticker数据"""
ticker_data = {
'timestamp': datetime.now().isoformat(),
'symbol': data.get('symbol'),
'price': data.get('price'),
'volume': data.get('volume'),
'change': data.get('change')
}
print(f"Ticker: {ticker_data}")
# 保存到文件或数据库
def handle_trade(self, data):
"""处理交易数据"""
print(f"Trade: {json.dumps(data, indent=2)}")
def handle_orderbook(self, data):
"""处理订单簿数据"""
print(f"Orderbook update received")
def on_error(self, ws, error):
"""处理错误"""
print(f"WebSocket错误: {error}")
def on_close(self, ws, close_status_code, close_msg):
"""处理连接关闭"""
print(f"WebSocket连接关闭: {close_status_code}")
if self.running:
self.reconnect()
def on_open(self, ws):
"""处理连接建立"""
print("WebSocket连接已建立")
self.reconnect_count = 0
# 发送订阅消息
for channel in self.channels:
subscribe_msg = {
"event": "subscribe",
"channel": channel
}
ws.send(json.dumps(subscribe_msg))
print(f"已订阅: {channel}")
def connect(self):
"""建立连接"""
websocket.enableTrace(False)
self.ws = websocket.WebSocketApp(
self.url,
on_open=self.on_open,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close
)
self.running = True
# 在另一个线程中运行
wst = threading.Thread(target=self.ws.run_forever)
wst.daemon = True
wst.start()
def reconnect(self):
"""重连机制"""
if self.reconnect_count < 10: # 最多重连10次
wait_time = min(30, 2 ** self.reconnect_count)
print(f"将在 {wait_time} 秒后重连...")
time.sleep(wait_time)
self.reconnect_count += 1
self.connect()
def disconnect(self):
"""断开连接"""
self.running = False
if self.ws:
self.ws.close()
def send_message(self, message):
"""发送消息"""
if self.ws and self.running:
self.ws.send(json.dumps(message))
# 使用示例
def main():
# 配置WebSocket连接
ws_client = CryptoWebSocket(
url="wss://stream.binance.com:9443/ws",
channels=["btcusdt@ticker", "ethusdt@ticker"]
)
# 启动连接
ws_client.connect()
try:
# 保持主线程运行
while True:
time.sleep(1)
except KeyboardInterrupt:
print("正在关闭连接...")
ws_client.disconnect()
if __name__ == "__main__":
main()
使用Selenium模拟浏览器WebSocket
from selenium import webdriver
from selenium.webdriver.common.by import By
import json
import time
def capture_websocket_via_selenium():
"""通过Selenium捕获WebSocket通信"""
options = webdriver.ChromeOptions()
options.add_argument('--disable-gpu')
options.add_argument('--headless') # 无头模式
# 启用性能日志
options.set_capability('goog:loggingPrefs', {'performance': 'ALL'})
driver = webdriver.Chrome(options=options)
try:
# 访问目标网站
driver.get("https://example.com") # 替换为实际URL
# 等待页面加载
time.sleep(5)
# 获取性能日志
logs = driver.get_log('performance')
websocket_messages = []
for entry in logs:
log_data = json.loads(entry['message'])
message = log_data.get('message', {})
# 过滤WebSocket消息
if message.get('method') == 'Network.webSocketFrameReceived':
params = message.get('params', {})
response = params.get('response', {})
payload = response.get('payloadData', '')
try:
data = json.loads(payload)
websocket_messages.append(data)
print(f"WebSocket消息: {data}")
except:
pass
return websocket_messages
finally:
driver.quit()
高级特性:自动重连与数据持久化
import asyncio
import websockets
import json
import sqlite3
from datetime import datetime
import logging
logging.basicConfig(level=logging.INFO)
class WebSocketCrawler:
"""高级WebSocket爬虫"""
def __init__(self, url, db_path='websocket_data.db'):
self.url = url
self.db_path = db_path
self.setup_database()
def setup_database(self):
"""初始化数据库"""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
# 创建数据表
cursor.execute('''
CREATE TABLE IF NOT EXISTS websocket_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
channel TEXT,
data TEXT,
received_at TEXT
)
''')
conn.commit()
conn.close()
def save_to_database(self, channel, data):
"""保存数据到数据库"""
try:
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('''
INSERT INTO websocket_data (timestamp, channel, data, received_at)
VALUES (?, ?, ?, ?)
''', (
datetime.now().isoformat(),
channel,
json.dumps(data),
datetime.now().isoformat()
))
conn.commit()
conn.close()
return True
except Exception as e:
logging.error(f"保存数据失败: {e}")
return False
async def connect_with_retry(self, max_retries=5):
"""带重试的连接"""
for attempt in range(max_retries):
try:
async with websockets.connect(
self.url,
ping_interval=30,
ping_timeout=10
) as websocket:
logging.info(f"连接成功 (尝试 {attempt + 1})")
# 订阅数据
await websocket.send(json.dumps({
"event": "subscribe",
"channel": "ticker"
}))
# 持续接收数据
async for message in websocket:
try:
data = json.loads(message)
channel = data.get('channel', 'unknown')
# 保存到数据库
self.save_to_database(channel, data)
# 可选:发送到消息队列
# await self.send_to_queue(data)
except json.JSONDecodeError:
continue
except websockets.exceptions.ConnectionClosed:
logging.warning(f"连接断开,准备重试 ({attempt + 1}/{max_retries})")
await asyncio.sleep(2 ** attempt) # 指数退避
except Exception as e:
logging.error(f"连接错误: {e}")
await asyncio.sleep(5)
logging.error("达到最大重试次数,放弃连接")
# 使用示例
async def main():
crawler = WebSocketCrawler("wss://your-websocket-url.com/ws")
await crawler.connect_with_retry()
if __name__ == "__main__":
asyncio.run(main())
注意事项
- 法律合规:确保抓取行为符合网站服务条款和当地法律法规
- 频率限制:遵守WebSocket的速率限制,避免过度请求
- 数据解析:不同平台的数据格式可能不同,需要适配解析
- 错误处理:实现完善的错误处理和重连机制
- 资源管理:及时关闭连接,释放资源
- 安全性:避免在代码中硬编码敏感信息
选择哪种方法取决于你的具体需求:同步库适合简单场景,异步库适合高并发,Selenium适合抓取动态加载的WebSocket数据。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播