Golang 谷歌搜索api 实现搜索引擎(前端 bootstrap + jquery)
Golang 谷歌搜索api 实现搜索引擎(前端 bootstrap + jquery)
体验 冒号搜索
1. 获取谷歌搜索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)的更多相关文章
- Python + Bottle + 谷歌搜索Api 实现简单搜索引擎
1.运行环境 python3 centos7 2.Bottle的使用 使用bottle主要是因为它仅用python自带的库即可实现对web的搭建. bottle源码分析 bottle使用教程 3.代码 ...
- 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 ...
- jsonp跨越请求百度搜索api 实现下拉列表提示
题目来源: 最近在做百度IFE前端技术学院的题,然后有一题就是模拟百度搜索智能提示.题目是开源的,稍后给出地址. 因为博主没学过后端啊,欲哭无泪,所以不能实现后端模糊搜索,那如果前端ajax纯粹请求一 ...
- 基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术-Angel工作室通用权限管理
一.Angel工作室简单通用权限系统简介 AngelRM(Asp.net MVC Web api)是基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术 ...
- 使用Javascript从Google Places搜索api获取纬度和经度
如何使用谷歌地图搜索框api从搜索到的位置获取经度和纬度. 我使用与谷歌演示相同的代码 – https://developers.google.com/maps/documentation/javas ...
- Google的搜索API的Delphi封装
这个东西实现了已经有一段时间了,那个时候谷歌还没有退出中国内地呢!而现在呢,谷歌都退了有一些日子了!紧以此纪念一番! 话说谷歌API,我相信很多人应该都知道!不晓得在实际应用中,用的人多不多(我说的不 ...
- Lucene.net站内搜索—5、搜索引擎第一版实现
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- Lucene.net站内搜索—4、搜索引擎第一版技术储备(简单介绍Log4Net、生产者消费者模式)
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- 百度音乐搜索API介绍
百度音乐搜索API的请求地址如下: [html] view plaincopy http://box.zhangmen.baidu.com/x?op=12&count=1&title= ...
随机推荐
- eosiolib文件解析
Source base on EOS version: 1.0.5,some photo except. 在eos源码中,eosiolib库在源码中的位置如下: 在\eos\contracts\e ...
- C语言实现折半插入算法
#include <stdio.h> int BInsertSort(int array[],int left,int right){ //接收主函数调用语句中的实参传到这里的形参里 in ...
- mysql5.7日志时间戳(log_timestmaps)与系统时间不一致问题以及日志报Got an error reading communication packets情况分析
一.mysql安装后error_log日志时间戳默认为UTC(如下图),因此会造成与系统时间不一致,与北京时间相差8个小时. 解决errro_logs时间戳与linux系统时间不一致问题 step1: ...
- XML与JSON的区别
JSON和XML的比较 ◆可读性 JSON和XML的可读性可谓不相上下,一边是简易的语法,一边是规范的标签形式,很难分出胜负. ◆可扩展性 XML天生有很好的扩展性,JSON当然也有,没有什么是XML ...
- 补充:jQuery的ajax
一.jQuery的ajax 什么是ajax AJAX = 异步的javascript和XML(Asynchronous Javascript and XML) 简言之,在不重载整个网页的情况下,AJA ...
- Codeforces Round #377 (Div. 2) E. Sockets
http://codeforces.com/contest/732/problem/E 题目说得很清楚,每个电脑去插一个插座,然后要刚好的,电脑的power和sockets的值相同才行. 如果不同,还 ...
- 宝塔面板安装的mysql5.5用命令行kill -9后启动不了
1.查看mysql版本方法一:status;方法二:select version(); 2.Mysql启动.停止.重启常用命令a.启动方式1.使用 service 启动:[root@localhost ...
- echarts Hello world 入门
<!DOCTYPE html> <html> <head> <title></title> <script type="te ...
- C#入门笔记3 表达式及运算符2
关系运算符,也称布尔比较运算符 注:var1为bool类型,var2与var3可以是其它类型.[数据类型看下一节] 运算符 类别 示例表达式 结果说明 == 二元 var1=var2==var3 如果 ...
- AJPFX总结Java 类加载器
顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java ...