Fetch the repository succeeded.
package valuta
import (
"encoding/json"
"fmt"
"github.com/PuerkitoBio/goquery"
"log"
"math/big"
"net/http"
"os"
"strconv"
"strings"
"sync"
"time"
)
var url = "https://chl.cn/?jinri"
var cMux sync.Mutex
var cacheDataAll = make(map[string]CurrencyRate)
//更新定时器
var upsetTicker *time.Ticker
type CurrencyRate struct {
Country string //目标地域
Rate float64 //汇率
}
func init() {
//设置每天更新三次 即每8小时更新一次
upsetTicker = time.NewTicker(time.Hour * 8)
go func() {
for {
select {
case <-upsetTicker.C:
upset()
}
}
}()
//启动时更新
upset()
}
func upset() {
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
req.Header.Set("Connection", "keep-alive") //设置请求头模拟浏览器登录
req.Header.Set("Cache-Control", "max-age=0")
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("Upgrade-Insecure-Requests", "1")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("Sec-Fetch-Mode", "navigate")
req.Header.Set("Sec-Fetch-User", "?1")
req.Header.Set("Sec-Fetch-Dest", "document")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
resp, err := client.Do(req)
if err != nil {
log.Fatalf("请求汇率站点发生错误:%s\n", err.Error())
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
log.Fatalf("站点返回信息 status:%d,error:%s\n", resp.StatusCode, err.Error())
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
log.Fatalf("读取站点信息发生错误:%s\n", err.Error())
}
cacheData := make(map[string]CurrencyRate)
//独立计算的币种
doc.Find(".hlb_lt > table > tbody > tr").Each(func(i int, s *goquery.Selection) {
if i == 0 {
return
}
Country := s.Find("td").First().Text()
// CurrencyCode 货币代码 使用时需要阶段处理 [2:]
CurrencyCode, _ := s.Find("td > a").Attr("href")
case1, _ := strconv.ParseFloat(s.Find("td").First().Next().Text(), 10)
case2, _ := strconv.ParseFloat(s.Find("td").First().Next().Next().Text(), 10)
var rate float64
if case1 > 0 {
rate = 100 / case1
} else {
rate = 100 / case2
}
if Country == "卢布" {
Country = "俄罗斯卢布"
}
cacheData[strings.ToLower(CurrencyCode[2:])] = CurrencyRate{Country: Country, Rate: rate}
})
doc.Find(".hblb3").Each(func(i int, s *goquery.Selection) {
t, _ := s.Html()
//fmt.Printf("%d\t%+v\n", i, t)
tl := strings.Split(t, "<br/>")
for k := range tl {
if strings.Index(tl[k], "</a>") > 0 {
temp := strings.Split(tl[k], "</a>")
if len(temp) < 2 {
continue
}
//fmt.Printf("%s\n", temp[0])
// CurrencyCode 货币代码 使用时不需要阶段处理
var CurrencyCode string
tempCodeArr := strings.Split(temp[0], "?")
if len(tempCodeArr) >= 2 {
tCode := strings.Split(tempCodeArr[1], "\"")
if len(tCode) >= 2 {
CurrencyCode = tCode[0]
}
}
index := strings.Index(temp[1], ")")
if index == -1 {
continue
}
d := strings.Trim(temp[1], " ")
Country := d[3:index]
rate, _ := strconv.ParseFloat(string(d[index+3:]), 10)
if CurrencyCode[len(CurrencyCode)-1:] == "0" {
CurrencyCode = CurrencyCode[:len(CurrencyCode)-1]
}
cacheData[strings.ToLower(CurrencyCode)] = CurrencyRate{Country: Country, Rate: rate}
}
}
})
cacheData["cny"] = CurrencyRate{"中国人民币", 1}
cMux.Lock()
defer cMux.Unlock()
cacheDataAll = cacheData
fmt.Println("共", len(cacheData), "种货币", "更新完成")
}
// ResetCache 主动刷新缓存
func ResetCache() {
upset()
//若城市地区被加载则更新缓存时,同步更新该数据
if len(cacheCountryCurrency) > 0 {
LoadCountryInfo("")
}
}
// GetCurrencyExchangeRate 获取指定国家 货币与人民币的汇率
// 参考兑换比例 1元人命币,兑换该国家的货币 汇率
// code 该国家货币编码
func GetCurrencyExchangeRate(code string) CurrencyRate {
code = strings.ToLower(code)
return cacheDataAll[code]
}
// ExchangeCurrency 人民币转其他币种
// cny 人民币数额
// code 目标币种 编码
// 返回
// cur 目标币种数量
// country 目标币种名称
func ExchangeCurrency(cny float64, code string) (cur float64, country string) {
c := GetCurrencyExchangeRate(code)
country = c.Country + "|" + code
cur = c.Rate * cny
return
}
// ExchangeCurrencyTo 其他币种转人命币
// code 币种名称
// cur 币种数量
// 返回
// cny 人民币数量
// county 固定为CN之类表示中国的符号
func ExchangeCurrencyTo(code string, cur float64) (cny float64, country string) {
c := GetCurrencyExchangeRate(code)
country = "人民币|CNY"
cny = cur / c.Rate
return
}
// ExchangeCurrencyStrTo 其他币种转人命币
// code 币种名称
// cur 币种数量
// 返回
// cny 人民币数量
// county 固定为CN之类表示中国的符号
func ExchangeCurrencyStrTo(code, cur string, prec int) (cnyMoney string, country string) {
c := GetCurrencyExchangeRate(code)
country = "人民币|CNY"
cnyRat := new(big.Rat).SetFloat64(c.Rate)
curRat, _ := new(big.Rat).SetString(cur)
quoRat := new(big.Rat).Quo(curRat, cnyRat)
cnyMoney = quoRat.FloatString(prec)
return
}
type CountryCurrency struct {
ZhCountry string `json:"zh_country"`
Code2 string `json:"code2"`
CurrencyCode string `json:"currency_code"`
ZhCurrencyName string `json:"zh_currency_name"`
Rate float64 `json:"rate"`
}
var mux sync.Mutex
var cacheCountryCurrency = make(map[string]CountryCurrency)
// LoadCountryInfo 加载国家信息
func LoadCountryInfo(path string) {
if path == "" {
path = "data/valuta/conuntryCurrency.json"
}
fc, err := os.Open(path)
if err != nil {
fmt.Printf("加载国家信息失败:%s\n", err.Error())
return
}
defer fc.Close()
tempCache := make(map[string]CountryCurrency)
var cbuf []CountryCurrency
temp := json.NewDecoder(fc)
err = temp.Decode(&cbuf)
if err != nil {
log.Fatalf("读取国家信息出错:%s\n", err.Error())
}
for k := range cbuf {
tmp := cbuf[k]
tmp.Rate = cacheDataAll[strings.ToLower(cbuf[k].CurrencyCode)].Rate
tempCache[strings.ToLower(cbuf[k].Code2)] = tmp
}
mux.Lock()
defer mux.Unlock()
cacheCountryCurrency = tempCache
}
// GetCountryExchangeRate 获取指定国家 货币与人民币的汇率
// 参考兑换比例 1元人命币,兑换该国家的货币 汇率
// code 该国家编码
func GetCountryExchangeRate(code string) CountryCurrency {
code = strings.ToLower(code)
return cacheCountryCurrency[code]
}
// ExchangeCountryValuta 人民办转目标地域货币
// cny 人民币数额
// code 目标地域编码 如MY 马来西亚
// 返回
// cur 目标币种数量 country 目标币种名称
func ExchangeCountryValuta(cny float64, code string) (cur float64, country string) {
c := GetCountryExchangeRate(code)
country = c.ZhCurrencyName + "|" + c.CurrencyCode
cur = c.Rate * cny
return
}
// ExchangeCountryValutaTo 目标地域货币转人民币
// cur 目标币种数量
// code 目标地域编码 如MY 马来西亚
// 返回
// cny 人民币数额 country 目标币种名称
func ExchangeCountryValutaTo(code string, cur float64) (cny float64, country string) {
c := GetCountryExchangeRate(code)
country = "人民币|CNY"
cny = cur / c.Rate
return
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。