域名:d.jtup.cc
论排版的重要性:https://zybuluo.com/jtahstu/note/873304
iDomain - 基于Vue.js+MongoDB+Laravel 5.4的域名查询系统
项目
链接 d.jtup.cc
一、idea
why?
因为在老早以前还不太懂的时候,买了一个.com的域名,jtahstu.com,现在感觉太长了,并不太利于让别人记住,所以想换个简短的域名。
二、调研
how?
搜了下是否有查询域名是否已注册的接口,找到两三个,尝试了两种方式,最后使用的万网,也就是阿里云的接口,get一个地址,like this http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=jtahstu.com,然后获取xml数据,解析即可。
ok (〃'▽'〃)
有了这个接口,后面就是遍历了,哈哈,ACM中最常用的方法,暴力搜索,这里是暴力查询。
so (o゚▽゚)o
下面就是要先写个爬虫,不断去拿阿里云接口的数据,然后存到MySQL数据库里。
then →_→
没注册的域名已经有了,下面就是先写个接口,让前端去调,前后分离嘛。这里后端就要考虑MongoDB记录缓存、使用加密算法的数据传输、访问频率限制、搜索记录保存、基于搜索习惯的优化查询、防爬虫等问题了。
finaly 。◕ᴗ◕。
就剩前端的问题了,后端都是小case啦。移动端优先的原则,要写适配移动端的页面,本人前端菜的一批,可耻的使用了别人的模板,自己做了一些修改,能正常用,太炫酷的臣妾做不到啊。
前端在把基础模板搞定之后,使用vue.js,从后台获取数据,渲染页面,然后处理页面的搜索功能等。基本没几行jQuery代码,Vue大法好!!!
三、代码实现
1 爬虫
//请求http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=jtahstu.com <?xml version="1.0" encoding="gb2312"?> <property> <returncode>200</returncode> <key>jtahstu.com</key> <original>211 : Domain name is not available</original> </property>
//请求http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=jtahstu.cn <?xml version="1.0" encoding="gb2312"?> <property> <returncode>200</returncode> <key>jtahstu.cn</key> <original>210 : Domain name is available</original> </property>
不能跑太快,不然阿里云就给封IP了,本人是两次间隔0.5s,这都有点快,之前阿里云已经封过一次了,建议慢点。
2 后端
2.1 Controller
<?php namespace App\Http\Controllers; use App\Http\Common\Response; use Illuminate\Http\Request; use App\Http\Models\Domain; class DomainController extends Controller { public $key = "iDomain"; /** * 首页 * @param Request $request * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(Request $request) { return view('domain'); } /** * 搜索 * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function ajax(Request $request) { $token = $request->input('_token'); $str = trim($request->input('str')); $len = $request->input('len'); $type = $request->input('type'); if ($this->checkParameter($str,$len,$type)) { return Response::responseError('500', '参数错误'); } if($str != 'jt'){ self::writeLog($request->input()); } $data = Domain::locateStr($str, $type, $len); return Response::responseAjax($data); } /** * 记录搜索记录 * @param $data */ public static function writeLog($data) { $data["add_time"] = date("Y-m-d H:i:s"); $manager = new \MongoDB\Driver\Manager("mongodb://username:password@localhost:27017"); $bulk = new \MongoDB\Driver\BulkWrite; $bulk->insert($data); $manager->executeBulkWrite('iApp.domain_log', $bulk); return true; } /** * 检查参数 * @param $str * @param $len * @param $type * @return bool */ public function checkParameter($str,$len,$type) { $strFlag = false; if (strlen($str) <= 0 || strlen($str) > 5 || !ctype_alpha($str)) $strFlag = true; $lenFlag = !in_array($len, [4, 5]); $typeFlag = !in_array($type, ['cc', 'com']); return $strFlag || $lenFlag || $typeFlag; } }
2.2 Model
<?php namespace App\Http\Models; use Illuminate\Database\Eloquent\Model; class Domain extends Model { protected $table = 'domain'; protected $fillable = ['domain','type','num','len']; public static function locateStr($str,$type,$len) { return self::where('type','=',"$type") ->where('len','=',$len) ->whereRaw("locate('".$str."',domain)>0") ->orderBy('id','asc') ->select("domain","num","type") ->get() ->toArray(); } }
3 前端
页面太长了,主要是个js
/** * Created by jtahstu on 2017/9/2. */ csrf_token = document.querySelector('meta[name=jtahstu]').getAttribute('content'); window.isMobile = function() { var check = false; (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); return check; }; var vm = new Vue({ delimiters: ['${', '}'], el: '#app', data: { domain_count: -1, domains: [], default_str: 'jt' }, mounted: function () { this.$nextTick(function () { this.init(); }) }, methods: { init: function () { this.postData(this.default_str) }, search: function () { var word = document.getElementById("search_input").value; if (word.length > 0) { this.postData(word) } }, postData: function (str) { Vue.http.options.emulateJSON = true; var _this = this; this.$http.post( "/domain/ajax", {str: str, type: "cc", len: 4, "_token": csrf_token} ).then(function (res) { // console.log(res.data.data); _this.domain_count = res.data.data.length; _this.domains = res.data.data }) }, }, filters: { domainFilter: function (value) { return "https://wanwang.aliyun.com/domain/searchresult/?keyword=" + value.domain + "&suffix=." + value.type } } }); $(function () { setTimeout(randomColor, 2000); $('#search-btn').click(function () { setTimeout(randomColor, 2000) }); if(!isMobile()){ $('#app').css("width","50%").css("margin-left","25%") } //input按回车键搜索 $("#search_input").keydown(function(event) { if (event.keyCode == 13) { vm.search() } }) }) function randomColor() { $(".domain").each(function () { //随机变色 $(this).css('color', '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).substr(-6)); }) }
Vue.js真的好用,能省掉很多的jQuery代码,视图和数据的双向绑定很不错,而且完全可以充当模板引擎了,这里都没有用laravel自带的blade。
写着玩,熟悉下Vue和MongoDB,也让我挑选了一个比较中意的域名(jtup.cc),这就够了呀。
---
本文章采用 知识共享署名2.5中国大陆许可协议 进行许可,转载必须注明作者和本文链接。
---
发表评论