[关闭]
@jtahstu 2017-09-18T03:39:02.000000Z 字数 6527 阅读 2879

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 爬虫

  1. //请求http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=jtahstu.com
  2. <?xml version="1.0" encoding="gb2312"?>
  3. <property>
  4. <returncode>200</returncode>
  5. <key>jtahstu.com</key>
  6. <original>211 : Domain name is not available</original>
  7. </property>
  1. //请求http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=jtahstu.cn
  2. <?xml version="1.0" encoding="gb2312"?>
  3. <property>
  4. <returncode>200</returncode>
  5. <key>jtahstu.cn</key>
  6. <original>210 : Domain name is available</original>
  7. </property>

不能跑太快,不然阿里云就给封IP了,本人是两次间隔0.5s,这都有点快,之前阿里云已经封过一次了,建议慢点。

2 后端

2.1 Controller

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Common\Response;
  4. use Illuminate\Http\Request;
  5. use App\Http\Models\Domain;
  6. class DomainController extends Controller
  7. {
  8. public $key = "iDomain";
  9. /**
  10. * 首页
  11. * @param Request $request
  12. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  13. */
  14. public function index(Request $request)
  15. {
  16. return view('domain');
  17. }
  18. /**
  19. * 搜索
  20. * @param Request $request
  21. * @return \Illuminate\Http\JsonResponse
  22. */
  23. public function ajax(Request $request)
  24. {
  25. $token = $request->input('_token');
  26. $str = trim($request->input('str'));
  27. $len = $request->input('len');
  28. $type = $request->input('type');
  29. if ($this->checkParameter($str,$len,$type)) {
  30. return Response::responseError('500', '参数错误');
  31. }
  32. if($str != 'jt'){
  33. self::writeLog($request->input());
  34. }
  35. $data = Domain::locateStr($str, $type, $len);
  36. return Response::responseAjax($data);
  37. }
  38. /**
  39. * 记录搜索记录
  40. * @param $data
  41. */
  42. public static function writeLog($data)
  43. {
  44. $data["add_time"] = date("Y-m-d H:i:s");
  45. $manager = new \MongoDB\Driver\Manager("mongodb://username:password@localhost:27017");
  46. $bulk = new \MongoDB\Driver\BulkWrite;
  47. $bulk->insert($data);
  48. $manager->executeBulkWrite('iApp.domain_log', $bulk);
  49. return true;
  50. }
  51. /**
  52. * 检查参数
  53. * @param $str
  54. * @param $len
  55. * @param $type
  56. * @return bool
  57. */
  58. public function checkParameter($str,$len,$type)
  59. {
  60. $strFlag = false;
  61. if (strlen($str) <= 0 || strlen($str) > 5 || !ctype_alpha($str))
  62. $strFlag = true;
  63. $lenFlag = !in_array($len, [4, 5]);
  64. $typeFlag = !in_array($type, ['cc', 'com']);
  65. return $strFlag || $lenFlag || $typeFlag;
  66. }
  67. }

2.2 Model

  1. <?php
  2. namespace App\Http\Models;
  3. use Illuminate\Database\Eloquent\Model;
  4. class Domain extends Model
  5. {
  6. protected $table = 'domain';
  7. protected $fillable = ['domain','type','num','len'];
  8. public static function locateStr($str,$type,$len)
  9. {
  10. return self::where('type','=',"$type")
  11. ->where('len','=',$len)
  12. ->whereRaw("locate('".$str."',domain)>0")
  13. ->orderBy('id','asc')
  14. ->select("domain","num","type")
  15. ->get()
  16. ->toArray();
  17. }
  18. }

3 前端

页面太长了,主要是个js

  1. /**
  2. * Created by jtahstu on 2017/9/2.
  3. */
  4. csrf_token = document.querySelector('meta[name=jtahstu]').getAttribute('content');
  5. window.isMobile = function() {
  6. var check = false;
  7. (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);
  8. return check;
  9. };
  10. var vm = new Vue({
  11. delimiters: ['${', '}'],
  12. el: '#app',
  13. data: {
  14. domain_count: -1,
  15. domains: [],
  16. default_str: 'jt'
  17. },
  18. mounted: function () {
  19. this.$nextTick(function () {
  20. this.init();
  21. })
  22. },
  23. methods: {
  24. init: function () {
  25. this.postData(this.default_str)
  26. },
  27. search: function () {
  28. var word = document.getElementById("search_input").value;
  29. if (word.length > 0) {
  30. this.postData(word)
  31. }
  32. },
  33. postData: function (str) {
  34. Vue.http.options.emulateJSON = true;
  35. var _this = this;
  36. this.$http.post(
  37. "/domain/ajax",
  38. {str: str, type: "cc", len: 4, "_token": csrf_token}
  39. ).then(function (res) {
  40. // console.log(res.data.data);
  41. _this.domain_count = res.data.data.length;
  42. _this.domains = res.data.data
  43. })
  44. },
  45. },
  46. filters: {
  47. domainFilter: function (value) {
  48. return "https://wanwang.aliyun.com/domain/searchresult/?keyword=" + value.domain + "&suffix=." + value.type
  49. }
  50. }
  51. });
  52. $(function () {
  53. setTimeout(randomColor, 2000);
  54. $('#search-btn').click(function () {
  55. setTimeout(randomColor, 2000)
  56. });
  57. if(!isMobile()){
  58. $('#app').css("width","50%").css("margin-left","25%")
  59. }
  60. //input按回车键搜索
  61. $("#search_input").keydown(function(event) {
  62. if (event.keyCode == 13) {
  63. vm.search()
  64. }
  65. })
  66. })
  67. function randomColor() {
  68. $(".domain").each(function () {
  69. //随机变色
  70. $(this).css('color', '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).substr(-6));
  71. })
  72. }

Vue.js真的好用,能省掉很多的jQuery代码,视图和数据的双向绑定很不错,而且完全可以充当模板引擎了,这里都没有用laravel自带的blade。

写着玩,熟悉下Vue和MongoDB,也让我挑选了一个比较中意的域名(jtup.cc),这就够了呀。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注