彻底解决 Stata 无法读取过宽文件的问题&cnstock2 命令获取上市公司基本情况信息

彻底解决 Stata 无法读取过宽文件的问题&cnstock2 命令获取上市公司基本情况信息

在使用 Stata 爬数据的时候经常会遇到这样一个问题,就是文件中有的行过长(大约超过两万个字符就很难处理了)。这个时候会无法直接读入 Stata 作为一个变量处理。在过去,我常用的折中办法是使用 fileread()函数或者手动断行(当前这里需要用到 Sublime Text3 等编辑器的替换功能)。然而就在昨天晚上,我发现了一个永久解决这个麻烦的办法。

问题是这样出现的,我发现了这个接口:

http://stockdata.stock.hexun.com/gszl/data/jsondata/jbgk.ashx?count=5000&titType=null&page=1&callback=hxbase_json15

这个接口提供了 json 格式的全部沪深两市上市公司的基本信息,网页浏览的话是这样的:

如果把这个接口的数据下载为 txt 文件的话,你会发现这个文件只有一行,而且有 200 多万个字符。当然也可以通过修改接口的 count 参数和 page 参数分成 100 多次处理,但是效率肯定是非常低的。

Mac 用户从这里阅读

我就觉得一定有处理文本文件的 shell 命令,然后找了一会儿,发现tr命令可以实现,下面的 shell 命令就可以实现把文本中的所有{替换成换行符然后再使用重定向符>将结果输出至另外一个文件my.txt的操作:

1
cat temp.txt|tr "{" "\n" > my.txt

打开my.txt

然后就很容易处理啦,下面的代码就能整理好这份数据了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
!curl  "http://stockdata.stock.hexun.com/gszl/data/jsondata/jbgk.ashx?count=5000&titType=null&page=1&callback=hxbase_json15" | tr "{" "\n" > my.txt
utrans my.txt
infix strL v 1-20000 using my.txt, clear
drop in 1/2
split v, parse(,)
drop v
keep v1 v3 v4 v5 v6 v7 v8 v9 v12 v13 v14
replace v1 = ustrregexs(1) if ustrregexm(v1, `"'(.*)'"')
label var v1 "序号"
ren v1 number
gen code = ustrregexs(1) if ustrregexm(v3, `"\((.*)\)"')
order number code
replace v3 = ustrregexs(1) if ustrregexm(v3, `"'(.*)\("')
label var v3 "公司名称"
ren v3 name
label var code "公司代码"
replace v4 = ustrregexs(1) if ustrregexm(v4, `"'(.*)'"')
label var v4 "总股本(亿股)"
ren v4 total_stock_num
replace v5 = ustrregexs(1) if ustrregexm(v5, `"'(.*)'"')
replace v6 = ustrregexs(1) if ustrregexm(v6, `"'(.*)'"')
replace v7 = ustrregexs(1) if ustrregexm(v7, `"'(.*)'"')
replace v8 = ustrregexs(1) if ustrregexm(v8, `"'(.*)'"')
replace v9 = ustrregexs(1) if ustrregexm(v9, `">(.*)<"')
replace v12 = ustrregexs(1) if ustrregexm(v12, `"">(.*)</a>"')
replace v13 = ustrregexs(1) if ustrregexm(v13, `"">(.*)</a>"')
replace v14 = ustrregexs(1) if ustrregexm(v14, `"'(.*)'"')
replace v14 = ustrregexs(1) if ustrregexm(v12, `"'(.*)'"')
replace v12 = "" if index(v12, "price")
replace v13 = "" if index(v13, "view")
compress
label var v5 "流通股本(亿股)"
ren v5 outstanding_stock_num
label var v6 "流通市值(亿元)"
ren v6 outstanding_stock_value
label var v7 "注册资本(万元)"
ren v7 registered_capital
label var v8 "市盈率"
ren v8 pe_ratio
label var v9 "所属行业"
ren v9 industry
label var v12 "所属概念"
ren v12 concept
label var v13 "所属地域"
ren v13 area
label var v14 "收盘价"
ren v14 close
foreach i of varlist _all{
cap replace `i' = "" if `i' == "--"
}
destring number total_stock_num outstanding_stock_num outstanding_stock_value registered_capital pe_ratio close, replace
save allstock, replace
export excel using allstock.xlsx, replace firstrow(var)

整理结果:

最后我再把这段代码打包成一个命令——cnstock2
文件下载:
cnstock2.ado
cnstock2.sthlp
示例:

1
2
3
4
5
6
/* 下载两市所有上市公司的基本情况数据: */
cnstock2
/* 下载沪市所有上市公司的基本情况数据: */
cnstock2, m(SH)
/* 下载深市所有上市公司的基本情况数据: */
cnstock2, m(SZ)

此外上面代码中的下面这几行代码

1
2
3
copy "http://stockdata.stock.hexun.com/gszl/data/jsondata/jbgk.ashx?count=5000&titType=null&page=1&callback=hxbase_json15" temp.txt, replace
utrans temp.txt
!cat temp.txt|tr "{" "\n" > my.txt

实际上是可以换成下面的这一句:

1
2
!curl "http://stockdata.stock.hexun.com/gszl/data/jsondata/jbgk.ashx?count=5000&titType=null&page=1&callback=hxbase_json15" | tr "{" "\n" > my.txt
utrans my.txt

附注
utrans 命令是我自己编写的用于快速转码的命令, 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*! utf-8中文转码
*! utrans 文件名.后缀名
*! 示例:utrans temp.do
cap prog drop utrans
prog define utrans
version 14.0
syntax anything
cap preserve
clear
cap qui{
unicode encoding set gb18030
unicode translate "`anything'"
unicode erasebackups, badidea
unicode analyze "`anything'"
unicode erasebackups, badidea
}
if r(N_needed) == 0 di in yellow "转码完成"
if r(N_needed) != 0 di in red "转码失败"
end

Windows 用户从这里阅读

Windows 的 Powershell 环境可以进行文件内容的替换, 但是很尴尬的是 powershell 中的换行符是`n, 而下面的语句:

1
2
copy "http://stockdata.stock.hexun.com/gszl/data/jsondata/jbgk.ashx?count=5000&titType=null&page=1&callback=hxbase_json15" temp.txt, replace
!powershell -Command "(gc temp.txt) - replace '{', '`n' > my.txt"

非常巧妙地与 Stata 中的局部宏的引用“撞衫”了! 所以上面的方法就不可行了.
Windows 系统并没有自带 curl 命令, 更没有 tr 命令, 所以首先得安装一下 curl 命令:

  • 首先打开命令提示符,输入where powershell找到 powershell.exe 的位置, 然后找到它右键选择以管理员身份打开. 然后就会弹出来一个蓝色的命令行界面.
  • 然后可以安装一个包管理工具 choco(这里参考了这篇文章《在 windows 下使用 choco 作为包管理工具》). 在以管理员身份打开的 powershell 里依次输入下面几句命令:
1
2
3
4
5
Set-ExecutionPolicy RemoteSigned
/* 安装choco */
iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex
/* 安装curl */
choco install curl

然后是安装另外一个命令sed, 这个命令的下载地址是:

http://batch-cn.qiniudn.com/tool/4.0.7/sed.exe

下载之后将sed.exe文件放入C:\Windows\System32即可.

如果你成功的安装好了 curl 和 sed 之后, 下面的命令就能实现了自动换行了:

1
2
!curl "http://stockdata.stock.hexun.com/gszl/data/jsondata/jbgk.ashx?count=5000&titType=null&page=1&callback=hxbase_json15" -o temp.txt
!sed -i "s/{/\n/g" temp.txt

此外 WindowsOS 用户也可以下载 tr 命令, 这样上面的 cnstock2 命令就能运行了, tr 命令的下载地址为: tr, 安装方法与上面介绍的sed一样. 安装之后就能使用 sed 了.

最后

欢迎经常浏览我的网站, 网站的文章基本每天都会有几篇更新, 另外我最近还为自己的网站添加了二级菜单和数据图表界面, 数据图表提供了各种最新的数据和图表展示以及各种格式的下载链接.

其它应用

最后再贴上一段今天随手写的代码, 用于爬取余额宝 7 日年化收益率的数据. 使用上面的方法就能够非常方便的获取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
!curl "http://img1.money.126.net/data/fn/nav/000198.json?callback=_jsonp0"| tr "[" "\n" > temp.txt
infix strL v 1-2000 using temp.txt, clear
drop in 1/2
split v, parse(,)
keep v1 v2 v3 v4 v4
replace v1 = subinstr(v1, `"""', "", .)
replace v4 = subinstr(v4, `"]"', "", .)
gen date = date(v1, "YMD")
format date %tdCY-N-D
drop v1
destring, replace
format v3 %6.4f
order date
ren v3 万份收益
replace v2 = 100*v2
ren v2 余额宝7日年化收益率
ren v4 一年定存利率
ren date 日期
erase temp.txt
gsort 日期

这个图是这个样子的:

# Stata

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×