zoukankan      html  css  js  c++  java
  • Golang 谷歌搜索api 实现搜索引擎(前端 bootstrap + jquery)

    Golang 谷歌搜索api 实现搜索引擎(前端 bootstrap + jquery)

    体验 冒号搜索

    1. 获取谷歌搜索api

    谷歌搜索api教程

    2. 后台调用

    程序入口 main.go

    // goSearch project main.go
    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func main() {
        Api()
        ReadApi("./api.txt")
        go TimeTo()
    
        http.HandleFunc("/", Home)
        http.HandleFunc("/search", Search)
        http.Handle("/static", http.FileServer(http.Dir("./static")))
    
        fmt.Print("server is running
    ")
        http.ListenAndServe(":80", nil)
    }
    

    处理函数 route.go

    // route
    package main
    
    import (
        "fmt"
        "io"
        "net/http"
        "strconv"
    )
    
    func Home(w http.ResponseWriter, r *http.Request) {
        fmt.Println("go")
        fmt.Println(GetBest())
        w.Write([]byte("hi"))
    }
    
    func Search(w http.ResponseWriter, r *http.Request) {
        url := "https://www.googleapis.com/customsearch/v1?cx=项目id&safe=是否开启安全模式(active)&key=" + GetBest()
        r.ParseForm()
        q := r.Form["q"][0]
        var p string
        var t string
        if r.Form["p"] != nil {
            p = r.Form["p"][0]
        } else {
            p = ""
        }
        if r.Form["t"] != nil {
            t = r.Form["t"][0]
        } else {
            t = ""
        }
    
        if q == "" {
            w.Write([]byte("null"))
            return
        } else {
            url = url + "&q=" + q
        }
        if p == "" {
            p = "1"
        } else {
            i, _ := strconv.Atoi(p)
            p = strconv.Itoa(i*10 + 1)
        }
        url = url + "&start=" + p
    
        if t != "" {
            url = url + "&siteSearch=" + t
        }
    
        fmt.Println("q= ", q, " p= ", p, " t= ", t)
        client := http.Client{}
        resp, err := client.Get(url)
        if err != nil {
            fmt.Println(err.Error())
            return
        }
        defer resp.Body.Close()
        w.Header().Set("Access-Control-Allow-Origin", "*")
        io.Copy(w, resp.Body)
    }
    

    多个api 获取使用次数最少api,从文件获取apis
    api.go

    // api
    package main
    
    import (
        "bufio"
        "errors"
        "fmt"
        "os"
        "time"
    )
    
    type SeaApi struct {
        apis []api
        time time.Time
    }
    
    type api struct {
        apiCode string
        count   int
    }
    
    var apii *SeaApi
    //初始化
    func Api() {
        apii = &SeaApi{time: time.Now()}
    }
    
    func NewApi() *SeaApi {
        return &SeaApi{time: time.Now()}
    }
    //添加api
    func AddApi(a string) {
        newApi := api{a, 0}
        apii.apis = append(apii.apis, newApi)
    }
    
    func (s *SeaApi) AddApi(a string) {
        newApi := api{a, 0}
        s.apis = append(s.apis, newApi)
    }
    //删除指定api
    func DelApi(n int) {
        apii.apis = append(apii.apis[:n], apii.apis[n+1:]...)
    }
    
    func (s *SeaApi) DelApi(n int) {
        s.apis = append(s.apis[:n], s.apis[n+1:]...)
    }
    //获取指定api
    func GetApi(n int) (api, error) {
        if n > len(apii.apis) {
            return api{}, errors.New("fault index")
        }
        return apii.apis[n], nil
    }
    
    func (s *SeaApi) GetApi(n int) (api, error) {
        if n > len(s.apis) {
            return api{}, errors.New("fault index")
        }
        return s.apis[n], nil
    }
    //获取所有api
    func GetAllApi() *SeaApi {
        return apii
    }
    
    func (s *SeaApi) GetAllApi() *SeaApi {
        return s
    }
    //从文件读取api,每行一个,文件名api.txt
    func ReadApi(file string) interface{} {
        f, err := os.Open(file)
        if err != nil {
            fmt.Print(err.Error())
            return nil
        }
        defer f.Close()
        Clear()
        scan := bufio.NewScanner(f)
        count := 0
        for scan.Scan() {
            str := scan.Text()
            apii.AddApi(str)
            count = count + 1
        }
        return count
    }
    
    func (s *SeaApi) ReadApi(file string) interface{} {
        f, err := os.Open(file)
        if err != nil {
            fmt.Print(err.Error())
            return nil
        }
        defer f.Close()
        Clear()
        scan := bufio.NewScanner(f)
        count := 0
        for scan.Scan() {
            str := scan.Text()
            s.AddApi(str)
            count = count + 1
        }
        return count
    }
    //清理所有api
    func Clear() {
        apii.apis = apii.apis[0:0]
    }
    
    func (s *SeaApi) Clear() {
        s.apis = s.apis[0:0]
    }
    
    func TimeTo() {
        for {
            time.Sleep(time.Duration(1) * time.Hour)
            now := time.Now()
            if now.Sub(apii.time).Hours() > 24 {
                apii.time = now
                for _, a := range apii.apis {
                    a.count = 0
                }
            }
        }
    }
    //轮询,满24小时更新使用次数为0
    func (s *SeaApi) TimeTo() {
        for {
            time.Sleep(time.Duration(1) * time.Hour)
            now := time.Now()
            if now.Sub(s.time).Hours() > 24 {
                s.time = now
                for _, a := range s.apis {
                    a.count = 0
                }
            }
        }
    }
    
    func GetBest() string {
        n := 0
        for i, a := range apii.apis {
            if apii.apis[n].count >= a.count {
                n = i
            }
        }
        apii.apis[n].count = apii.apis[n].count + 1
        return apii.apis[n].apiCode
    }
    //获取使用次数最少的api
    func (s *SeaApi) GetBest() string {
        n := 0
        for i, a := range s.apis {
            if s.apis[n].count >= a.count {
                n = i
            }
        }
        s.apis[n].count = s.apis[n].count + 1
        return s.apis[n].apiCode
    }
    

    3. 前端页面

    html可以自己设计

    主要js代码:

    index.js

    $(document).ready(function () {
        //文本输入框监听
        $("#text").keydown(function (e) {
            var curKey = e.which;
            if (curKey == 13) {
                $("#go").click();
                return false;
            }
        });
        //搜索按钮监听
        $("#go").click(function () {
            var str = $("#text").val();
            console.log(str);
            if (str != '') window.location.href = 'search.html?q=' + str;
        });
    
        //判断是否是手机端
        function IsMobile() {
            var isMobile = {
                Android: function () {
                    return navigator.userAgent.match(/Android/i) ? true : false;
                },
                BlackBerry: function () {
                    return navigator.userAgent.match(/BlackBerry/i) ? true : false;
                },
                iOS: function () {
                    return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
                },
                Windows: function () {
                    return navigator.userAgent.match(/IEMobile/i) ? true : false;
                },
                any: function () {
                    return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
                }
            };
    
            return isMobile.any(); //是移动设备
        }
    
        var mobile_flag = IsMobile();
    
        if (mobile_flag) {
            $("#mho").attr("style","font-size: 3em;");
            $("#pc1").hide();
        }
    })

    search.js

    $(document).ready(function () {
        var str = GetUrlPara();
        var nowPage = 0;
        $("#up").hide();
        $("#down").hide();
        //获取请求参数
        function GetUrlPara() {
            var url = document.location.toString();
            var arrUrl = url.split("?");
            var para = arrUrl[1];
            para = para.split("&");
            var p0 = para[0].split("=");
            return p0[1];
        }
        //ajax获取搜索值
        function Search(query, page, type) {
            query = decodeURIComponent(query);
            var urls = "后台服务器ip或域名/search?q=" + query + "&p=" + page + "&t=" + type;
            $("#tit").html("冒号--> " + decodeURIComponent(query));
            $("#text").attr("value", decodeURIComponent(query));
            urls = urls.replace(/[ ]/g,'_');
            console.log(urls);
            $.ajax({
                type: "GET",
                url: urls,
                dataType: "json",
                success: function (data) {
                    $("#loading").hide();
                    var str1 = '<div class="row"><div class="panel panel-default"><div class="panel-body"><p><h3><a href="';
                    var str2 = '">';
                    var str3 = '</a></h3></p><p>';
                    var str4 = '</p><p><a href="';
                    var str5 = '">';
                    var str6 = '</a></p></div></div></div>';
                    var all = '';
                    for (var j = 0; j < data["items"].length; j++) {
                        all = all + str1 + data["items"][j]["link"] + str2 + data["items"][j]["title"] + str3 + data["items"][j]["snippet"] + str4 + data["items"][j]["link"] + str5 + data["items"][j]["displayLink"] + str6;
                    }
                    $("#cont").html(all);
                    if (data["queries"]["nextPage"] != null) {
                        $("#down").show();
                    } else {
                        $("#down").hide();
                    }
                    if (nowPage != 0) {
                        $("#up").show();
                    } else {
                        $("#up").hide();
                    }
                }
            });
        }
    
        Search(str, 0, "");
    
        $("#text").keydown(function (e) {
            var curKey = e.which;
            if (curKey == 13) {
                $("#go").click();
                return false;
            }
        });
    
        $("#go").click(function () {
            var strText = $("#text").val();
            if (strText == "") {
                window.location.href = 'index.html';
            }
            else {
                window.location.href = 'search.html?q=' + strText;
            }
            //Search(strText,0,"");
        });
    
        $("#logo").click(function () {
            window.location.href = 'index.html';
        });
        //回到顶部
        function pageScroll() {
            $('html,body').animate({
                scrollTop: 0
            }, 1000);
        }
    
        $("#up").click(function () {
            $("#loading").show();
            nowPage--;
            Search(str, nowPage, "");
            pageScroll();
        });
    
        $("#down").click(function () {
            $("#loading").show();
            nowPage++;
            Search(str, nowPage, "");
            pageScroll();
        });
    
    
        function IsMobile() {
            var isMobile = {
                Android: function () {
                    return navigator.userAgent.match(/Android/i) ? true : false;
                },
                BlackBerry: function () {
                    return navigator.userAgent.match(/BlackBerry/i) ? true : false;
                },
                iOS: function () {
                    return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
                },
                Windows: function () {
                    return navigator.userAgent.match(/IEMobile/i) ? true : false;
                },
                any: function () {
                    return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
                }
            };
    
            return isMobile.any(); //是移动设备
        }
    
        var mobile_flag = IsMobile();
    
        if (mobile_flag) {
            $("#mho").attr("style", "font-size: 2em;text-align: center;");
        }
    })

    4. 程序上线

    我将html、js托管在coding pages上,go程序发布到美国服务器ubuntu18上,服务器开启了bbr加速,域名全部使用cloudflare,并开启了cdn功能(有缓存,调试的话先关了)。

    小结

    golang程序的编写,使用了许多go官方库,也踩了许多坑,但是对go 的库使用更加熟练。前端页面的编写主要用bootstrap和jquery框架,开发速度快很多,相较于以前,对这两个框架使用更加灵活,官方文档认真的看下来会发现以前没认真看真的走了好多弯路。

    效果图

    首页

    搜索页

  • 相关阅读:
    arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)
    arcgis api 3.x for js 入门开发系列七图层控制(附源码下载)
    arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)
    arcgis api 3.x for js 入门开发系列五地图态势标绘(附源码下载)
    arcgis api 3.x for js 入门开发系列四地图查询(附源码下载)
    Java里面获取当前服务器的IP地址
    Flutter at Google I/O 2018
    Modbus RTU 协议使用汇总
    plsql 创建表空间、用户、赋予权限
    Oracle:ODP.NET Managed 小试牛刀
  • 原文地址:https://www.cnblogs.com/boxker/p/11057614.html
Copyright © 2011-2022 走看看