1.课题概述
课题背景:随着投资市场的发展和投资者对股票信息需求的增加,准确获取和及时分析股票市场数据对于投资决策和风险控制至关重要。东方财富网作为中国领先的金融信息服务提供商,汇集了大量的股票信息,包括股票行情、公司公告、财务数据等。通过爬取东方财富网上的股票信息,可以帮助投资者更好地了解市场动态,进行数据分析和决策支持。
课题目标:本课程设计的目标是设计并实现一个基于Python的股票信息爬虫与数据分析系统,以自动抓取东方财富网上的股票数据并进行相关的数据分析和可视化展示。
2.系统分析设计部分
2.1系统的功能
该系统的主要功能是从东方财富网上抓取股票信息,将其存放在excle中并进行数据清洗和数据分析。
包括:(1) 实现一个高效可靠的网络爬虫模块,能够自动抓取东方财富网上的股票信息,包括股票代码、股票名称、股价、涨跌幅等。(2) 设计数据存储与处理模块,对抓取的股票数据进行预处理,包括去除无效数据、处理缺失值和异常值,并将其保存在excle表中。(3)利用Python的数据分析库(如Pandas、Matplotlib)对股票数据进行统计分析。
2.2可行性分析
技术可行性:使用Python的爬虫技术抓取网页数据以及数据分析库进行数据处理和分析,从技术上来看是可行的。
经济可行性:该系统能够提供准确的股票信息,对投资者和用户具有一定的经济效益,因此在经济上是可行的。
2.3需求分析
该系统可以实现自动抓取东方财富网上的股票数据并进行相关的数据分析和可视化展示,例如绘制绘制股票价格趋势图和绘制股票成交量柱状图。这可以帮助投资者更好地了解市场动态,使其进行数据分析和决策更为便捷。
2.4概要设计
2.4.1系统功能模块划分
(1)数据爬取与处理模块:负责从东方财富网获取股票信息的功能并对对爬取的数据进行处理和存放的功能。
import json
import os
import pandas as pd
import requests
import openpyxl
session = requests.session()
# 数据格式化
def pd_unit(newArr):
result = format(float(newArr) / 10000, '.2f')
return result
# 获取K线数据
def getLinesData(code: str, id: str):
# beg和end可以调整数据区间
params = f"fields1=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13&" \
"fields2=f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61&" \
"beg=20220101&" \
"end=20221231&" \
"ut=fa5fd1943c7b386f172d6893dbfba10b&" \
"rtntype = 6&" \
f"secid={code}.{id}&" \
"klt=101&" \
"fqt=1&"
res = session.get("http://push2his.eastmoney.com/api/qt/stock/kline/get", params=params)
data = json.loads(res.text)
return data["data"]["klines"]
# 获取公司数据
def getCompanyData(code: str, id: str):
area = ''
if code == "0":
area = "SZ"
elif code == "1":
area = "SH"
res = session.get(f"https://emweb.securities.eastmoney.com/PC_HSF10/CompanySurvey/PageAjax?code={area}{id}")
result = json.loads(res.text)
cData = []
cData.append(result["jbzl"][0]["PROVINCE"])
cData.append(result["jbzl"][0]["SECURITY_NAME_ABBR"])
return cData
# 获取股票概念
def getConcept(code: str, id: str):
params = f"fltt=1&"\
"invt=2&"\
"fields=f14%2Cf12%2Cf13%2Cf3%2Cf152%2Cf4%2Cf128%2Cf140%2Cf141&"\
f"secid={code}.{id}&"\
"ut=fa5fd1943c7b386f172d6893dbfba10b&"\
"pi=0&"\
"po=1&"\
"np=1&"\
"pz=5&"\
"spt=3"
res = session.get("http://push2.eastmoney.com/api/qt/slist/get", params=params)
data = json.loads(res.text)
result = data["data"]["diff"]
concept = []
for item in result:
concept.append(item["f14"])
return concept
# 获取股票列表
def getStockList(title: str):
# pz可以调整爬取股票的数量
params = "pn=1&"\
"pz=80&"\
"po=1&"\
"np=1&"\
"ut=bd1d9ddb04089700cf9c27f6f7426281&"\
"fltt=2&"\
"invt=2&"\
"wbp2u=|0|0|0|web&"\
"fid=f3&"\
f"fs=b:{title}+f:!50&"\
"fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152,f45&"\
res = session.get("http://83.push2.eastmoney.com/api/qt/clist/get", params=params)
result = json.loads(res.text)
lists = result["data"]["diff"]
data = []
for item in lists:
stockObj = {"code": item["f13"], "id": item["f12"]}
data.append(stockObj)
return data
#打包为xlsx文件
def getxlsx(code: str, id: str):
cur_dir = os.path.dirname(__file__)
res = pd.DataFrame(columns=(
"股票代码", "股票简称", "日期", "开盘", "收盘", "最高", "最低", "涨跌幅", "涨跌额", "成交量(万)", "成交额(万)", "振幅",
"换手率", "行业", "地区", "概念1", "概念2", "概念3", "概念4"))
linesData = getLinesData(code, id)
concept = getConcept(code, id)
companyData = getCompanyData(code, id)
# 计数
count = 1
for item in linesData:
newArr = item.split(',')
count = count + 1
# 行业 地区 概念
res.loc[count] = [id, companyData[1], newArr[0], newArr[1], newArr[2], newArr[3], newArr[4], newArr[8] + '%',
newArr[9], pd_unit(newArr[5]), pd_unit(newArr[6]), newArr[7] + '%', newArr[10] + '%',
concept[0], companyData[0], concept[1], concept[2], concept[3], concept[4]]
res.to_excel(os.path.join(cur_dir, id + ".xlsx"))
def main():
stocks = getStockList("BK0476")
for stock in stocks:
try:
getxlsx(str(stock["code"]), stock["id"])
except Exception as e:
print("爬取失败,错误股票代码" + stock["id"], e)
continue
else:
print("股票" + stock["id"]+"爬取成功")
if __name__ == '__main__':
main()
(2)数据可视化模块:绘制股票价格分析图和2022年股票成交量柱状图的功能。
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
def plotStockPriceTrend(date, close_price, stock_symbol):
# 创建绘图对象和子图
fig, ax = plt.subplots()
# 绘制价格趋势图
ax.plot(date, close_price, color='blue')
# 设置X轴和Y轴标签
ax.set_xlabel('日期(月)')
ax.set_ylabel('收盘价(元)')
# 显示网格线
ax.grid(True)
# 设置每个月的第一天显示日期标签,其他日期隐藏
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m'))
# 设置X轴刻度标签水平放置
plt.xticks(rotation=0)
# 设置中文字体为黑体
plt.rcParams['font.sans-serif'] = ['SimHei']
# 设置标题为股票简称
plt.title(f'2022年至2023年1月 {stock_symbol} 股票价格趋势')
# 显示图形
plt.show()
def plotStockVolume(date, volume, stock_symbol):
# 创建日期和成交量的DataFrame
df = pd.DataFrame({'date': date, 'volume': volume})
# 按月汇总并计算每月总成交量
df['month'] = df['date'].dt.to_period('M') # 添加月份列
monthly_volume = df.groupby('month')['volume'].sum()
# 提取月份作为横坐标(去除年份)
months = [m.strftime('%m') for m in monthly_volume.index]
# 提取每个月的总成交量作为纵坐标
monthly_volume_values = monthly_volume.values
# 创建绘图对象和子图
fig, ax = plt.subplots()
# 绘制成交量柱状图
ax.bar(months, monthly_volume_values, color='green')
# 设置X轴和Y轴标签
ax.set_xlabel('月份')
ax.set_ylabel('成交量')
# 设置X轴刻度标签水平放置
plt.xticks(rotation=0)
# 设置中文字体为黑体
plt.rcParams['font.sans-serif'] = ['SimHei']
# 设置标题为股票简称
plt.title(f'2022年至2023年1月 {stock_symbol} 股票月均交易量图')
# 显示图形
plt.show()
def main():
# 从Excel表格中读取数据
df = pd.read_excel(r'D:\PyCharm Community Edition 2021.2.2\project\003012.xlsx')
# 提取需要的列数据
date = df['日期']
close_price = df['收盘']
volume = df['成交量(万)']
stock_symbol = df['股票简称'].iloc[0] # 获取第一行的股票简称
# 转换日期格式
date = pd.to_datetime(date)
# 调用绘图函数绘制股票价格趋势图
plotStockPriceTrend(date, close_price, stock_symbol)
# 调用绘图函数绘制股票成交量柱状图
plotStockVolume(date, volume, stock_symbol)
if __name__ == '__main__':
main()