You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang爬取Haremaltin站点ATA_ESKI金价字段问题及解决方案

问题描述

编写Go代码爬取黄金报价站点HTML表格中指定单元格的数值,目标站点地址为https://www.haremaltin.com/altin-fiyatlari,在浏览器开发者工具元素检查面板搜索satis__ATA_ESKI即可定位到目标值(旧阿塔金币售价)。作为Go初学者尝试多种写法均无法成功获取该值,已知信息如下:

  • 站点未提供公开API
  • 最初尝试静态爬取时需要添加等待逻辑等待页面加载完成,若返回结果为-则代表页面尚未加载完成

初始尝试代码

package main

import (
"fmt"
"log"
"net/http"

"github.com/PuerkitoBio/goquery"
)

func main() {
   url := "https://www.haremaltin.com/altin-fiyatlari"

   resp, err := http.Get(url)
   if err != nil {
       log.Fatal(err)
   }
   defer resp.Body.Close()
   if resp.StatusCode != 200 {
       log.Fatalf("failed to fetch data: %d %s", resp.StatusCode, resp.Status)
   }

   doc, err := goquery.NewDocumentFromReader(resp.Body)
   if err != nil {
      log.Fatal(err)
   }

   doc.Find("tr__ATA_ESKI tr").Each(func(j int, tr *goquery.Selection) {
      data := []string{}
      tr.Find("td").Each(func(ix int, td *goquery.Selection) {
           e := td.Text()
           data = append(data, e)
           fmt.Println(data)
      })
   })
}
解决方案

静态爬取失败的核心原因:页面价格数据并非内嵌在初始返回的静态HTML中,而是页面加载完成后通过AJAX异步拉取再渲染到DOM节点上,直接请求静态页无法拿到渲染后的数值,也不需要模拟浏览器等待加载,直接请求站点内部使用的异步数据接口即可拿到结构化JSON数据,解析效率更高。
页面源码参考截图

核心提取逻辑为遍历接口返回的Map结构,匹配ATA_ESKI键下的satis(售价)字段即可,核心代码片段如下:

for _, v := range data { // 遍历Map提取值
    m, ok := v.(map[string]interface{}) // 类型断言以支持遍历
    if !ok {
        fmt.Printf("类型错误,实际类型: %T", v)
    }
    for k, l := range m {
        if k == "ATA_ESKI"{ // 目标数据存储在该键对应的Map中
            a, ok := l.(map[string]interface{}) // 二次类型断言
            if !ok {
                fmt.Printf("类型错误,实际类型: %T", v)
            }
            for b,c := range a{
                if b == "satis"{ // 提取目标售价字段
                    fmt.Println("当前价格为", c)
                }
            }
        }
    }
}

完整可运行代码

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"
)

func main() {
    fetchData()
}

func fetchData() (map[string]interface{}, error) {
    body := strings.NewReader("dil_kodu=tr")
    req, err := http.NewRequest("POST", "https://www.haremaltin.com/dashboard/ajax/doviz", body)
    if err != nil {
        return nil, err
    }
    // 必须携带该请求头模拟AJAX请求,否则接口会返回异常
    req.Header.Set("X-Requested-With", "XMLHttpRequest")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    jsonData, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    var data map[string]interface{}
    err = json.Unmarshal(jsonData, &data)
    if err != nil {
        return nil, err
    }

    for _, v := range data {
        m, ok := v.(map[string]interface{})
        if !ok {
            fmt.Printf("类型错误,实际类型: %T", v)
        }
        for k, l := range m {
            if k == "ATA_ESKI" {
                a, ok := l.(map[string]interface{})
                if !ok {
                    fmt.Printf("类型错误,实际类型: %T", v)
                }
                for b, c := range a {
                    if b == "satis" {
                        fmt.Println("Price", c)
                    }
                }
            }
        }
    }

    return data, nil
}

注:已修正原代码中fecthData的拼写错误为标准fetchData,如果有更简洁的实现方式欢迎交流。


内容的提问来源于stack exchange,提问作者eyup.tatar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:39:14