// searx_parse.go:searxng json 样本解析(RawResult.Extra → 中间条目)。 // // 形状权威:bench/searxng-cn/samples/t1-1.excerpt.json(title/url/content/engine // + publishedDate 可选 + unresponsive_engines)。与 dock 包的响应解码解耦: // 模版层只认 Extra 里的 searx_results。 package scheduler import ( "encoding/json" "time" "onesvm.com/onesvm/browser-server/internal/contract" ) // searxItem 搜索条目(与 dock 侧响应形状一致;publishedDate 为引擎返回字符串)。 type searxItem struct { Title string `json:"title"` URL string `json:"url"` Content string `json:"content"` Engine string `json:"engine"` PublishedDate *string `json:"publishedDate"` } // parseSearxResults 从 RawResult.Extra 解析结果条目与 unresponsive 引擎名。 func parseSearxResults(raw *contract.RawResult) ([]searxItem, []string) { var items []searxItem if v, ok := raw.Extra["searx_results"]; ok { if b, err := json.Marshal(v); err == nil { _ = json.Unmarshal(b, &items) } } var unres []string if v, ok := raw.Extra["unresponsive_engines"]; ok { var pairs []json.RawMessage if b, err := json.Marshal(v); err == nil && json.Unmarshal(b, &pairs) == nil { for _, p := range pairs { var pair [2]string if json.Unmarshal(p, &pair) == nil && len(pair) == 2 { unres = append(unres, pair[0]+"("+pair[1]+")") } } } } return items, unres } // publishedAtOf 引擎时间串 → 东八区 Time(多格式容错;失败给 nil 由调用方置空)。 func publishedAtOf(s string) (contract.Time, bool) { layouts := []string{time.RFC3339, "2006-01-02 15:04:05", "2006-01-02"} for _, l := range layouts { if t, err := time.Parse(l, s); err == nil { return contract.NewTime(t), true } } return contract.Time{}, false }