我正在try 使用Golang net/http从API获取数据.当我从VS代码甚至postman 中使用雷霆客户端时,我得到了正确的数据,但当我试图从Golang代码中获取数据时,我得到了一个空响应.

数据获取分两步进行:

  1. 使用初始GET请求获取Cookie(此部分在两者中都工作得很好)
  2. 使用Cookie发出另一个获取所需数据的GET请求.(这是在Golang中给出空白响应的步骤,并在下面给出的postman 链接中命名为历史数据)

Run in Postman

这是Golang的代码.代码可能有点长,但这只是因为添加了多行标题.

var BaseURL string = "https://www.nseindia.com"

func ReqConfig() *http.Request {
    req, _ := http.NewRequest("GET", BaseURL, nil)
    req.Header.Add("Accept", "*/*")
    req.Header.Add("Accept-Encoding", "gzip, deflate, br")
    req.Header.Add("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8")
    req.Header.Add("Connection", "keep-alive")
    req.Header.Add("Host", "www.nseindia.com")
    req.Header.Add("Referer", "https://www.nseindia.com/get-quotes/equity")
    req.Header.Add("X-Requested-With", "XMLHttpRequest")
    req.Header.Add("sec-fetch-dest", "empty")
    req.Header.Add("sec-fetch-mode", "cors")
    req.Header.Add("pragma", "no-cache")
    req.Header.Add("sec-fetch-site", "same-origin")
    req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36")
    fmt.Println(1, req.Header.Get("Cookie"))

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer res.Body.Close()
    for _, cookie := range res.Cookies() {
        req.AddCookie(cookie)
    }

    // TODO: Remove the need to call this API twice. This is just a temporary fix.
    res, err = http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer res.Body.Close()
    for _, cookie := range res.Cookies() {
        req.AddCookie(cookie)
    }


    cookies := req.Cookies()
    for i := 0; i < len(cookies); i++ {
        for j := i + 1; j < len(cookies); j++ {
            if cookies[i].Name == cookies[j].Name {
                cookies = append(cookies[:j], cookies[j+1:]...)
                j--
            }
        }
    }
    req.Header.Del("Cookie")
    for _, cookie := range cookies {
        req.AddCookie(cookie)
    }
    fmt.Println("Fetched cookies")

    return req
}


func HistoricalEQ(symbol string, from string, to string, series string) {
    req := ReqConfig()

    query := req.URL.Query()
    query.Add("symbol", symbol)
    query.Add("from", from)
    query.Add("to", to)
    query.Add("series", "[\""+series+"\"]")
    req.URL.RawQuery = query.Encode()
    req.URL.Path = "/api/historical/cm/equity"

    client := &http.Client{Timeout: 40 * time.Second}
    res, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer res.Body.Close()

    var data map[string]interface{}
    json.NewDecoder(res.Body).Decode(&data)

        // Prints `map[]` and not the whole json data which is provided in Postman req
    fmt.Println(data)
}


func main() {
    symbol := "PAYTM"
    series := "EQ"
    from_date := time.Date(2023, 1, 1, 0, 0, 0, 0, time.Local).Format("02-01-2006")
    to_date := time.Date(2023, 1, 24, 0, 0, 0, 0, time.Local).Format("02-01-2006")
    HistoricalEQ(symbol, from_date, to_date, series)
}

如果您能够从Golang only中的其他方式从 GET https://www.nseindia.com/api/historical/cm/equity?symbol=PAYTM&series=[%22EQ%22]&from=28-12-2022&to=28-01-2023中获取数据,那么也可以解决我的问题.你可以拨打https://www.nseindia.com/get-quotes/equity?symbol=PAYTM查看网站前台.我请求GET请求可以通过转到历史数据选项卡并单击筛选器按钮来触发

与PYTHON类似的代码:https://github.com/jugaad-py/jugaad-data/blob/47bbf1aa39ebec3a260579c76ff427ea06e42acd/jugaad_data/nse/history.py#L61

推荐答案

%1缺少️⃣解码错误处理

err := json.NewDecoder(res.Body).Decode(&data)
if err != nil {
    log.Fatalf("decode request: %v", err)
}
invalid character '\x1f' looking for beginning of value

2️⃣看起来响应数据已被压缩(gzip数据以魔术序列0x1f 0x8b开始).如果你判断回应是Headers,你会看到

...
Content-Encoding:[gzip] ????????????????????????
Content-Length:[1890] 
Content-Type:[application/json; charset=utf-8] 
...

它看起来像是事实

3️⃣try 手动处理压缩(compress/gzip)

    client := &http.Client{Timeout: 40 * time.Second}
    res, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(res.Header)

    var reader io.ReadCloser
    switch res.Header.Get("Content-Encoding") {
    case "gzip":
        reader, err = gzip.NewReader(res.Body)
    default:
        reader = res.Body
    }
    defer reader.Close()

    var data map[string]interface{}
    err = json.NewDecoder(reader).Decode(&data)
    if err != nil {
        log.Fatalf("decode request: %v", err)
    }

    fmt.Println(data) ???????? // map[data:[map[CH_52WEEK_HIGH_PRICE:994 CH_52WEEK_LOW_PRICE:438.35 CH_CLOSING_PRICE:543.55 CH_ISIN:INE982J01020 CH_LAST_TRADED_PRICE:542.2 CH_MARKET_TYPE:N ...

Go相关问答推荐

Go -SDP服务器读缓冲区不会更改任何内容

在保留额外参数的同时解封YAML

../golang/pkg/mod/github.com/wmentor/lemmas@v0.0.6/processor.go:72:9:未定义:令牌.进程

Go Regexp:匹配完整的单词或子字符串,或者根本不匹配

如何使用gopher-lua定义一个Lua函数,该函数有一个预定义的表作为param,Lua脚本可以在其中访问该函数中的表?

exec的可执行决议.命令+路径

为什么要立即调用内联函数,而不仅仅是调用其包含的函数?

Golang Fiber Render - 将数据发送到多个布局

Go time.Parse 无效的 ISO 日期

Get 请求在 Thunder 客户端/Postman 中返回数据,但在 Golang 代码中给出空白数据

动态 SQL 集 Golang

emersion/go-imap - imap.FetchRFC822:无效内存地址或零指针取消引用

访问传递给可变参数函数的通用 struct 的特定字段

如何根据 Go 中第二次出现的分隔符拆分字符串?

使用go doc命令查看示例函数?

Golang 数据库/sql 与 SetMaxOpenConns 挂起

将 CSVExport 函数传递给处理程序 Gin

如何在 Gorm 中获得特定日期的最大值?

Scanner.Buffer - 最大值对自定义拆分没有影响?

同一个 Go struct成员上的多个标签