还是跟着@Jack-Cui老哥教程跟着编的爬虫,稍微改动了下,主要是mysql的插入方式,我使用了lazyspider的方法,不需要手动撸sql语句,还用的progressbar模块,可以显示进度条(不过不能再cmd用!!)
原网址:https://blog.csdn.net/c406495762/article/details/77801899
要点:1.eval()可以把字串符变为 变量
2.利用循环生成创建表格的sql语句
3.lazystore的使用
4.progressbar模块生成进度条
代码如下
#-*- coding:UTF-8 -*-
import sys
import requests
from bs4 import BeautifulSoup
import re
from lazyspider.lazystore import LazyMysql
import time
from progressbar import *
class FinancialData():
def __init__(self):
# 服务器域名
self.server = 'http://quotes.money.163.com/'
self.cwnb = 'http://quotes.money.163.com/hkstock/cwsj_'
# 主要财务指标
self.cwzb_dict = {'EPS': '基本每股收益', 'EPS_DILUTED': '摊薄每股收益', 'GROSS_MARGIN': '毛利率',
'CAPITAL_ADEQUACY': '资本充足率', 'LOANS_DEPOSITS': '贷款回报率', 'ROTA': '总资产收益率',
'ROEQUITY': '净资产收益率', 'CURRENT_RATIO': '流动比率', 'QUICK_RATIO': '速动比率',
'ROLOANS': '存贷比', 'INVENTORY_TURNOVER': '存货周转率', 'GENERAL_ADMIN_RATIO': '管理费用比率',
'TOTAL_ASSET2TURNOVER': '资产周转率', 'FINCOSTS_GROSSPROFIT': '财务费用比率', 'TURNOVER_CASH': '销售现金比率',
'YEAREND_DATE': '报表日期'}
# 利润表
self.lrb_dict = {'TURNOVER': '总营收', 'OPER_PROFIT': '经营利润', 'PBT': '除税前利润',
'NET_PROF': '净利润', 'EPS': '每股基本盈利', 'DPS': '每股派息',
'INCOME_INTEREST': '利息收益', 'INCOME_NETTRADING': '交易收益', 'INCOME_NETFEE': '费用收益',
'YEAREND_DATE': '报表日期'}
# 资产负债表
self.fzb_dict = {
'FIX_ASS': '固定资产', 'CURR_ASS': '流动资产', 'CURR_LIAB': '流动负债',
'INVENTORY': '存款', 'CASH': '现金及银行存结', 'OTHER_ASS': '其他资产',
'TOTAL_ASS': '总资产', 'TOTAL_LIAB': '总负债', 'EQUITY': '股东权益',
'CASH_SHORTTERMFUND': '库存现金及短期资金', 'DEPOSITS_FROM_CUSTOMER': '客户存款',
'FINANCIALASSET_SALE': '可供出售之证券', 'LOAN_TO_BANK': '银行同业存款及贷款',
'DERIVATIVES_LIABILITIES': '金融负债', 'DERIVATIVES_ASSET': '金融资产', 'YEAREND_DATE': '报表日期'}
# 现金流表
self.llb_dict = {
'CF_NCF_OPERACT': '经营活动产生的现金流', 'CF_DIV_REC': '已收利息', 'CF_INT_PAID': '已付利息',
'CF_INT_REC': '已收股息', 'CF_DIV_PAID': '已派股息', 'CF_INV': '投资活动产生现金流',
'CF_FIN_ACT': '融资活动产生现金流', 'CF_BEG': '期初现金及现金等价物', 'CF_CHANGE_CSH': '现金及现金等价物净增加额',
'CF_END': '期末现金及现金等价物', 'CF_EXCH': '汇率变动影响', 'YEAREND_DATE': '报表日期'}
# 请求头
self.headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.109 Safari/537.36'}
#总表
self.table_name={'cwzb': '主要财务指标', 'lrb': '利润表', 'fzb': '资产负债表', 'llb': '现金流量表'}
def get_name(self,code):
'''输入股票编号,返回名字,报表时间'''
code=str(code)
target_url = self.cwnb+code+'.html'
req = requests.get(url=target_url, headers=self.headers)
req.encoding = 'utf-8'
html = req.text
page_bf = BeautifulSoup(html, 'lxml')
# 股票名称
name = page_bf.find_all('span', class_='name')[0].string
#报表初始时间———结束时间
time=page_bf.find_all('select',id='cwzb1')[0].select('option')
endtime=time[0].text
starttime=time[-1].text
return name,starttime,endtime
def get_informations(self,code):
'''返回名字,汇总字典{报表:对应list,,,}'''
# 整个汇总字典结构如下{'cwzb':[{'TURNOVER':33,'股票名':tx,···}、{}],'lrb':[{},{}],····}
name, starttime, endtime=self.get_name(code)
table_dict={} #总字典
for table in self.table_name.keys():#每个表的数据轮流单独处理
url=self.server+'hk/service/cwsj_service.php?symbol={}&start={}&end={}&type={}&unit=yuan'\
.format(code,starttime,endtime,table)
#打开每个数据类型对应的网页,把该表格的数据汇总,每个年度的字典组成的list
table_text=requests.get(url=url,headers=self.headers).json()
#得到对应的中英文转换表,self.cwzb_dict
dicts=eval('self.'+table+'_dict')
list=[]
for one in table_text: #英文名的表头全部换为中文,再把每个年度的字典放进list里,然后再把这个list放进总字典
c={dicts[zhong]:one[ying] for zhong in dicts.keys() for ying in one.keys() if ying==zhong}
c['股票名']=name
c['股票代码']=code
list.append(c) #c就是每一年度的具体报表,list就是该报表的每个年度的汇总,table_dict就是4个报表的汇总
table_dict[table]=list#每个报表:list
return name,table_dict
def insert_tables(self,table_dict):
'''先创建table(现金流表、、),然后把每一年的数据插入'''
for table in table_dict.keys():#循环总字典
table_name=self.table_name[table] #总字典key是英文(cwzb、、),先转换为中文
#循环数据(dict)把每一列的列名添加到创建table的sql语句中
sql="CREATE TABLE IF NOT EXISTS %s (报表日期 char(30)"% table_name
for key in table_dict[table][0].keys():#总字典→报表→第一个字典的keys
if key!='报表日期':
sql+=','+key+' char(30)'
sql=sql+")ENGINE=InnoDB DEFAULT CHARSET='utf8'"
#运用lazymysql,登录mysql然后执行
TEST_DB = {
'host': 'localhost',
'user': 用户名,
'password': 密码,
'db': 'test'
}
store = LazyMysql(TEST_DB)
store.query(sql) #直接操作sql语句,创建表格table
bar = ProgressBar(widgets=[ #使用progress模块,显示进度条
' [正在下载 ',
Percentage(),
Bar() , '] ',table_name,
])
#把list的每一年的数据(dict)插入到对应的表格里
for item in bar(table_dict[table]):#循环报表的list
time.sleep(0.1)
store.save_one_data(item,table_name) #插入到mysql----表名,字典
if __name__ == '__main__':
print('*' * 100)
print('\t\t\t\t\t财务数据下载助手\n')
print('*' * 100)
fd = FinancialData()
# 上市股票地址
code = input('请输入股票代码:')
name,table_dict=fd.get_informations(code)
print('\n %s:(%s)财务数据下载中!\n' % (name, code))
fd.insert_tables(table_dict)
print('\n %s:(%s)财务数据下载完成!' % (name, code))
其中创建table的语句我用循环自动生成了,不需要自己手撸这么痛苦!!!
CREATE TABLE IF NOT EXISTS 利润表 (报表日期 char(30),每股派息 char(30),总营收 char(30),股票代码 char(30),经营利润 char(30),除税前利润 char(30),交易收益 char(30),净利润 char(30),利息收益 char(30),股票名 char(30),每股基本盈利 char(30),费用收益 char(30))ENGINE=InnoDB DEFAULT CHARSET='utf8'
效果图:
插入图: