使用Python通过API提取基金净值信息并保存到SQLite数据库

该博客介绍了如何使用Python爬虫从网站获取基金净值信息,并利用SQLite数据库进行存储。作者首先展示了如何读取Excel文件中的基金列表,然后通过批量处理将数据写入SQLite数据库,以避免内存问题。在数据库设计上,采用了多字段唯一约束来防止重复导入数据。此方法适用于数据量较大时替代Excel保存爬取结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前写了一篇保存到Excel版的,但毕竟随着数据量的增大,Excel不是长久之计,所以研究了一下SQLite数据库,SQLite有个好处,不用另外安装程序,Python自带,而且是单文件,方便拷贝转移。

和保存到Excel的主要区别是,可以先将爬取到的数据保存在Python的二维列表中,然后一次性写入SQLite数据库,Python的二维列表的数据容量非常巨大,就是从内存安全性来说,不是很严谨。

以下是代码:

# -*- coding: utf-8 -*-
"""
根据FundList.xls文件中的基金列表,从小熊同学网站API读取基金净值信息,写入到
SQLite数据库中

@author: RockyCoder
"""

'''
第一部分:引用
'''
import xlrd
import sqlite3
import requests
import json

'''
第二部分:函数
'''
# 将长度不定的列表,按照指定长度切割为子列表后,整合成嵌套列表。

def LineList(SrcList,LineLen):
    # 新列表,供返回
    NewList=[]
    # 记录源列表长度
    SrcLen=len(SrcList)

    # 判断是否需要分行
    if SrcLen<LineLen:
        return SrcList
    else:
        # 若需要分行,计算行数和剩余个数
        LineCnt=int(SrcLen/LineLen)
        LeftLen=SrcLen%LineLen
        # 在行数范围内,通过列表切片方式,获取指定长度的子列表
        for i in range(LineCnt):
            Lines=SrcList[(i*LineLen):(i*LineLen+LineLen):1]
            # 拼接到返回列表中
            NewList.append(Lines)
        # 如果剩余个数大于0,则将剩余部分通过切片方式,以子列表形式拼接到返回列表
        if LeftLen>0:
            NewList.append(SrcList[SrcLen-LeftLen:])

        return NewList

# 将指定的列表转换为以逗号分隔的字符串

def CSVString(SrcList):
    TempString=''
    
    for i in range(len(SrcList)):
        if type(SrcList[i]) is int:
            TempString=TempString+str(SrcList[i])+','
        elif type(SrcList[i]) is str:
            TempString=TempString+SrcList[i]+','
        else:
            print(type(SrcList[i]))
            
    return TempString[:-1]

'''
第三部分:操作
'''
# 打开基金原始表格
rdBook=xlrd.open_workbook('FundList.xls',formatting_info=True)
rdSheet=rdBook.sheet_by_name('Sheet1')

# 准备数据库
conn=sqlite3.connect('Fund.db')
c=conn.cursor()

# 初始化基础变量
url="https://api.doctorxiong.club/v1/fund?code="
SQLList=[]
TempList=[]
# 读取完整基金列表
fundCnt=int(rdSheet.cell_value(0,2))
FundList=[]
for j in range(2,fundCnt+1):
    FundCode=str(int(rdSheet.cell_value(j,1)))
    if len(FundCode)>0:
        FundList.append('0'*(6-len(FundCode))+FundCode)
    else:
        print("基金代码不得为空")
        exit(0)
# 按照20个一组,形成子列表
Lines=[]
Lines=LineList(FundList,20)

for l in Lines:
    # 根据逐个子列表,形成URL
    FinalURL=url+CSVString(l)
    strHTML=requests.get(FinalURL)
    contents=json.loads(strHTML.text)
    for k in contents["data"]:
        # 将有用字段写成一行
        TempList.extend((k['code'],k['name'],k['netWorth'],k['dayGrowth'],k['lastWeekGrowth'],k['lastMonthGrowth'],k['lastThreeMonthsGrowth'],k['lastSixMonthsGrowth'],k['lastYearGrowth'],k['netWorthDate']))
        # 将每一行集合成一个二维表
        SQLList.append(TempList)
        TempList=[]
    # 检查当前净值是否已写入过数据库
    
    # 将净值列表写入数据库
    c.executemany("INSERT INTO 产品库 (基金代码,基金名称,单位净值,日涨幅,周涨幅,月涨幅,季涨幅,半年涨幅,年涨幅,更新日期) VALUES (?,?,?,?,?,?,?,?,?,?)", SQLList)
    conn.commit()

conn.close()

SQLite相关数据表的结构

为了避免重复导入,在数据库层面做了一个多字段联合的约束,这个约束必须在创建数据表的SQL语句中体现,代码如下:

CREATE TABLE 产品库 (
    ID   INTEGER  PRIMARY KEY AUTOINCREMENT,
    基金代码 CHAR (6),
    基金名称 CHAR,
    单位净值 DECIMAL,
    日涨幅  DECIMAL,
    周涨幅  DECIMAL,
    月涨幅  DECIMAL,
    季涨幅  DECIMAL,
    半年涨幅 DECIMAL,
    年涨幅  DECIMAL,
    更新日期 DATE,
    UNIQUE (
        基金代码,
        更新日期
    )
    ON CONFLICT REPLACE
);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RockyCoder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值