123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- package services
- import (
- "context"
- "encoding/json"
- "eta/eta_crawler/models"
- "eta/eta_crawler/utils"
- "fmt"
- "reflect"
- "strconv"
- "strings"
- "time"
- "github.com/rdlucklib/rdluck_tools/http"
- )
- var noCrawlerName = map[string]struct{}{"Real Gross Domestic Product": {}, "Nominal U.S. Dollar Exchange Rate": {}}
- func SyncEiaSteoData(cont context.Context) (err error) {
- // err = syncEiaSteoData()
- eiaSteoUrls := map[string]string{
- "International Petroleum and Other Liquids Production、Consumption、Inventories": `https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=6&f=M&s=0&id=&linechart=PAPR_OECD~PAPR_NONOPEC&maptype=0&ctype=linechart&map=&method=getData`,
- "Non-OPEC Petroleum and Other Liquids Production": `https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=29&f=M&s=0&start=201901&end=202512&id=&ctype=linechart&maptype=0&method=getData`,
- "Total Liquid Fuels Production": `https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=7&f=M&s=0&start=201901&end=202512&maptype=0&ctype=linechart&id=&method=getData`,
- "Total Crude Oil Production": `https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=30&f=M&s=0&start=201901&end=202512&id=&ctype=linechart&maptype=0&method=getData`,
- "World Petroleum and Other Liquid Fuels Consumption": `https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=31&f=M&s=0&start=201901&end=202512&maptype=0&ctype=linechart&id=&method=getData`,
- "U.S. Petroleum and Other Liquids Supply、Consumption、Inventories": `https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=9&f=M&s=0&start=201901&end=202512&maptype=0&ctype=linechart&method=getData`,
- "Drilling Productivity Metrics": `https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=32&f=M&s=0&start=201901&end=202512&ctype=linechart&maptype=0&method=getData`,
- "Crude Oil and Natural Gas Production from Shale and Tight Formations": `https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=33&f=M&s=0&start=201901&end=202512&maptype=0&ctype=linechart&method=getData`,
- }
- var eiaIndexName = []string{
- "International Petroleum and Other Liquids Production、Consumption、Inventories",
- "Non-OPEC Petroleum and Other Liquids Production",
- "Total Liquid Fuels Production",
- "Total Crude Oil Production",
- "World Petroleum and Other Liquid Fuels Consumption",
- "U.S. Petroleum and Other Liquids Supply、Consumption、Inventories",
- "Drilling Productivity Metrics",
- "Crude Oil and Natural Gas Production from Shale and Tight Formations",
- }
- for _, name := range eiaIndexName {
- url := eiaSteoUrls[name]
- err = syncEiaSteoDataV2(name, url)
- if err != nil {
- fmt.Println("同步失败", err)
- return
- }
- }
- return
- }
- func syncEiaSteoData(eiaSteoUrl string) (err error) {
- // 获取数据
- //官网地址:https://www.eia.gov/outlooks/steo/data/browser/#/?v=6&f=M&s=0&start=201701&end=202312&linechart=~T3_STCHANGE_WORLD&maptype=0&ctype=linechart&map=
- // 这是获取数据的链接(月度的)
- // eiaSteoUrl := "https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=6&f=M&s=0&id=&linechart=PAPR_OECD~PAPR_NONOPEC&maptype=0&ctype=linechart&map=&method=getData"
- eiaSteoData, err := queryData(eiaSteoUrl)
- if err != nil {
- fmt.Println("读取失败", err)
- return
- }
- // 获取分类列表
- classifyList, err := models.GetBaseFromEiaSteoClassifyAll()
- if err != nil {
- fmt.Println("获取分类失败:", err)
- return
- }
- classifyMap := make(map[string]*models.BaseFromEiaSteoClassify)
- for _, v := range classifyList {
- classifyMap[v.ClassifyNameOriginal] = v
- }
- // 获取指标列表
- indexList, err := models.GetBaseFromEiaSteoIndexAll()
- if err != nil {
- fmt.Println("获取分类失败:", err)
- return
- }
- indexMap := make(map[string]*models.BaseFromEiaSteoIndex)
- for _, v := range indexList {
- indexMap[v.IndexCode] = v
- }
- var nowClassify *models.BaseFromEiaSteoClassify
- for _, v := range eiaSteoData.VIEWSDATA.ROWS {
- // 如果没有数据,那么就返回
- if v.HASDATA != 1 {
- continue
- }
- if v.LEVEL == 1 {
- tmpNowClassify, ok := classifyMap[v.CHARTNAME]
- if !ok {
- nowClassify = &models.BaseFromEiaSteoClassify{
- BaseFromEiaSteoClassifyId: 0,
- ClassifyName: v.CHARTNAME,
- ClassifyNameOriginal: v.CHARTNAME,
- ModifyTime: time.Now(),
- CreateTime: time.Now(),
- }
- // 新增指标
- err = nowClassify.AddBaseFromEiaSteoClassify()
- if err != nil {
- return
- }
- classifyMap[v.CHARTNAME] = nowClassify
- } else {
- nowClassify = tmpNowClassify
- }
- //continue
- }
- // 如果系列名称为空的话,那么也返回
- if v.SERIESID == `` {
- continue
- }
- if v.LEVEL > 1 && v.SERIESID == `` {
- continue
- }
- var eiaSteoIndex *models.BaseFromEiaSteoIndex
- eiaSteoIndex, ok := indexMap[v.SERIESID]
- if !ok {
- eiaSteoIndex = &models.BaseFromEiaSteoIndex{
- //BaseFromEiaSteoIndexId: 0,
- BaseFromEiaSteoClassifyId: nowClassify.BaseFromEiaSteoClassifyId,
- IndexCode: v.SERIESID,
- IndexName: v.CHARTNAME, // 不做中文名称的转换
- IndexNameOriginal: v.CHARTNAME,
- Frequency: "月度",
- Level: v.LEVEL,
- Unit: v.UNITS,
- Super: v.SUPER,
- Precision: v.PRECISION,
- LastHistorical: strconv.Itoa(v.LASTHISTORICAL),
- Description: v.DESCRIPTION,
- IsMappable: v.ISMAPPABLE,
- StartDate: time.Now(),
- EndDate: time.Now(),
- ModifyTime: time.Now(),
- CreateTime: time.Now(),
- }
- // 新增指标
- err = eiaSteoIndex.Add()
- if err != nil {
- return
- }
- indexMap[v.SERIESID] = eiaSteoIndex
- } else {
- updateCol := make([]string, 0)
- if eiaSteoIndex.BaseFromEiaSteoClassifyId != nowClassify.BaseFromEiaSteoClassifyId {
- eiaSteoIndex.BaseFromEiaSteoClassifyId = nowClassify.BaseFromEiaSteoClassifyId
- updateCol = append(updateCol, "BaseFromEiaSteoClassifyId")
- }
- if eiaSteoIndex.IndexName != v.CHARTNAME {
- eiaSteoIndex.IndexName = v.CHARTNAME
- updateCol = append(updateCol, "IndexName")
- }
- if eiaSteoIndex.IndexNameOriginal != v.CHARTNAME {
- eiaSteoIndex.IndexNameOriginal = v.CHARTNAME
- updateCol = append(updateCol, "IndexNameOriginal")
- }
- // Frequency: "月度",
- // Level: v.LEVEL,
- // Unit: v.UNITS,
- // Super: v.SUPER,
- // Precision: v.PRECISION,
- // LastHistorical: strconv.Itoa(v.LASTHISTORICAL),
- // Description: v.DESCRIPTION,
- // IsMappable: v.ISMAPPABLE,
- if len(updateCol) > 0 {
- eiaSteoIndex.Update(updateCol)
- }
- }
- //校验数据类型对不对
- valType := reflect.TypeOf(v.DATA)
- //if valType.String() == "map[string]interface{}"{
- // fmt.Println("匹配上了")
- //}
- switch valType.String() {
- case "[]interface {}": // 没有数据
- case "map[string]interface {}": // 有数据
- data := v.DATA.(map[string]interface{})
- err = models.HandleEiaSteoData(data, eiaSteoIndex)
- if err != nil {
- return
- }
- //if eiaSteoIndex.IndexCode == "PATC_OECD_EUROPE" {
- // os.Exit(0)
- //}
- }
- fmt.Println(v.CHARTNAME, v.SERIESID, "==", v.PRECISION, "===========")
- }
- return
- }
- func syncEiaSteoDataV2(eiaSteoName, eiaSteoUrl string) (err error) {
- defer func() {
- if r := recover(); r != nil {
- fmt.Println("异常:", r)
- fmt.Println("异常的eiaSteo名字", eiaSteoName)
- }
- }()
- // 获取数据
- //官网地址:https://www.eia.gov/outlooks/steo/data/browser/#/?v=6&f=M&s=0&start=201701&end=202312&linechart=~T3_STCHANGE_WORLD&maptype=0&ctype=linechart&map=
- // 这是获取数据的链接(月度的)
- // eiaSteoUrl := "https://www.eia.gov/outlooks/steo/data/browser/data/index.php?v=6&f=M&s=0&id=&linechart=PAPR_OECD~PAPR_NONOPEC&maptype=0&ctype=linechart&map=&method=getData"
- eiaSteoData, err := queryData(eiaSteoUrl)
- if err != nil {
- fmt.Println("读取失败", err)
- return
- }
- parentClassify, err := models.GetBaseFromEiaSteoClassifyByName(eiaSteoName)
- if err != nil && err.Error() != utils.ErrNoRow() {
- fmt.Println("添加eiaSteo指标异常, err: ", err.Error())
- return
- }
- if parentClassify == nil {
- tmpClassify := &models.BaseFromEiaSteoClassify{
- ClassifyName: eiaSteoName,
- ClassifyNameOriginal: eiaSteoName,
- Level: 1,
- ModifyTime: time.Now(),
- CreateTime: time.Now(),
- }
- // 新增指标分类
- err = tmpClassify.AddBaseFromEiaSteoClassify()
- if err != nil {
- return
- }
- parentClassify = tmpClassify
- }
- // 获取分类列表
- classifyList, err := models.GetChildBaseFromEiaSteoClassifyById(parentClassify.BaseFromEiaSteoClassifyId)
- if err != nil {
- fmt.Println("获取分类失败:", err)
- return
- }
- classifyMap := make(map[string]*models.BaseFromEiaSteoClassify)
- for _, v := range classifyList {
- classifyMap[v.ClassifyNameOriginal] = v
- }
- // 获取指标列表
- indexList, err := models.GetBaseFromEiaSteoIndexAll()
- if err != nil {
- fmt.Println("获取分类失败:", err)
- return
- }
- indexMap := make(map[string]*models.BaseFromEiaSteoIndex)
- for _, v := range indexList {
- indexMap[v.IndexCode] = v
- }
- var hasClassify *models.BaseFromEiaSteoClassify
- var noDataClassify *models.BaseFromEiaSteoClassify
- for i, v := range eiaSteoData.VIEWSDATA.ROWS {
- // 如果没有数据,那么就返回
- if v.HASDATA != 1 && strings.TrimSpace(v.CHARTNAME) == "" {
- curRow := eiaSteoData.VIEWSDATA.ROWS
- length := len(eiaSteoData.VIEWSDATA.ROWS)
- if length > i+1 {
- if noDataClassify != nil {
- if curRow[i+1].LEVEL == 1 && strings.TrimSpace(curRow[i+1].CHARTNAME) != "" && curRow[i+1].HASDATA != 1 {
- noDataClassify = nil
- }
- }
- if hasClassify != nil {
- if curRow[i+1].LEVEL == 1 && strings.TrimSpace(curRow[i+1].CHARTNAME) != "" && curRow[i+1].HASDATA == 1 {
- hasClassify = nil
- }
- }
- }
- continue
- }
- if noDataClassify == nil && hasClassify == nil && strings.TrimSpace(v.CHARTNAME) != "" && v.LEVEL == 1 {
- classify, ok := classifyMap[v.CHARTNAME]
- if !ok {
- tmpClassify := &models.BaseFromEiaSteoClassify{
- BaseFromEiaSteoClassifyId: 0,
- ClassifyName: v.CHARTNAME,
- ClassifyNameOriginal: v.CHARTNAME,
- ParentId: parentClassify.BaseFromEiaSteoClassifyId,
- Level: 2,
- ModifyTime: time.Now(),
- CreateTime: time.Now(),
- }
- classifyMap[v.CHARTNAME] = tmpClassify
- if v.HASDATA == 1 {
- hasClassify = tmpClassify
- } else {
- noDataClassify = tmpClassify
- }
- if _, ok := noCrawlerName[tmpClassify.ClassifyName]; ok {
- continue
- }
- // 新增指标分类
- err = tmpClassify.AddBaseFromEiaSteoClassify()
- if err != nil {
- return
- }
- } else {
- if v.HASDATA == 1 {
- hasClassify = classify
- } else {
- noDataClassify = classify
- }
- }
- }
- // 如果系列名称为空的话,那么也返回
- if v.SERIESID == `` {
- continue
- }
- if v.HASDATA != 1 {
- continue
- }
- var curClassify *models.BaseFromEiaSteoClassify
- if noDataClassify != nil {
- curClassify = noDataClassify
- } else {
- curClassify = hasClassify
- }
- if _, ok := noCrawlerName[curClassify.ClassifyName]; ok {
- continue
- }
- eiaSteoIndex, ok := indexMap[v.SERIESID]
- if !ok {
- eiaSteoIndex = &models.BaseFromEiaSteoIndex{
- //BaseFromEiaSteoIndexId: 0,
- BaseFromEiaSteoClassifyId: curClassify.BaseFromEiaSteoClassifyId,
- IndexCode: v.SERIESID,
- IndexName: v.CHARTNAME, // 不做中文名称的转换
- IndexNameOriginal: v.CHARTNAME,
- Frequency: "月度",
- Level: v.LEVEL,
- Unit: v.UNITS,
- Super: v.SUPER,
- Precision: v.PRECISION,
- LastHistorical: strconv.Itoa(v.LASTHISTORICAL),
- Description: v.DESCRIPTION,
- IsMappable: v.ISMAPPABLE,
- StartDate: time.Now(),
- EndDate: time.Now(),
- ModifyTime: time.Now(),
- CreateTime: time.Now(),
- }
- // 新增指标
- err = eiaSteoIndex.Add()
- if err != nil {
- return
- }
- indexMap[v.SERIESID] = eiaSteoIndex
- } else {
- updateCol := make([]string, 0)
- if eiaSteoIndex.BaseFromEiaSteoClassifyId != curClassify.BaseFromEiaSteoClassifyId {
- eiaSteoIndex.BaseFromEiaSteoClassifyId = curClassify.BaseFromEiaSteoClassifyId
- updateCol = append(updateCol, "BaseFromEiaSteoClassifyId")
- }
- if eiaSteoIndex.IndexName != v.CHARTNAME {
- eiaSteoIndex.IndexName = v.CHARTNAME
- updateCol = append(updateCol, "IndexName")
- }
- if eiaSteoIndex.IndexNameOriginal != v.CHARTNAME {
- eiaSteoIndex.IndexNameOriginal = v.CHARTNAME
- updateCol = append(updateCol, "IndexNameOriginal")
- }
- if len(updateCol) > 0 {
- eiaSteoIndex.Update(updateCol)
- }
- }
- //校验数据类型对不对
- valType := reflect.TypeOf(v.DATA)
- switch valType.String() {
- case "[]interface {}": // 没有数据
- case "map[string]interface {}": // 有数据
- data := v.DATA.(map[string]interface{})
- err = models.HandleEiaSteoData(data, eiaSteoIndex)
- if err != nil {
- return
- }
- }
- fmt.Println(v.CHARTNAME, v.SERIESID, "==", v.PRECISION, "===========")
- }
- return
- }
- // queryData 接口请求网站数据
- func queryData(eiaSteoUrl string) (eiaSteoData EiaSteoData, err error) {
- body, err := http.Get(eiaSteoUrl)
- if err != nil {
- fmt.Println("err:", err)
- }
- //utils.FileLog.Info("eia steo 报告数据:" + string(body))
- err = json.Unmarshal(body, &eiaSteoData)
- return
- }
- type EiaSteoData struct {
- SERIESDATA struct {
- DATACOLUMNS []interface{} `json:"DATACOLUMNS"`
- ROWS []interface{} `json:"ROWS"`
- } `json:"SERIESDATA"`
- VIEWSDATA struct {
- DATACOLUMNS []int `json:"DATACOLUMNS"`
- ROWS []struct {
- CHARTNAME string `json:"CHART_NAME"`
- DESCRIPTION string `json:"DESCRIPTION"`
- HASDATA int `json:"HAS_DATA"`
- PRECISION int `json:"PRECISION"`
- SERIESID string `json:"SERIES_ID"`
- UNITS string `json:"UNITS"`
- SUPER string `json:"SUPER"`
- LEVEL int `json:"LEVEL"`
- //DATA map[int]float64 `json:"DATA"`
- DATA interface{} `json:"DATA"`
- LASTHISTORICAL int `json:"LAST_HISTORICAL,omitempty"`
- ISMAPPABLE int `json:"IS_MAPPABLE,omitempty"`
- } `json:"ROWS"`
- } `json:"VIEWSDATA"`
- }
- // EiaSteoNameMap 中英文互换
- var EiaSteoNameMap = map[string]string{
- "PAPR_OECD": "OECD石油产量",
- "PAPR_US": "美国五十州石油产量",
- "PAPR_CA": "加拿大石油产量",
- "PAPR_MX": "墨西哥石油产量",
- "PAPR_OTHEROECD": "其他OECD石油产量",
- "PAPR_NONOECD": "非OECD石油产量",
- "PAPR_OPEC": "OPEC13国石油产量",
- "COPR_OPEC": "OPEC13国原油产量",
- "OPEC_NC": "OPEC其他石油液体产量",
- "PAPR_FSU": "欧亚石油产量",
- "PAPR_CH": "中国石油产量",
- "PAPR_OTHER_NONOECD": "其他非OECD石油产量",
- "PAPR_WORLD": "全球石油产量",
- "PAPR_NONOPEC": "非OPEC石油产量",
- "PATC_OECD": "OECD石油需求",
- "PATC_US": "美国五十州石油需求",
- "PATC_UST": "美国领地石油需求",
- "PATC_CA": "加拿大石油需求",
- "PATC_OECD_EUROPE": "欧洲石油需求",
- "PATC_JA": "日本石油需求",
- "PATC_OTHER_OECD": "其他OECD石油需求",
- "PATC_NON_OECD": "非OECD石油需求",
- "PATC_FSU": "欧亚石油需求",
- "PATC_NONOECD_EUROPE": "非OECD欧洲石油需求",
- "PATC_CH": "中国石油需求",
- "PATC_OTHER_ASIA": "其他亚洲石油需求",
- "PATC_OTHER_NONOECD": "其他非OECD石油需求",
- "PATC_WORLD": "全球石油需求",
- "T3_STCHANGE_US": "美国50州石油库存去化(需求-供给)",
- "T3_STCHANGE_OOECD": "其他OECD石油库存去化(需求-供给)",
- "T3_STCHANGE_NOECD": "非OECD石油库存去化(需求-供给)",
- "T3_STCHANGE_WORLD": "全球石油库存去化(需求-供给)",
- "PASC_US": "美国商业库存",
- "PASC_OECD_T3": "OECD商业库存",
- }
|