前言
最近实习需要做一些关于问询函的研究,但手工整理相关信息实在太慢,于是想用爬虫一步到位。
准备工作
json包的抓取
上交所和深交所官网都有便捷的问询函列表页面供访客查看,也有友好的json数据包供我们抓取😆😆😆
很常规的json数据,我们只需要进行普通的解析工作就OK了~
获取其他页数的数据
观察json数据的地址:http://query.sse.com.cn/commonSoaQuery.do?jsonCallBack=jsonpCallback42130&siteId=28&sqlId=BS_KCB_GGLL&extGGLX=&stockcode=&channelId=10743%2C10744%2C10012&extGGDL=&order=createTime%7Cdesc%2Cstockcode%7Casc&isPagination=true&pageHelp.pageSize=15&pageHelp. pageNo=1&pageHelp.beginPage=1&pageHelp.cacheSize=1&pageHelp.endPage=31&type=&_=1596181186068
我们只需要对pageNo和beginPage进行修改就可以得到其他页数的数据了,常规!
查询股价接口
之前查阅了一些资料,关于股价历史信息的接口,有pandas_DataReader
库可以使用,它提供YahooFinance的接口,我们可以通过输入股票代码和查询日期范围直接进行查询,但效果并不好,一方面是访问速度比较慢,另一方面是一些股票代码查询不到。同花顺的API更别说,虽然功能强大,数据齐全,但是不免费哇!
后来我发现了BaoStock这个宝藏平台,免费提供接口,还有详细的函数说明,果断使用了,速度比YahooFinance快了好多好多倍(绝没恰饭,是真的好用,感谢这些提供开源平台供后人乘凉的大神们)。
这里是BaoStock提供的历史股价查询函数DEMO,可以根据自己的需求灵活修改。
代码编写
遍历爬取所有问询函
悄悄地说:好像上交所并没有做反爬,也可能几千条数据他们并不在乎
import pandas as pd
import requests
#新建一个dataframe,等会用来插入数据
df = pd.DataFrame(data=None, index=None, columns=['时间','标题','股票代码','问询函类型','文件地址'], dtype=None, copy=False)
#输入页码,用于遍历所有页码的json地址
def downlourl(currentpage):
url = "http://query.sse.com.cn/commonSoaQuery.do?siteId=28&sqlId=BS_GGLL&extGGLX=&stockcode=&channelId=10743%2C10744%2C10012&extGGDL=&order=createTime%7Cdesc%2Cstockcode%7Casc&isPagination=true&pageHelp.pageSize=15&pageHelp.pageNo=" + repr(currentpage) + "&pageHelp.beginPage=" + repr(currentpage) +"&pageHelp.cacheSize=1"
return(url)
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
for page in range(0,141):
r = requests.get(downlourl(page), headers=headers)
for i in r.json()['result']:
Date = i['cmsOpDate']
Title = i['docTitle']
stockCode = i['stockcode']
extWTFL = i['extWTFL']
Type = i['docType']
createTime = i['createTime']
docURL = i['docURL']
data = pd.DataFrame({'时间': Date,'标题':Title,'股票代码':stockCode,'问询函类型':extWTFL,'文件地址':i['docURL']},index =[0])
df = df.append(data,ignore_index=True)
print('完成爬取第%d页'%page)
`在这里插入代码片`df.to_csv('问询函.csv')
爬取后文件的样子是这样的:
查询被发函公司发函日(第T日)后3天的股价
利用BaoStock提供的接口函数,我们可以根据股票代码和日期范围输出得到dataframe格式的股价信息,非常详细。
通过刚才爬取到的信息,我们取出所需要的股票代码列,并将日期修改为统一的格式,与BaoStock所提供的接口函数相对应,用来获取第T天和第T+3天的数据
#获取询问函前后时间
import pandas as pd
import datetime
import baostock as bs
from datetime import timedelta
with open('上交所问询函.csv',encoding='utf-8') as f:
df = pd.read_csv(f)
#修改日期格式
df['时间'] = pd.to_datetime(df['时间'])
df['时间'] = df['时间'].dt.date
df_raw = pd.DataFrame(data=None, index=None, columns=['股票代码','第T天','第T+3天'], dtype=None, copy=False)
bs.login()
for i in range(0,len(df)):
#获取股票id,起始日期
df1 = df[['股票代码','时间']]
#股票代码的格式需要修改
stock_id ="sh."+str(df1['股票代码'][i])
start_date = df1['时间'][i]
end_date = start_date+timedelta(days = 10)
try:
rs = bs.query_history_k_data_plus(stock_id,
"date,code,close,preclose,adjustflag,turn,tradestatus,pctChg",
start_date=str(start_date), end_date=str(end_date),
frequency="d", adjustflag="3")
data_list = []
while (rs.error_code == '0') & rs.next():
data_list.append(rs.get_row_data())
stock_dt1 = pd.DataFrame(data_list, columns=rs.fields)
df2 = pd.DataFrame({'股票代码':stock_id,'第T天':stock_dt1.iloc[0]['close'],'第T+3天':stock_dt1.iloc[3]['close']},index = [0])
df_raw = df_raw.append(df2,ignore_index = True)
print('正在处理第'+str(i)+"条记录")
except:
#可能出现第T+3天在十天内查询范围内不存在的情况,也有通过股票代码查询不到的情况
df2 = pd.DataFrame({'股票代码':stock_id,'第T天':'error','第T+3天':'error'},index = [0])
df_raw = df_raw.append(df2,ignore_index = True)
print("第"+str(i)+"条记录出现问题")
bs.logout()
df_raw.to_csv('stock.csv')
我们可以得到第T日和T+3日的股价信息,当然也可以多记录几天的数据:
总结
这篇文章算是一次简单的记录,涉及到的爬虫知识并不难,爬取上交所和深交所还是比较友好的过程,不需要用到IP池,甚至不需要做随机UA,爬就完事儿了!在获取了pdf的地址后,可以通过pdfminer做进一步的pdf解析,得到文本后跟NLP联系起来玩出更多花样~