You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

87 lines
2.0 KiB

package bingsearch
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"
)
// newSys 创建 Bing 搜索系统对象
// 参数:
// - options: 系统选项
//
// 返回值:
// - sys: 系统对象指针
// - err: 创建过程中的错误
//
// 异常:
// - 无(最小实现,仅进行结构体初始化)
func newSys(options Options) (sys *BingSearch, err error) {
sys = &BingSearch{
options: options,
httpClient: &http.Client{Timeout: 30 * time.Second},
}
return
}
type BingSearch struct {
options Options
httpClient *http.Client
}
// Search 执行网页搜索(最小实现)
// 参数:
// - ctx: 上下文
// - query: 搜索关键词
// - count: 返回条数
// - offset: 偏移量
//
// 返回值:
// - results: BingResponse 最小结构
// - err: 调用过程中的错误
//
// 异常:
// - 当 API Key 未配置时返回错误
// - 当网络请求失败、HTTP 状态非 200 或解析 JSON 失败时返回错误
func (this *BingSearch) Search(ctx context.Context, query string, count, offset int) (results *BingResponse, err error) {
if this.options.ApiKey == "" {
err = fmt.Errorf("bing api key is empty")
return
}
endpoint := "https://api.bing.microsoft.com/v7.0/search"
values := url.Values{}
values.Set("q", query)
if count > 0 {
values.Set("count", fmt.Sprintf("%d", count))
}
if offset > 0 {
values.Set("offset", fmt.Sprintf("%d", offset))
}
mkt := this.options.Market
if mkt == "" {
mkt = "zh-CN"
}
values.Set("mkt", mkt)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s?%s", endpoint, values.Encode()), nil)
if err != nil {
return
}
req.Header.Set("Ocp-Apim-Subscription-Key", this.options.ApiKey)
resp, err := this.httpClient.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("bing http status %d", resp.StatusCode)
return
}
results = &BingResponse{}
if err = json.NewDecoder(resp.Body).Decode(results); err != nil {
return
}
return
}