查看原文
其他

stata调用python爬取时间数据——借他山之石以攻玉

爬虫俱乐部 Stata and Python数据分析 2022-03-15

本文作者:陈志玲

文字编辑:张馨月

技术总编:张计宝

写在前面:



利用stata调用python是stata16中的一个新增功能。对此,相信很多人和小编当初的想法一样,觉得该功能是多此一举。但是小编在深入了解学习之后发现,该功能简直是stata用户的福音。该功能使得,我们可以先利用python爬取数据,然后再利用用户所熟悉的stata去处理数据,因为stata在处理数据方面具有一定的优势

那么今天我们就来看看,怎样利用stata调用python爬取数据,再用stata进行处理?今天试爬的数据是巨潮网上的预约年报的披露时间数据。


进入Python交互模式


首先做好准备工作,清空内存,创建好路径,进入路径,然后只需要输入python,即可进入python交互模式,具体程序如下:

clear cap mkdir "D:\爬虫\A股年报披露时间" cd "D:\爬虫\A股年报披露时间"python
结果如图:


此时出现报错,报错信息提示,end命令缺失。这就是需要我们注意的地方,进入python交互模式之后,在dofile中的程序中不可以像之前stata程序一样一行一行运行,而必须将python和end命令(包括python和end命令)之间的所有行一起运行,即必须以end命令结尾。


Python爬取网络数据


(1)利用python爬取网页源代码

大家可以进入巨潮资讯网(http://www.cninfo.com.cn/new/index),点击上图的数据—>定期报告预约披露,可以看到该网页包含190页的数据,为了方便起见,今天只爬取这190页的数据。


 

为方便stata与python使用循环,下面将利用python语法封装函数。爬取网页源代码的程序如下(此处原理参考往期推文《玩转python之“手把手”教你爬数据》):

def GetSourceCode(page) : #获取网页源代码 import requests import time url = "http://www.cninfo.com.cn/new/information/getPrbookInfo" headers = { "Accept":"*/*", "Accept-Encoding":"gzip, deflate", "Accept-Language":"zh-CN,zh;q=0.9", "Connection":"keep-alive", "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8", "Host":"www.cninfo.com.cn", "Origin":"http://www.cninfo.com.cn", "Referer":"http://www.cninfo.com.cn/new/commonUrl?url=data/yypl", "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36", "X-Requested-With":"XMLHttpRequest" } postdata = { "sectionTime":"2019-12-31", "firstTime":"", "lastTime":"", "market":"szsh", "stockCode":"", "orderClos":"", "isDesc":"", "pagesize":20, "pagenum":page } html = requests.post(url, headers = headers, data = postdata)  return html.text

(2)解析嵌套字典——jsonpath模块

我们要获取的数据如图所示:


在我们的往期爬虫推文中,面对多层嵌套字典的json文件数据的获取,都是使用json库解析,往往需要多层遍历比较繁杂。今天介绍一个,对于多层嵌套字典更简洁的解决方式——jsonpath模块的应用。首先安装第三方模块jsonpath,在python的命令窗口输入 pip install jsonpath,安装成功后即可。

然后开始解析上面GetSourceCode()函数获取的网页源代码,具体程序如下:

def GetList(html) : import jsonpath true = True false = False page = eval(html) #eval函数就是将html转换为它原本的格式,这里是字典 stkcd_list = jsonpath.jsonpath(page['prbookinfos'], "$..seccode") #$从根节点开始,..指不管什么位置,选择符合条件的内容,获取股票代码 date1_list = jsonpath.jsonpath(page['prbookinfos'], "$..f002d_0102")#从根节点开始,获取所有Key为f002d_0102的值 date2_list = jsonpath.jsonpath(page['prbookinfos'], "$..f003d_0102") date3_list = jsonpath.jsonpath(page['prbookinfos'], "$..f004d_0102") date4_list = jsonpath.jsonpath(page['prbookinfos'], "$..f005d_0102") date5_list = jsonpath.jsonpath(page['prbookinfos'], "$..f006d_0102")  return stkcd_list, date1_list, date2_list, date3_list, date4_list, date5_list

(3)将数据存储于stata

但目前为止,我们已经利用python爬取到了股票代码和日期数据,接下来就是将数据全部存储于stata中。这需要调用stata中的sfi(StataFunction Interface)模块中的Data类。在Data类中,set族方法是设置当前数据的一些属性;add族方法是向当前数据中添加观察值或变量;store族方法是将数据保存到当前数据集中。

具体程序如下:

def Convert2dta(stkcd_list, date1_list, date2_list, date3_list, date4_list, date5_list) : #将Python获取的数据存储到Stata中 from sfi import Data Data.setObsTotal(len(stkcd_list)) #设置数据属性 Data.addVarStr("stkcd", 6) #添加stkcd变量 Data.store("stkcd", None, stkcd_list)#存储stkcd变量 Data.addVarStr("date1", 10) Data.store("date1", None, date1_list) Data.addVarStr("date2", 10) Data.store("date2", None, date2_list) Data.addVarStr("date3", 10) Data.store("date3", None, date3_list) Data.addVarStr("date4", 10) Data.store("date4", None, date4_list) Data.addVarStr("date5", 10)  Data.store("date5", None, date5_list)

最后需要一个调用以上所有函数的函数,程序如下:

def GetData(page) : #获取一页的数据 html = GetSourceCode(page) stkcd_list, date1_list, date2_list, date3_list, date4_list, date5_list = GetList(html) Convert2dta(stkcd_list, date1_list, date2_list, date3_list, date4_list, date5_list)end

以end命令结束,我们就完成了python的调用,即停止调用python。

注意在stata中调用python时,python代码依旧需要严格遵守缩进规则,注释也是python中的注释方式(本文用#注释)。


使用stata处理数据


现在只需要调用以上程序即可获得指定数据。接下来就是stata命令,循环190页,获得每一页的数据,然后保存:

forvalues i = 1/190 { clear python: GetData(`i') save "`i'.dta", replace}

运行程序即可获得如图所示数据集:

然后合并数据集:

forvalues i = 1/190 { append using "`i'.dta"}

改变数据类型:

destring stkcd, replace //destring 将字符型数据转换为数值型数据forvalues i = 1/5 { gen PredictedDate`i' = date(date`i', "YMD") //生成新的变量存储日期 format %dCY-N-D PredictedDate`i' //指定格式为年月日} drop date1 - date5    //删除原来变量

因为有部分股票变更过预约时间,如图:


所以需要如下处理:

gen PredictedDate = PredictedDate1 // PredictedDate为最终预约时间PredictedDate1为首次预约时间
forvalues i = 2/5 { replace PredictedDate = PredictedDate`i' if PredictedDate`i' != . } //对变更过的,令最终日期为最后一个非缺失值format %dCY-N-D PredictedDateorder stkcd PredictedDate //最后将stkcd PredictedDate进行排序sort PredictedDate         //数据按最终预约披露时间PredictedDate排序

结果如图所示:



到这里,我们就顺利的用stata调用python攻取了玉(时间数据),并且将数据存储到了stata的数据集里,进行了进一步的处理,最后得到了年报最新预约的披露日期。看到这里,对于这个新功能,你是不是心动啦,赶快拿出stata试一试吧!


完整程序

clear //清空内存cap mkdir "D:\爬虫\A股年报披露时间" //cap mkdircd "D:\爬虫\A股年报披露时间"
python
def GetSourceCode(page) : #获取网页源代码 import requests import time url = "http://www.cninfo.com.cn/new/information/getPrbookInfo" headers = { "Accept":"*/*", "Accept-Encoding":"gzip, deflate", "Accept-Language":"zh-CN,zh;q=0.9", "Connection":"keep-alive", "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8", "Host":"www.cninfo.com.cn", "Origin":"http://www.cninfo.com.cn", "Referer":"http://www.cninfo.com.cn/new/commonUrl?url=data/yypl", "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36", "X-Requested-With":"XMLHttpRequest" } postdata = { "sectionTime":"2019-12-31", "firstTime":"", "lastTime":"", "market":"szsh", "stockCode":"", "orderClos":"", "isDesc":"", "pagesize":20, "pagenum":page } html = requests.post(url, headers = headers, data = postdata) return html.text

def GetList(html) : #利用jsonpath模块解析网页源代码 import jsonpath #jsonpath模块用于获取多层嵌套字典的值,不需要一层层遍历获取 true = True #正确即返回数据 false = False page = eval(html) #eval函数就是将html转换为它原本的格式——字典 stkcd_list = jsonpath.jsonpath(page['prbookinfos'], "$..seccode") #$从根节点开始,..指不管位置,选择符合条件的内容,此行为获取股票代码 date1_list = jsonpath.jsonpath(page['prbookinfos'], "$..f002d_0102") #从根节点开始,获取所有Key为f002d_0102的值 date2_list = jsonpath.jsonpath(page['prbookinfos'], "$..f003d_0102") date3_list = jsonpath.jsonpath(page['prbookinfos'], "$..f004d_0102") date4_list = jsonpath.jsonpath(page['prbookinfos'], "$..f005d_0102") date5_list = jsonpath.jsonpath(page['prbookinfos'], "$..f006d_0102") return stkcd_list, date1_list, date2_list, date3_list, date4_list, date5_list
def Convert2dta(stkcd_list, date1_list, date2_list, date3_list, date4_list, date5_list) : #将Python获取的数据存储到Stata中 from sfi import Data Data.setObsTotal(len(stkcd_list)) #设置数据属性 Data.addVarStr("stkcd", 6) #添加stkcd变量 Data.store("stkcd", None, stkcd_list)#存储stkcd变量 Data.addVarStr("date1", 10) Data.store("date1", None, date1_list) Data.addVarStr("date2", 10) Data.store("date2", None, date2_list) Data.addVarStr("date3", 10) Data.store("date3", None, date3_list) Data.addVarStr("date4", 10) Data.store("date4", None, date4_list) Data.addVarStr("date5", 10) Data.store("date5", None, date5_list)
def GetData(page) : html = GetSourceCode(page) stkcd_list, date1_list, date2_list, date3_list, date4_list, date5_list = GetList(html) Convert2dta(stkcd_list, date1_list, date2_list, date3_list, date4_list, date5_list)end
forvalues i = 1/190 { clear python: GetData(`i') save "`i'.dta", replace}
clearforvalues i = 1/190 { append using "`i'.dta"}destring stkcd, replace //destring 将字符型数据转换为数值型数据forvalues i = 1/5 { gen PredictedDate`i' = date(date`i', "YMD") //生成新的变量存储日期 format %dCY-N-D PredictedDate`i' //指定格式为年月日}drop date1 - date5gen PredictedDate = PredictedDate1 forvalues i = 2/5 { replace PredictedDate = PredictedDate`i' if PredictedDate`i' != . //对变更过的,令最终日期为最后一个非缺失值}format %dCY-N-D PredictedDate //最后将变量排序order stkcd PredictedDate //数据按最终预约披露时间排序sort PredictedDate   






对我们的推文累计打赏超过1000元,我们即可给您开具发票,发票类别为“咨询费”。用心做事,不负您的支持!
往期推文推荐

全国31省GDP排行强势登场!

接力《发哨子的人》Stata版
批量实现WORD转PDF

Stata有问必答环节

我听到了企业的哀鸣
“物以类聚”、“近朱者赤”——机器学习初探之KNN
SFI:Stata与Python的数据交互手册(二)

从流调数据中寻找感染真相

熟悉又陌生的reshape

NBA球员薪资分析——基于随机森林算法(二)

NBA球员薪资分析——基于随机森林算法(一)

高亮输出之唐诗作者

湖北省各市疫情数据爬取

古代诗人总去的这些地方你一定要知道!

DataFrame数组常用方法(二)

ftools命令——畅游大数据时代的加速器

卫健委的“糊涂账”

Pandas中数据的排序与切片

关于我们



微信公众号“Stata and Python数据分析”分享实用的stata、python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。

此外,欢迎大家踊跃投稿,介绍一些关于stata和python的数据处理和分析技巧。
投稿邮箱:statatraining@163.com
投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存