national_data.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. package national_data
  2. import (
  3. "crypto/tls"
  4. "encoding/json"
  5. "fmt"
  6. "hongze/hongze_data_crawler/models"
  7. "io/ioutil"
  8. "net/http"
  9. "net/url"
  10. "strings"
  11. "time"
  12. )
  13. const (
  14. NationalStatisticsBaseReqUrl = "https://data.stats.gov.cn/easyquery.htm"
  15. )
  16. func NationalHttpPost(reqUrl, payload string) (result []byte, err error) {
  17. tr := &http.Transport{
  18. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  19. }
  20. client := &http.Client{
  21. Transport: tr,
  22. }
  23. req, err := http.NewRequest("POST", reqUrl, strings.NewReader(payload))
  24. if err != nil {
  25. return
  26. }
  27. req.Header.Add("Accept", "text/plain, */*; q=0.01")
  28. req.Header.Add("Accept-Encoding", "tgzip, deflate, br")
  29. req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9")
  30. req.Header.Add("Connection", "keep-alive")
  31. req.Header.Add("Content-Length", "37")
  32. req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
  33. req.Header.Add("Cookie", "wzws_sessionid=gDExNS4xOTQuMTAyLjEyN6BkERzUgmZjNWVlMYFiOWNiZDg=; JSESSIONID=UOri2Cu3f3c-Y3rPgXWJ04E8pfbeyAUGG-s7zJ7Tt0JhlEiLi0EU!412929168; u=5")
  34. req.Header.Add("Host", "data.stats.gov.cn")
  35. req.Header.Add("Origin", "https://data.stats.gov.cn")
  36. req.Header.Set("Referer", "https://data.stats.gov.cn/easyquery.htm?cn=A01")
  37. req.Header.Set("sec-ch-ua", "\"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"")
  38. req.Header.Set("sec-ch-ua-mobile", "?0")
  39. req.Header.Set("sec-ch-ua-platform", "\"Windows\"")
  40. req.Header.Set("Sec-Fetch-Dest", "empty")
  41. req.Header.Set("Sec-Fetch-Mode", "cors")
  42. req.Header.Set("Sec-Fetch-Site", "same-origin")
  43. req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36")
  44. req.Header.Set("X-Requested-With", "XMLHttpRequest")
  45. res, err := client.Do(req)
  46. if err != nil {
  47. return
  48. }
  49. defer res.Body.Close()
  50. body, err := ioutil.ReadAll(res.Body)
  51. if err != nil {
  52. return
  53. }
  54. result = body
  55. return
  56. }
  57. func NationalGet(reqUrl, payload string) (err error) {
  58. tr := &http.Transport{
  59. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  60. }
  61. client := &http.Client{
  62. Transport: tr,
  63. }
  64. req, err := http.NewRequest("GET", reqUrl, strings.NewReader(payload))
  65. if err != nil {
  66. return
  67. }
  68. res, err := client.Do(req)
  69. if err != nil {
  70. return
  71. }
  72. defer res.Body.Close()
  73. _, err = ioutil.ReadAll(res.Body)
  74. if err != nil {
  75. return
  76. }
  77. Cookie := res.Header.Get("Cookie")
  78. fmt.Println(Cookie)
  79. rcookie := req.Header.Get("Cookie")
  80. fmt.Println("rcookie")
  81. fmt.Println(rcookie)
  82. //fmt.Println("body:" + string(body))
  83. cookiesArr := res.Cookies()
  84. fmt.Println("cookiesArrLen:", len(cookiesArr))
  85. for k, v := range cookiesArr {
  86. fmt.Println(k, v)
  87. }
  88. return
  89. }
  90. // QuotaClassifyTreeResp 指标分类树响应
  91. type QuotaClassifyTreeResp struct {
  92. Id string `description:"分类ID(字符串)"`
  93. IsParent bool `description:"是否为父级"`
  94. Name string `description:"分类名称"`
  95. Pid string `description:"父级分类ID"`
  96. Dbcode string `description:"源-dbocde"`
  97. Wdcode string `description:"源-wdcode"`
  98. }
  99. // SyncQuotaClassifyTree 同步指标分类树
  100. // dbcode: hgyd-月度; hgjd-季度; ...
  101. func SyncQuotaClassifyTree() (err error) {
  102. defer func() {
  103. if err != nil {
  104. fmt.Println(err.Error())
  105. }
  106. }()
  107. items := make([]*models.BaseFromNationalStatisticsClassify, 0)
  108. initId := "zb"
  109. initDbcode := "hgyd"
  110. initWdcode := "zb"
  111. resp, e := curlAndFormatQuotaClassify(initId, initDbcode, initWdcode, items)
  112. if e != nil {
  113. err = fmt.Errorf("递归指标分类失败, Err: %s", e.Error())
  114. return
  115. }
  116. items = resp
  117. // 去重
  118. classifyMap := make(map[string]bool)
  119. classifyOB := new(models.BaseFromNationalStatisticsClassify)
  120. classifyPars := make([]interface{}, 0)
  121. classifies, e := classifyOB.GetItemsByCondition("", classifyPars, []string{}, "")
  122. if e != nil {
  123. err = fmt.Errorf("获取指标分类列表失败, Err: %s", e.Error())
  124. return
  125. }
  126. for _, c := range classifies {
  127. classifyMap[c.Id] = true
  128. }
  129. finalList := make([]*models.BaseFromNationalStatisticsClassify, 0)
  130. for _, v := range items {
  131. if classifyMap[v.Id] {
  132. continue
  133. }
  134. finalList = append(finalList, v)
  135. }
  136. if e = classifyOB.CreateMulti(items); e != nil {
  137. err = fmt.Errorf("批量新增指标分类失败, Err: %s", e.Error())
  138. return
  139. }
  140. return
  141. }
  142. // curlAndFormatQuotaClassify 递归请求分类树
  143. func curlAndFormatQuotaClassify(id, dbcode, wdcode string, items []*models.BaseFromNationalStatisticsClassify) (resp []*models.BaseFromNationalStatisticsClassify, err error) {
  144. f := url.Values{}
  145. f.Add("id", id)
  146. f.Add("dbcode", dbcode)
  147. f.Add("wdcode", wdcode)
  148. f.Add("m", "getTree")
  149. r, e := NationalHttpPost(NationalStatisticsBaseReqUrl, f.Encode())
  150. if e != nil {
  151. err = fmt.Errorf("请求指标分类树失败, Err: %s", e.Error())
  152. return
  153. }
  154. list := make([]*QuotaClassifyTreeResp, 0)
  155. if e = json.Unmarshal(r, &list); e != nil {
  156. err = fmt.Errorf("解析响应数据失败, Err: %s", e.Error())
  157. return
  158. }
  159. nowTime := time.Now().Local()
  160. for _, v := range list {
  161. isParent := 0
  162. if v.IsParent {
  163. isParent = 1
  164. }
  165. items = append(items, &models.BaseFromNationalStatisticsClassify{
  166. ClassifyName: v.Name,
  167. Id: v.Id,
  168. Dbcode: v.Dbcode,
  169. Wdcode: v.Wdcode,
  170. Pid: v.Pid,
  171. IsParent: isParent,
  172. CreateTime: nowTime,
  173. ModifyTime: nowTime,
  174. })
  175. // 向下递归
  176. if isParent == 1 {
  177. time.Sleep(1 * time.Second) // 缓缓...毕竟接口是人家的...
  178. items, e = curlAndFormatQuotaClassify(v.Id, v.Dbcode, v.Wdcode, items)
  179. if e != nil {
  180. err = fmt.Errorf("递归请求分类树失败, Err: %s", e.Error())
  181. return
  182. }
  183. }
  184. }
  185. return items, nil
  186. }
  187. type QuotaListDataResp struct {
  188. ReturnCode int `description:"状态码" json:"returncode"`
  189. ReturnData struct {
  190. DataNodes []QuotaDataNode `json:"datanodes"`
  191. WdNodes struct{} `json:"wdnodes"`
  192. }
  193. }
  194. type QuotaDataNode struct {
  195. Code string `description:"编码"`
  196. Data struct {
  197. Data float64 `description:"指标值"`
  198. HasData bool `description:"是否有值" json:"hasdata"`
  199. StrData string `description:"指标值(字符串)" json:"strdata"`
  200. }
  201. Wds []QuotaDataWds
  202. }
  203. type QuotaDataWds struct {
  204. ValueCode string `json:"valuecode"`
  205. WdCode string `json:"wdcode"`
  206. }
  207. // SyncQuotaDataFromDbCodeAndId 同步指标值
  208. func SyncQuotaDataFromDbCodeAndId() (err error) {
  209. // 查询无父级的指标分类
  210. //classifyOB := new(models.BaseFromNationalStatisticsClassify)
  211. //classifyCond := ` AND is_parent = 0`
  212. //classifyPars := make([]interface{}, 0)
  213. //classifyOrder := ` ORDER BY base_from_national_statistics_classify_id ASC`
  214. //classifies, e := classifyOB.GetItemsByCondition(classifyCond, classifyPars, []string{}, classifyOrder)
  215. //if e != nil {
  216. // err = fmt.Errorf("获取指标分类列表失败, Err: %s", e.Error())
  217. // return
  218. //}
  219. // m: QueryData
  220. // dbcode: hgyd
  221. // rowcode: zb
  222. // colcode: sj
  223. // wds: []
  224. // dfwds: [{"wdcode":"zb","valuecode":"A010101"}]
  225. // k1: 1678872233342
  226. // h: 1
  227. time.Sleep(2 * time.Second)
  228. // 构建查询
  229. f := url.Values{}
  230. f.Add("m", "QueryData")
  231. f.Add("dbcode", "hgyd")
  232. f.Add("rowcode", "zb")
  233. f.Add("colcode", "sj")
  234. f.Add("wds", "[]")
  235. f.Add("dfwds", `[{"wdcode":"zb","valuecode":"A010101"}]`)
  236. f.Add("k1", fmt.Sprint(time.Now().UnixNano()/1e6))
  237. f.Add("h", "1")
  238. r, e := NationalHttpPost(NationalStatisticsBaseReqUrl, f.Encode())
  239. fmt.Println("err: ", e)
  240. if e != nil {
  241. fmt.Println("获取失败, Err: ", e.Error())
  242. //err = fmt.Errorf("请求指标分类树失败, Err: %s", e.Error())
  243. return
  244. }
  245. fmt.Println("res: ", string(r))
  246. return
  247. }