程振兴 @czxa.top
截止今天,我已经在本博客上写了604.4k个字了!
在使用Stata爬数据的时候经常会遇到这样一个问题,就是文件中有的行过长(大约超过两万个字符就很难处理了)。这个时候会无法直接读入Stata作为一个变量处理。在过去,我常用的折中办法是使用fileread()函数或者手动断行(当前这里需要用到Sublime Text3等编辑器的替换功能)。然而就在昨天晚上,我发现了一个永久解决这个麻烦的办法。
问题是这样出现的,我发现了这个接口:
这个接口提供了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
3copy "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 | *! utf-8中文转码 |
Windows用户从这里阅读
Windows的Powershell环境可以进行文件内容的替换, 但是很尴尬的是powershell中的换行符是`n, 而下面的语句:
1 | copy "http://stockdata.stock.hexun.com/gszl/data/jsondata/jbgk.ashx?count=5000&titType=null&page=1&callback=hxbase_json15" temp.txt, replace |
非常巧妙地与Stata中的局部宏的引用“撞衫”了! 所以上面的方法就不可行了.
Windows系统并没有自带curl命令, 更没有tr命令, 所以首先得安装一下curl命令:
- 首先打开命令提示符,输入
where powershell
找到powershell.exe的位置, 然后找到它右键选择以管理员身份打开. 然后就会弹出来一个蓝色的命令行界面. - 然后可以安装一个包管理工具choco(这里参考了这篇文章《在windows下使用choco作为包管理工具》). 在以管理员身份打开的powershell里依次输入下面几句命令:
1 | Set-ExecutionPolicy RemoteSigned |
然后是安装另外一个命令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 日期
这个图是这个样子的: