【爬虫】爬取股票历史K线数据写入数据库(三)

在这里插入图片描述
前几天有写过两篇:
【爬虫】爬取A股数据写入数据库(二)
【爬虫】爬取A股数据写入数据库(一)

现在继续完善,分析及爬取股票的历史K线数据通过ORM形式批量写入数据库。

2024/05,本文主要内容如下:

  1. 对东方财富官网进行分析,并作数据爬取,使用python,使用pip install requests 模拟http数据请求,获取数据。
  2. 将爬取的数据写入通过 sqlalchemy ORM 写入 sqlite数据库。
  3. 记录爬取股票的基本信息,如果库中已存在某个股票代码,则进行更新。
  4. 后续计划:会不断完善,最终目标是做出一个简单的股票查看客户端。
  5. 本系列所有源码均无偿分享,仅作交流无其他,供大家参考。
    python依赖环境如下:
pip install requests==2.31.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pandas==2.2.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install jsonpath==0.8.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install sqlalchemy==2.0.30 -i https://pypi.tuna.tsinghua.edu.cn/simple

1. 对东方财富官网历史K线数据分析

网页地址:https://quote.eastmoney.com/sz002224.html?jump_to_web=true#fullScreenChart
通过分析网页,发现https://push2his.eastmoney.com/api/qt/stock/kline/get?请求后面带着一些参数即可以获取到相应数据,我们不断调试,模拟这类请求即可。分析过程如下图所示,F12调出调试框,不断尝试:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 爬取数据代码逻辑

如下即爬取数据的可运行代码,复制后直接能跑:

import pandas as pd
from typing import List
import requests
from jsonpath import jsonpath

class CustomedSession(requests.Session):
    def request(self, *args, **kwargs):
        kwargs.setdefault('timeout', 60)
        return super(CustomedSession, self).request(*args, **kwargs)
session = CustomedSession()
adapter = requests.adapters.HTTPAdapter(pool_connections = 50, pool_maxsize = 50, max_retries = 5)
session.mount('http://', adapter)
session.mount('https://', adapter)

# 请求地址
QEURY_URL = 'http://push2his.eastmoney.com/api/qt/stock/kline/get'
# HTTP 请求头
EASTMONEY_REQUEST_HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko',
    'Accept': '*/*',
    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
}

"""
获取单只股票的历史K线数据
"""
def get_k_history_data(
    stock_codes: str, # 股票代码
    beg: str = '19000101', # 开始日期,19000101,表示 1900年1月1日
    end: str = '20500101', # 结束日期
    klt: int = 101,  # 行情之间的时间间隔 1、5、15、30、60分钟; 101:日; 102:周; 103:月
    fqt: int = 1, # 复权方式,0 不复权 1 前复权 2 后复权
):
    try:
        # 生成东方财富专用的secid
        if stock_codes[:3] == '000':   # 沪市指数
            secid = f'1.{stock_codes}'
        elif stock_codes[:3] == '399': # 深证指数
            secid = f'0.{stock_codes}'

        if stock_codes[0] != '6':  # 沪市股票
            secid = f'0.{stock_codes}'
        else:
            secid = f'1.{stock_codes}' # 深市股票
            
        EASTMONEY_KLINE_FIELDS = {'f51': '日期', 'f52': '开盘', 'f53': '收盘', 'f54': '最高', 'f55': '最低',
                                'f56': '成交量', 'f57': '成交额', 'f58': '振幅', 'f59': '涨跌幅', 'f60': '涨跌额', 'f61': '换手率',}
        fields = list(EASTMONEY_KLINE_FIELDS.keys())
        # columns = list(EASTMONEY_KLINE_FIELDS.values())
        fields2 = ",".join(fields)
        params = (
            ('fields1', 'f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13'),
            ('fields2', fields2),
            ('beg', beg),
            ('end', end),
            ('rtntype', '6'),
            ('secid', secid),
            ('klt', f'{klt}'),
            ('fqt', f'{fqt}'),
        )
        code = secid.split('.')[-1]
        json_response = session.get(QEURY_URL, headers=EASTMONEY_REQUEST_HEADERS, params=params, verify=False).json()
        data_list = []
        klines: List[str] = jsonpath(json_response, '$..klines[:]')
        if not klines:
            return data_list
        
        name = json_response['data']['name']
        rows = [kline.split(',') for kline in klines]
        # 0           1      2     3      4      5        6           7        8        9       10
        # 日期,       开盘,   收盘, 最高,  最低,   成交量,  成交额,      振幅,    涨跌幅,   涨跌额, 换手率
        # 2024-05-08, 4.89,  4.82, 4.91,  4.80,  61811,  29955564.00,  2.25,  -1.23,    -0.06,  0.98
        # data_list = [{'code': '002224', 'name': '三力士', 'time': '2024-05-08', 'info': '0,1,2,3,4,5,6,7,8,9,10'}]
        for row in rows:
            time, open, close, high, low, vol, quota, mm, change, range, tun = row
            line_str = f'{open},{close},{high},{low},{vol},{quota},{mm},{change},{range},{tun}'
            data_list.append({'id': None,'code': code, 'name': name, 'time': time, 'info': line_str})
        
        return data_list
    except Exception as e:
        print('get_k_history_data error-----------------------', str(e))
        return data_list

if __name__ == "__main__":
    data = get_k_history_data(stock_codes='002224', beg='20240507', end='20500101')
    print('----', data)

3. 将爬取的数据通过ORM形式写入数据库

数据库表设计:

from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, Index, Table
from sqlalchemy.orm import declarative_base, sessionmaker, scoped_session
from sqlalchemy.schema import UniqueConstraint
from datetime import datetime

# 声明一个基类,所有的ORM类都将继承自这个基类
DBBase = declarative_base()

# 创建引擎
engine = create_engine('sqlite:///a.db',  echo=False)
# 绑定引擎
Session = sessionmaker(bind=engine)
# 创建数据库链接池,直接使用session即可为当前线程拿出一个链接对象conn
db_session = scoped_session(Session)

'''
股票K线信息表
0           1      2     3      4      5        6           7        8        9       10
日期,       开盘,   收盘, 最高,  最低,   成交量,  成交额,      振幅,    涨跌幅,   涨跌额, 换手率
2024-05-08, 4.89,  4.82, 4.91,  4.80,  61811,  29955564.00,  2.25,  -1.23,    -0.06,  0.98
data_list = [{'code': '002224', 'name': '三力士', 'time': '2024-05-08', 'info': '1,2,3,4,5,6,7,8,9,10'}]
'''
class tb_k(DBBase):
    __tablename__ = 'tb_k'
    id = Column(Integer, primary_key=True, autoincrement=True)
    code = Column(String, nullable=False, comment="股票代码")
    name = Column(String, comment="股票名称")
    time = Column(String, comment="时间")
    info = Column(String, comment="开盘,收盘,最高,最低,成交量,成交额,振幅,涨跌幅,涨跌额,换手率")
    __table_args__ = (
        Index('unique_index', 'code', 'time', unique=True),
    )
# 创建表, 创建所有class xx(DBBase)
DBBase.metadata.create_all(engine)

写入数据库的逻辑:

# 查询某个股票最近更新K线的日期
def query_latast_K_data(code):
    result = db_session.query(tb_k).filter(tb_k.code==code).order_by(desc(tb_k.time)).first()
    if result is None:
        return '19000101'
    return str(result.time).replace('-','')

# 批量插入或更新某只股票的历史K线数据
def insert_or_update_stock_k(data_list):
    if len(data_list) <= 0:
        return
    try:
        db_session.bulk_insert_mappings(tb_k, data_list)
        db_session.commit()
    except Exception as e:
        print('insert_or_update_stock_k error=', str(e))

4. 整体逻辑流程

步骤:

  1. 输入某个股票代码爬取该股票的历史K线数据
  2. 将返回结果组成数组,批量写入数据库
  3. 每次写入前,会根据该股票代码,查询最新的同步日期,从该日期开始进行追加同步
# 更新某个股票的最新日K线数据到数据库
def update_k_info_db(code='002224'):
    # 根据 code 查询库中已存在的某个股票日K线数据的最近日期,作为开始日期,向后获取
    beg_time = db_orm.query_latast_K_data(code)
    data_list = stock.get_k_history_data(stock_codes=code, beg=beg_time, end='20500101')
    
    if len(data_list) > 0:
        db_orm.insert_or_update_stock_k(data_list)
        
        
if __name__ == "__main__":
    update_base_info_db()

最终结果保存在 a.db中,例如:
在这里插入图片描述
更多内容可关注我,后续源码包均在上面回复下载:
【爬虫】爬取A股数据系列工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/620218.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

十五、Redis缓存常见问题

Redis作为最常用的缓存中间件&#xff0c;在使用过程中&#xff0c;必然会遇到过&#xff1b;**缓存穿透、缓存雪崩、缓存击穿。**这三个可以说是Redis缓存使用过程中&#xff0c;最常见的问题&#xff0c;且也是面试中最常闻到的问题。1、缓存穿透 **缓存穿透&#xff1a;**是…

【手势操作-复习前一天的内容-预习今天的内容 Objective-C语言】

一、昨天呢,我们学习的是这个,事件 1.事件这一块儿呢,iOS事件,分为三大类, 1)触摸事件 2)加速计事件 3)远程控制事件 2.这个里边呢,我们主要学习的是这个触摸事件,触摸事件里边,就是Touch,touchesBegan:方法里边,有一个touches参数,它是set类型的, 3.Set,…

启动项目时出现SELinux is preventing

问题描述 启动项目时出现SELinux is preventing**** SELinux正在阻止systemd对文件AB.sevice进行读取访问。 我的是启zabbix是报该错&#xff1a; 最终解决方案 方法一&#xff1a;暂时禁用SELinux setenforce 0 方法二&#xff1a;禁用SELinux 在配置文件/etc/sysconfig/…

韵搜坊(全栈)-- 前后端初始化

文章目录 前端初始化后端初始化 前端初始化 使用ant design of vue 组件库 官网快速上手&#xff1a;https://www.antdv.com/docs/vue/getting-started-cn 安装脚手架工具 进入cmd $ npm install -g vue/cli # OR $ yarn global add vue/cli创建一个项目 $ vue create ant…

【网络安全入门】你必须要有的学习工具(附安装包)零基础入门到进阶,看这一篇就够了!

工欲善其事必先利其器 在新入门网络安全的小伙伴而言。这些工具你必须要有所了解。本文我们简单说说这些网络安全工具吧&#xff01; Web安全类 Web类工具主要是通过各种扫描工具&#xff0c;发现web站点存在的各种漏洞如sql注入、xss等。从而获取系统权限&#xff0c;常用的…

相同的树LeetCode

100. 相同的树 - 力扣&#xff08;LeetCode100. 相同的树 - 力扣&#xff08; 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 /*** Definition…

css 步骤条虚线渐变色效果实现

效果如图所示&#xff1a; 思路&#xff1a; 使用元素覆盖的方式实现视觉上虚线的效果 实现代码&#xff1a; html布局 <ul class"details-cont"><li class"details-li" v-for"item in 3" :key"item"><div class&qu…

如何从未入库的gerrit中撤销一个文件

用一个例子说明 比如有一个提交里面的default.xml的修改没有必要&#xff0c;需要从未入库的gerrit中移除 步骤如下&#xff1a; 1.做reset操作 git reset HEAD^ packages/SettingsProvider/res/values/defaults.xml 2.做checkout操作 git checkout packages/SettingsProv…

C语言leetcode刷题笔记3

C语言leetcode刷题笔记3 第8题&#xff1a;876.链表的中间结点遍历数节点个数快慢指针 第9题&#xff1a;874.比较含退格的字符串第10题&#xff1a;155.最小栈法1&#xff1a;getMin内部实现查找法2&#xff1a;getmin直接返回值补充&#xff1a;栈的使用例子优化&#xff1a;…

使用自动矢量化编译Neon

概述 作为程序员&#xff0c;你有多种方式使用 Neon 技术&#xff1a; 支持 Neon 的开源库&#xff0c;例如 Arm Compute Library提供一种最简单的方式使用 Neon编译器的自动矢量优化特性可以利用 Neon 技术自动优化你的代码Neon intrinsics内建函数&#xff0c;编译器用相应…

ArcGIS如何计算地级市间的距离

一、数据准备 加载配套实验数据包中的地级市和行政区划矢量数据(订阅专栏后,从私信查收数据),如下图所示: 二、计算距离 1. 计算邻近表 ArcGIS提供了计算点和另外点之间距离的工具:分析工具→邻域分析→生成临近表。 计算一个或多个要素类或图层中的要素间距离和其他邻…

sCrypt受邀在中国人民大学举办《区块链与数字经济》课程讲座

4月17日&#xff0c;可一科技特邀美国sCrypt公司的开发工程师周全&#xff0c;在中国人民大学的《区块链与数字经济》课程上进行了讲座。周全讲解了区块链的分布式设计、不可篡改特性&#xff0c;以及智能合约的基本原理&#xff0c;利用“智能家居触发机制”等生动比喻&#x…

JS解密之新js加密实战(二)

前言 上次发了一篇关于新加密的&#xff0c;只解了前边两层&#xff0c;这中间家里各种事情因素影响&#xff0c;没有继续进一步研究&#xff0c;今天百忙之中抽空发布第二篇&#xff0c;关于其中的一小段加密片段&#xff0c;我认为分割成多个小片段是更容易被理解的。逻辑相…

ansible——playbook

一、playbook定义 Ansible Playbook是设定自动化任务的一种蓝图&#xff0c;可在无需人工干预或有限干预的前提下执行复杂的IT操作。Ansible Playbook对一组或一类共同构成 Ansible 清单的主机执行。 Ansible Playbook本质上是一些框架&#xff0c;是一些预先编写的代码&#x…

OrangePi Zero2 全志H616开发学习文档、基础IO蜂鸣器、超声波测距、舵机PWM基础开发

一.平台介绍 OrangePi开发板不仅仅是一款消费品&#xff0c;同时也是给任何想用技术来进行创作创新的人设计的。它是一款简单、有趣、实用的工具&#xff0c;你可以用它去打造你身边的世界。 特性 CPU 全志H616四核64位1.5GHz高性能Cortex-A53处理器GPU MaliG31MP2 Supports…

【树】简要理解树的概念

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、树的概念2、树的相关概念3、结语 1、树的概念 树是一种非线性的数据结构&#xff0c;它…

[FSCTF 2023]ez_php1

一共有三小关 第一关&#xff1a;md5加密 第二关&#xff1a;反序列化 重点 单个字符串序列化 unserialize($str) "$KEY" <?php $KEY"YES I love";echo serialize($KEY); s:10:"YES I love"; 第三关&#xff1a; 反序列化 把a的地址赋给…

【SpringBoot】 什么是springboot(二)?springboot操作mybatisPlus、swagger、thymeleaf模板

文章目录 SpringBoot第三章1、整合mybatsPlus1-234-67-10问题 2、整合pageHelper分页3、MP代码生成器1、编写yml文件2、导入依赖3、创建mp代码生成器4、生成代码5、编写配置类扫描mapper类6、编写控制器类 4、swagger1、什么是swagger2、作用3、发展历程4、一个简单的swagger项…

Hexo博客重新部署与Git配置

由于电脑重装了一次&#xff0c;发现之前Hexo与NexT主题版本过于落后&#xff0c;重新部署了下。 1 Node.js与git安装 这一块安装就不赘述了。去两个官网找安装文件安装即可。 node.js git 打开git以后配置的几个关键命令行。 git config --global user.name "你的gi…

ArcGIS水文水环境数据编辑、管理、处理与分析;ArcGIS水文分析及流域特征提取;湖泊水库水环境监测及评价;河道水污染预测与水环境容量计算等案例实践

目录 专题一 ArcGIS&#xff1a;数据管理 专题二 ArcGIS&#xff1a;数据转换 专题三 ArcGIS&#xff1a;地图制作 专题四 水文水环境数据编辑与管理 专题五 水文水环境数据处理与分析 专题六 ArcGIS水文分析及流域特征提取 专题七 湖泊水库水环境监测及评价 专题八 河…