百度云开放referer api接口 ,能够获取百度关键词

百度云如今开放了referer api功能,能够经过 百度refer中的eqid参数来获取百度关键词。html

详见:https://cloud.baidu.com/doc/RefererAPI/ProductDescription.htmlpython

此接口为付费接口,并且目前只能在百度云(北京)的环境内调用。也就是说,想调用此接口,必需要有一台百度云北京区域的服务器,能够在百度云服务器上搭建代理服务,来实现远程调用。golang

注:json

  1. 只有企业认证的帐户才能调用此接口,我的帐户没法调用。
  2. 能够考虑使用缓存来减小接口请求次数,可是关键词和eqid是一对多的关系,在不一样的时间搜索同一个关键词,eqid是会变化的。因此,缓存做用有限。

官方目前只给出了python版本的代码示例,下面是我参照官方python示例写出的golang版本的测试代码:api

package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

func getAuth(accessKey, accessSecret, utcTimeStr, urlstr, method string) (string, error) {

	urlParseRet, err := url.Parse(urlstr)

	if err != nil {
		return "", err
	}

	host := urlParseRet.Host
	path := urlParseRet.Path
	version := "1"
	expirationSeconds := "1800"
	signatureHeaders := "host"

	val := fmt.Sprintf("bce-auth-v%s/%s/%s/%s", version, accessKey, utcTimeStr, expirationSeconds)

	key := []byte(accessSecret)
	h := hmac.New(sha256.New, key)
	_, err = h.Write([]byte(val))

	if err != nil {
		return "", errors.New("writing key error:" + err.Error())
	}

	signingKey := hex.EncodeToString(h.Sum(nil))

	canonicalURI, err := url.PathUnescape(path)

	if err != nil {
		return "", errors.New("unescape path failed:" + err.Error())
	}

	canonicalHeaders := fmt.Sprintf("host:%s", strings.Trim(host, " "))
	canonicalRequest := fmt.Sprintf("%s\n%s\n\n%s", strings.ToUpper(method), canonicalURI, canonicalHeaders)

	key = []byte(signingKey)
	h = hmac.New(sha256.New, key)
	_, err = h.Write([]byte(canonicalRequest))

	if err != nil {
		return "", errors.New("writing signature error:" + err.Error())
	}

	signature := hex.EncodeToString(h.Sum(nil))

	authorization := fmt.Sprintf("bce-auth-v%s/%s/%s/%s/%s/%s", version, accessKey, utcTimeStr, expirationSeconds, signatureHeaders, signature)

	return authorization, nil
}

// 将时间戳(精确到秒)0转换为时间字符串
func DateTime(timestamp int64) string {

	var lctime = time.Unix(timestamp, 0)

	timelayout := "2006-01-02T15:04:05Z"

	lca, err := time.LoadLocation("")

	if err != nil {
		panic(err)
	}
	var ltime = lctime.In(lca).Format(timelayout)

	return ltime
}

func GetKeywordByEqid(eqid string) string {
	accessKey := "xxxx"
	accessSecret := "xxxx"

	reqUrl := "http://referer.bj.baidubce.com/v1/eqid" + "/" + eqid
	method := "GET"

	utcTime := time.Now().Unix()
	utcTimeStr := DateTime(utcTime)

	auth, _ := getAuth(accessKey, accessSecret, utcTimeStr, reqUrl, method)

	// 发送http请求
	client := &http.Client{}
	//提交请求
	reqest, err := http.NewRequest("GET", reqUrl, nil)

	//增长header选项
	reqest.Header.Add("accept-encoding", "gzip, deflate")
	reqest.Header.Add("host", "referer.bj.baidubce.com")
	reqest.Header.Add("content-type", "application/json")
	reqest.Header.Add("x-bce-date", utcTimeStr)
	reqest.Header.Add("authorization", auth)
	reqest.Header.Add("accept", "*/*")

	if err != nil {
		panic(err)
	}

	begin := time.Now()
	//处理返回结果
	response, err := client.Do(reqest)

	if err != nil {
		panic(err)
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		panic(err)
	}

	result := string(body)
	fmt.Println(result)

	resultDecode, err := url.QueryUnescape(result)

	if err != nil {
		panic(err)
	}

	end := time.Now()
	td := end.Sub(begin)
	fmt.Println("timeUsed:\t", td)

	return resultDecode
}

func main() {

	result := GetKeywordByEqid("d6ebbb990001e54a000000065b7989ad")

	resultMap := make(map[string]string)
	err := json.Unmarshal([]byte(result), &resultMap)

	if err != nil {
		panic(err)
	}

	keyword := ""

	if _, ok := resultMap["wd"]; ok {
		keyword = resultMap["wd"]
	}

	fmt.Println(keyword)
}

 

须要注意的是:referer.bj.baidubce.com这个域名,在公网是没有dns解析的,只在北京的百度云内有解析,可是在加密的时候,会对请求的host进行加密,因此咱们须要在本身的服务器上,把这个域名解析到本身购买的百度云服务器上,再将其代理到这个域名。若是使用curl,能够直接经过curlopt_connect_to属性,将其解析到本身的百度云服务器。缓存