141 lines
4.5 KiB
Python
141 lines
4.5 KiB
Python
|
import time
|
|||
|
import requests
|
|||
|
import pymysql
|
|||
|
import ujson
|
|||
|
from datetime import datetime, timedelta
|
|||
|
|
|||
|
# MySQL 连接信息
|
|||
|
DB_CONFIG = {
|
|||
|
"host": "127.0.0.1",
|
|||
|
"user": "root",
|
|||
|
"password": "2GS@bPYcgiMyL14A",
|
|||
|
"database": "btcdb",
|
|||
|
"port": 4423
|
|||
|
}
|
|||
|
|
|||
|
# Nasdaq API Key
|
|||
|
NASDAQ_API_KEY = "FZqXog4sR-b7cYnXcRVV"
|
|||
|
|
|||
|
# 获取已存在的时间戳
|
|||
|
def get_existing_timestamps():
|
|||
|
connection = pymysql.connect(**DB_CONFIG)
|
|||
|
existing_timestamps = set()
|
|||
|
try:
|
|||
|
with connection.cursor() as cursor:
|
|||
|
cursor.execute("SELECT timestamp, source FROM btc_prices")
|
|||
|
for row in cursor.fetchall():
|
|||
|
existing_timestamps.add((row[0], row[1]))
|
|||
|
finally:
|
|||
|
connection.close()
|
|||
|
return existing_timestamps
|
|||
|
|
|||
|
# 工具函数:将任意时间戳调整为北京时间当日 08:00 的时间戳
|
|||
|
def adjust_to_beijing_08am(timestamp):
|
|||
|
dt = datetime.utcfromtimestamp(timestamp) + timedelta(hours=8)
|
|||
|
dt_08am = datetime(dt.year, dt.month, dt.day, 8, 0, 0)
|
|||
|
return int((dt_08am - timedelta(hours=8)).timestamp()) # 转回 UTC 存储
|
|||
|
|
|||
|
# Nasdaq 获取历史 BTC 美元价格
|
|||
|
def get_nasdaq_price():
|
|||
|
prices = {}
|
|||
|
url = f'https://data.nasdaq.com/api/v3/datatables/QDL/BCHAIN?code=MKPRU&api_key={NASDAQ_API_KEY}'
|
|||
|
response = requests.get(url)
|
|||
|
if response.status_code == 200:
|
|||
|
data = ujson.loads(response.content)
|
|||
|
if "datatable" in data and "data" in data["datatable"]:
|
|||
|
for item in data["datatable"]["data"]:
|
|||
|
daystr = item[1]
|
|||
|
price = item[2]
|
|||
|
dt = datetime.strptime(daystr, "%Y-%m-%d")
|
|||
|
dt_08am_bj = datetime(dt.year, dt.month, dt.day, 8, 0, 0)
|
|||
|
dt_08am_utc = dt_08am_bj - timedelta(hours=8)
|
|||
|
prices[int(dt_08am_utc.timestamp())] = float(price)
|
|||
|
print(f"Nasdaq 获取数据量: {len(prices)} 条")
|
|||
|
return prices
|
|||
|
|
|||
|
# CryptoCompare 获取 BTC 历史每日收盘价(时间强制统一为北京时间 08:00)
|
|||
|
def get_cryptocompare_price():
|
|||
|
url = "https://min-api.cryptocompare.com/data/v2/histoday"
|
|||
|
limit = 2000
|
|||
|
to_ts = int(time.time())
|
|||
|
prices = {}
|
|||
|
while True:
|
|||
|
params = {
|
|||
|
"fsym": "BTC",
|
|||
|
"tsym": "USD",
|
|||
|
"limit": limit,
|
|||
|
"toTs": to_ts
|
|||
|
}
|
|||
|
print(f"请求 CryptoCompare: {params}")
|
|||
|
response = requests.get(url, params=params)
|
|||
|
if response.status_code != 200:
|
|||
|
print("请求失败:", response.status_code)
|
|||
|
break
|
|||
|
|
|||
|
data = ujson.loads(response.content)
|
|||
|
if data["Response"] != "Success":
|
|||
|
print("API 返回错误:", data.get("Message"))
|
|||
|
break
|
|||
|
|
|||
|
entries = data["Data"]["Data"]
|
|||
|
if not entries:
|
|||
|
break
|
|||
|
|
|||
|
for entry in entries:
|
|||
|
raw_ts = entry["time"]
|
|||
|
price = entry["close"]
|
|||
|
adjusted_ts = adjust_to_beijing_08am(raw_ts)
|
|||
|
prices[adjusted_ts] = price
|
|||
|
|
|||
|
earliest = entries[0]["time"]
|
|||
|
if earliest <= 1279300000: # 大约2010年7月
|
|||
|
break
|
|||
|
|
|||
|
to_ts = earliest - 1
|
|||
|
time.sleep(1)
|
|||
|
|
|||
|
print(f"CryptoCompare 获取数据量: {len(prices)} 条")
|
|||
|
return prices
|
|||
|
|
|||
|
# 保存数据到数据库
|
|||
|
def save_to_database(data, source):
|
|||
|
existing_timestamps = get_existing_timestamps()
|
|||
|
connection = pymysql.connect(**DB_CONFIG)
|
|||
|
new_data_count = 0
|
|||
|
try:
|
|||
|
with connection.cursor() as cursor:
|
|||
|
sql = """
|
|||
|
INSERT INTO btc_prices (timestamp, price, source)
|
|||
|
VALUES (%s, %s, %s)
|
|||
|
"""
|
|||
|
for timestamp, price in data.items():
|
|||
|
if (timestamp, source) not in existing_timestamps:
|
|||
|
try:
|
|||
|
cursor.execute(sql, (timestamp, price, source))
|
|||
|
new_data_count += 1
|
|||
|
except pymysql.MySQLError as e:
|
|||
|
print(f"插入错误: {e}")
|
|||
|
continue
|
|||
|
connection.commit()
|
|||
|
print(f"成功存入 {new_data_count} 条新数据({source})")
|
|||
|
finally:
|
|||
|
connection.close()
|
|||
|
|
|||
|
# 定时任务
|
|||
|
def fetch_and_store_data():
|
|||
|
print("========== 开始获取比特币价格数据 ==========")
|
|||
|
|
|||
|
# Nasdaq
|
|||
|
nasdaq_prices = get_nasdaq_price()
|
|||
|
save_to_database(nasdaq_prices, "Nasdaq")
|
|||
|
|
|||
|
# CryptoCompare
|
|||
|
cc_prices = get_cryptocompare_price()
|
|||
|
save_to_database(cc_prices, "CryptoCompare")
|
|||
|
|
|||
|
print("========== 数据存储完成 ==========")
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
while True:
|
|||
|
fetch_and_store_data()
|
|||
|
time.sleep(14400) # 每 4 小时执行一次
|