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\n")
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框架,开发速度快很多,相较于以前,对这两个框架使用更加灵活,官方文档认真的看下来会发现以前没认真看真的走了好多弯路。

效果图

Golang 谷歌搜索api 实现搜索引擎(前端 bootstrap + jquery)的更多相关文章

  1. Python + Bottle + 谷歌搜索Api 实现简单搜索引擎

    1.运行环境 python3 centos7 2.Bottle的使用 使用bottle主要是因为它仅用python自带的库即可实现对web的搭建. bottle源码分析 bottle使用教程 3.代码 ...

  2. ASP.NET实现二维码 ASP.Net上传文件 SQL基础语法 C# 动态创建数据库三(MySQL) Net Core 实现谷歌翻译ApI 免费版 C#发布和调试WebService ajax调用WebService实现数据库操作 C# 实体类转json数据过滤掉字段为null的字段

    ASP.NET实现二维码 using System;using System.Collections.Generic;using System.Drawing;using System.Linq;us ...

  3. jsonp跨越请求百度搜索api 实现下拉列表提示

    题目来源: 最近在做百度IFE前端技术学院的题,然后有一题就是模拟百度搜索智能提示.题目是开源的,稍后给出地址. 因为博主没学过后端啊,欲哭无泪,所以不能实现后端模糊搜索,那如果前端ajax纯粹请求一 ...

  4. 基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术-Angel工作室通用权限管理

    一.Angel工作室简单通用权限系统简介 AngelRM(Asp.net MVC Web api)是基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术 ...

  5. 使用Javascript从Google Places搜索api获取纬度和经度

    如何使用谷歌地图搜索框api从搜索到的位置获取经度和纬度. 我使用与谷歌演示相同的代码 – https://developers.google.com/maps/documentation/javas ...

  6. Google的搜索API的Delphi封装

    这个东西实现了已经有一段时间了,那个时候谷歌还没有退出中国内地呢!而现在呢,谷歌都退了有一些日子了!紧以此纪念一番! 话说谷歌API,我相信很多人应该都知道!不晓得在实际应用中,用的人多不多(我说的不 ...

  7. Lucene.net站内搜索—5、搜索引擎第一版实现

    目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...

  8. Lucene.net站内搜索—4、搜索引擎第一版技术储备(简单介绍Log4Net、生产者消费者模式)

    目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...

  9. 百度音乐搜索API介绍

    百度音乐搜索API的请求地址如下: [html] view plaincopy http://box.zhangmen.baidu.com/x?op=12&count=1&title= ...

随机推荐

  1. Java获取路径

    "./" 代表当前目录,"../"代表上级目录 后续更新!!!

  2. Leetcode:根据身高重建队列

    题目 假设有打乱顺序的一群人站成一个队列. 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数. 编写一个算法来重建这个队列. 注意: 总人数少于11 ...

  3. Java EE学习笔记(十)

    MyBatis与Spring的整合 1.整合环境搭建 1).要实现MyBatis与Spring的整合,很明显需要这两个框架的JAR包,但是只使用这两个框架中所提供的JAR包是不够的,还需要其他的JAR ...

  4. Net Core2.0 基于QuartzNet任务管理系统

    Net Core2.0 基于QuartzNet任务管理系统 Quartz.NET官网地址:https://www.quartz-scheduler.net/ Quartz.NET文档地址:https: ...

  5. IIS中的 Asp.Net Core 和 dotnet watch

    在基于传统的.NET Framework的Asp.Net Mvc的时候,本地开发环境中可以在IIS中建立一个站点,可以直接把站点的目录指向asp.net mvc的项目的根目录.然后build一下就可以 ...

  6. 058 Length of Last Word 最后一个单词的长度

    给定一个字符串, 包含大小写字母.空格 ' ',请返回其最后一个单词的长度.如果不存在最后一个单词,请返回 0 .注意事项:一个单词的界定是,由字母组成,但不包含任何的空格.案例:输入: " ...

  7. scrapy-redis 分布式哔哩哔哩网站用户爬虫

    scrapy里面,对每次请求的url都有一个指纹,这个指纹就是判断url是否被请求过的.默认是开启指纹即一个URL请求一次.如果我们使用分布式在多台机上面爬取数据,为了让爬虫的数据不重复,我们也需要一 ...

  8. 专题《一》 mysql优化

    从今天开始,在这里记录面试会问的问题,针对java高级开发,架构师方向. 1.数据库设计要合理.开发经验不同  设计表水平不同  影响后面操作 三范式:1------------原子约束,每列不可分割 ...

  9. Error occurred while loading plugins. CLI functionality may be limited.

    npm install --save-dev --save-exact @ionic/cli-plugin-ionic-angular@latest @ionic/cli-plugin-cordova ...

  10. 在CentOS7上源码安装php7--Install php7 from source on CentOS7

    首先下载php源码包并解压: # wget http://cn2.php.net/get/php-7.0.9.tar.gz/from/this/mirror # .tar.gz # cd php- 然 ...