使用golang爬取股票数据

关键字:golang、股票、ohlc、指标
时间:2018年9月

// Copyright 2018 Wu Peng. All rights reserved.
//
package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"
)

func main() {
	downloadSymbols("symbols.csv")

	symbol := "sz002027"
	downloadOHLC(symbol, "ohlc-"symbol+".csv")

	symbol = "sh600585"
	downloadIndicators(symbol, "indicators-"+symbol+".json")

	symbol = "sh600660"
	downloadBonus(symbol, "bonus-"+symbol+".json")
}

// downloadSymbols() save symbols to a csv file.
//
// Format as follows:
// symbol
// --------
// sh600000
// sh600001
// sh600002
// ...
// --------
func downloadSymbols(filename string) {
	resp, err := http.Get("http://quote.eastmoney.com/stocklist.html")
	if err != nil {
		return
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	content := ""
	reg := regexp.MustCompile("s[hz][60]0\\d{4,4}")
	for _, s := range reg.FindAllString(string(body), -1) {
		content += s + "\n"
	}
	err = ioutil.WriteFile(filename, []byte(content), 0666)
}

// downloadOHLC() save a stock's OHLC data to a file.
//
// Format as follows:
// date   open  close high  low   volume
// -------------------------------------
// 180102 14.11 14.08 14.51 13.98 550796
// 180103 14.15 13.79 14.29 13.73 727753
// 180104 13.85 13.66 13.86 13.51 729298
// 180105 13.65 13.79 14.10 13.52 573245
// 180108 13.66 13.51 13.98 13.30 697819
// ...
// -------------------------------------
func downloadOHLC(symbol string, filename string) error {
	url := fmt.Sprintf("http://data.gtimg.cn/flashdata/hushen/daily/18/%s.js", symbol)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("http.Get():", err)
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		fmt.Println("http.Get():", "404 page not find.")
		return errors.New("HTTP 404.")
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("ioutil.ReadAll()", err)
		return err
	}
	str := string(body)
	str = strings.Replace(str, "\\n\\", "", -1)
	str = strings.Replace(str, "daily_data_18=\"\n", "", -1)
	str = strings.Replace(str, "\";", "", -1)
	err = ioutil.WriteFile(filename, []byte(str), 0666)
	if err != nil {
		fmt.Println("ioutil.WriteFile()", err)
	}
	return nil
}

// downloadIndicators() save a stock's indicators to a file.
//
// Format as follows:
// ----------------------------------
// [{
//   "date"       :"报告期",
//   "jbmgsy"     :"基本每股收益(元)",
//   "kfmgsy"     :"扣非每股收益(元)",
//   "xsmgsy"     :"稀释每股收益(元)",
//   "mgjzc"      :"每股净资产(元)",
//   "mggjj"      :"每股公积金(元)",
//   "mgwfply"    :"每股未分配利润(元)",
//   "mgjyxjl"    :"每股经营现金流(元)",
//   "yyzsr"      :"营业总收入(元)",
//   "mlr"        :"毛利润(元)",
//   "gsjlr"      :"归属净利润(元)",
//   "kfjlr"      :"扣非净利润(元)",
//   "yyzsrtbzz"  :"营业总收入同比增长(%)",
//   "gsjlrtbzz"  :"归属净利润同比增长(%)",
//   "kfjlrtbzz"  :"扣非净利润同比增长(%)",
//   "yyzsrgdhbzz":"营业总收入滚动环比增长(%)",
//   "gsjlrgdhbzz":"归属净利润滚动环比增长(%)",
//   "kfjlrgdhbzz":"扣非净利润滚动环比增长(%)",
//   "jqjzcsyl"   :"加权净资产收益率(%)",
//   "tbjzcsyl"   :"摊薄净资产收益率(%)",
//   "tbzzcsyl"   :"摊薄总资产收益率(%)",
//   "mll"        :"毛利率(%)",
//   "jll"        :"净利率(%)",
//   "sjsl"       :"实际税率(%)",
//   "yskyysr"    :"预收款/营业收入",
//   "xsxjlyysr"  :"销售现金流/营业收入",
//   "jyxjlyysr"  :"经营现金流/营业收入",
//   "zzczzy"     :"总资产周转率(次)",
//   "yszkzzts"   :"应收账款周转天数(天)",
//   "chzzts"     :"存货周转天数(天)",
//   "zcfzl"      :"资产负债率(%)",
//   "ldzczfz"    :"流动负债/总负债(%)",
//   "ldbl"       :"流动比率",
//   "sdbl"       :"速动比率"
// },{
//   ...
// }]
// -------------------------------------
func downloadIndicators(symbol string, filename string) error {
	url := fmt.Sprintf("http://emweb.securities.eastmoney.com/NewFinanceAnalysis/MainTargetAjax?ctype=4&type=0&code=%s", symbol)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("http.Get():", err)
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		fmt.Println("http.Get():", "404 page not find.")
		return errors.New("HTTP 404.")
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("ioutil.ReadAll()", err)
		return err
	}
	err = ioutil.WriteFile(filename, body, 0666)
	if err != nil {
		fmt.Println("ioutil.WriteFile()", err)
		return err
	}
	return nil
}

// downloadBonus() save a stock's bonus to a file.
func downloadBonus(symbol string, filename string) error {
	url := fmt.Sprintf("http://emweb.securities.eastmoney.com/PC_HSF10/BonusFinancing/BonusFinancingAjax?code=%s", symbol)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("http.Get():", err)
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		fmt.Println("http.Get():", "404 page not find.")
		return errors.New("HTTP 404.")
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("ioutil.ReadAll()", err)
		return err
	}
	err = ioutil.WriteFile(filename, body, 0666)
	if err != nil {
		fmt.Println("ioutil.WriteFile()", err)
		return err
	}
	return nil
}