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. 特殊形状图片之遮罩蒙版CSS3-Mask效果

    前不久做了一个项目,需要一个小效果,就是获取用户头像以心形的形状展现在页面上,开始小五想的实现方式是canvas画图或CSS3的clip(剪切),发现都不理想,和设计稿里的图形美观度相差太大,而且实现 ...

  2. [题解](gcd/欧拉函数)luogu_P2568_GCD

    求gcd(x,y)=p等价于求gcd(x/p,y/p)=1,转化为了n/p内互质的个数 所以欧拉函数,因为有序所以乘2,再特判一下只有在1,1情况下才会重复计算,所以每次都减一 数组开小一时爽,提交w ...

  3. 099 Recover Binary Search Tree 复原二叉搜索树

    二叉排序树中有两个节点被交换了,要求把树恢复成二叉排序树. 详见:https://leetcode.com/problems/recover-binary-search-tree/submission ...

  4. ssis-oracle 数据流任务

    [OLE DB 源 1 [16]] 错误: SSIS 错误代码 DTS_E_CANNOTACQUIRECONNECTIONFROMCONNECTIONMANAGER.对连接管理器“F360DB”的 A ...

  5. Centos7.2内网环境安装MySQL5.7.24

    1.配置本地yum源 内网环境,首先需要配置本地yum源,以解决MySQL的依赖安装,具体参考该文:点击打开 2.查看服务器环境 uname -a 3.去官网下载MySQL安装包 MySQL官网网址: ...

  6. express转发请求

    express var express = require('express'); var axios = require('axios'); var qs = require('qs'); var ...

  7. JAVA基础之基本类型包装类、System类、Math类、Arrays类及大数据运算

    个人理解: 为了方便运算及调用一些方法,我们需要将基本类型的数值转换为对象:不过转换的时候需要特别注意好它们的类型到底是什么,需要调用方法的类名是哪个!特别注意是Byte常量池的相关问题(==):gc ...

  8. 浏览器兼容之条件注释,cssHack

    对于形形色色的浏览器,随之而来的就是一些兼容问题,大多应该都是IE下的兼容问题,因为任何浏览器下出现渲染不一致都极有可能是我们自己的结构或样式不符合W3C的某些要求,或者说违背了浏览器的某些规则而先造 ...

  9. CoordinatorLayout使用笔记

    CoordinatorLayout的使用笔记 首先第一个子控件是AppBarLayout存放首部控件,里面放了一个CollapsingToolbarLayout.代码如下: <android.s ...

  10. linux机器上部署多台Tomcat

    在Linux机器上部署多台Tomcat, 我部署的是Tomcat8,只需要一步,即避免端口号冲突. 在解压后的tomcat目录下,修改conf下server.xml. 修改shutdown端口: &l ...