0×00 開頭照例扯淡php
自從各類脫褲門事件開始層出不窮,在下就學乖了,各個地方的密碼全都改爲不同的,重要賬號的密碼按期更換,生怕被人社出祖宗十八代的我,甚至開始用起了假名字,我給本身起一新網名」興才」,這個看起來還不錯的名字,實際上是咱們家鄉罵人土話,意思是腦殘人士…. -_-|||額好吧,反正是假的,不要在乎這些細節.前端
這只是名,至於姓氏麼,每一個賬號的註冊資料那裏,照着百家姓上趙錢孫李周吳鄭王的依次往下排,什麼張興才,李興才,王興才……因而也不知道我這樣」興才」了多久,終於有一天,我接到一個陌生電話: 您好,請問是馬興才先生嗎?java
好麼,該來的終於仍是來了,因而按名索驥,得知某某網站我用了這個名字,而後經過各類途徑找,果真,那破站被脫褲子了.python
果斷Down了那個褲子,而後就一發不可收拾,走上了收藏褲子的不歸路,直到有一天,我發現收藏已經很是豐富了,粗略估計得好幾十億條數據,拍腦殼一想,這不能光收藏啊,我也搭個社工庫用吧……mysql
0×01 介紹linux
社工庫怎麼搭呢,這種海量數據的東西,並非簡單的用mysql建個庫,而後作個php查詢select * from sgk where username like ‘%xxxxx%’這樣就能完事的,也不是某些幼稚騷年想的隨便找個4g內存,amd雙核的破電腦就能夠帶起來的,上面這樣的語句和系統配置,真要用於社工庫查詢,查一條記錄恐怕得半小時. 好在這個問題早就被一種叫作全文搜索引擎的東西解決了,更好的消息是,全文搜索引擎大部分都是開源的,不須要花錢.git
目前網上已經搭建好的社工庫,大部分是mysql+coreseek+php架構, coreseek基於sphinx,是一款優秀的全文搜索引擎,但缺點是比較輕量級,一旦數據量過數億,就會有些力不從心,而且搭建集羣作分佈式性能並不理想,若是要考慮之後數據量愈來愈大的狀況,仍是得用其餘方案,爲此我使用了solr.github
Solr的基礎是著名的Lucene框架,基於java,經過jdbc接口能夠導入各類數據庫和各類格式的數據,很是適合開發企業級的海量數據搜索平臺,而且提供完善的solr cloud集羣功能,更重要的是,solr的數據查詢徹底基於http,能夠經過簡單的post參數,返回json,xml,php,python,ruby,csv等多種格式.web
之前的solr,本質上是一組servlet,必須放進Tomcat才能運行,從solr5開始,它已經自帶了jetty,配置的好,徹底能夠獨立使用,而且應付大量併發請求,具體的架構咱們後面會講到,如今先來進行solr的安裝配置.sql
0×02 安裝和配置
如下是我整個搭建和測試過程所用的硬件和軟件平臺,本文全部內容均在此平臺上完成:
軟件配置: solr5.5,mysql5.7,jdk8,Tomcat8 Windows10/Ubuntu14.04 LTS
硬件配置: i7 4770k,16G DDR3,2T西數黑盤
2.1 mysql數據庫
Mysql數據庫的安裝和配置我這裏再也不贅述,只提一點,對於社工庫這種查詢任務遠遠多於插入和更新的應用來講,最好仍是使用MyISAM引擎.
搭建好數據庫後,新建一個庫,名爲newsgk,而後建立一個表命名爲b41sgk,結構以下:
id bigint 主鍵 自動增加
username varchar 用戶名
email varchar 郵箱
password varchar 密碼
salt varchar 密碼中的鹽或者第二密碼
ip varchar ip,住址,電話等其餘資料
site varchar 數據庫的來源站點
接下來就是把收集的各類褲子所有導入這個表了,這裏推薦使用navicat,它能夠支持各類格式的導入,具體過程至關的枯燥乏味,須要不少的耐心,這裏就再也不廢話了,列位看官本身去搞就是了,目前我初步導入的數據量大約是10億條.
2.2 Solr的搭建和配置
首先下載solr:
$ wget http://mirrors.hust.edu.cn/apache/lucene/solr/5.5.0/solr-5.5.0.tgz
解壓縮:
$ tar zxvf solr-5.5.0.tgz
安裝jdk8:
$ sudo add-apt-repository ppa:webupd8team/java $ sudo apt-get update $ sudo apt-get install oracle-java8-installer $ sudo apt-get install oracle-java8-set-default
由於是java跨平臺的,Windows下和linux下solr是同一個壓縮包,windows下jdk的安裝這裏再也不說明.
進入解壓縮後的solr文件夾的bin目錄,solr.cmd和solr分別是windows和linux下的啓動腳本:
由於社工庫是海量大數據,而jvm默認只使用512m的內存,這遠遠不夠,因此咱們須要修改,打開solr.in.sh文件,找到這一行:
SOLR_HEAP=」512m」
依據你的數據量,把它修改爲更高,我這裏改爲4G,改完保存. 在windows下略有不一樣,須要修改solr.in.cmd文件中的這一行:
set SOLR_JAVA_MEM=-Xms512m -Xmx512m
一樣把兩個512m都修改爲4G.
Solr的啓動,重啓和中止命令分別是:
$ ./solr start $ ./solr restart –p 8983 $ ./solr stop –all
在linux下還能夠經過install_solr_service.sh腳本把solr安裝爲服務,開機後臺自動運行.
Solr安裝完成,如今咱們須要從mysql導入數據,導入前,咱們須要先建立一個core, core是solr的特有概念,每一個core是一個查詢,數據,索引等的集合體,你能夠把它想象成一個獨立數據庫,咱們建立一個新core:
在solr-5.5.0/server/solr子目錄下面創建一個新文件夾,命名爲solr_mysql,這個是core的名稱,在下面建立兩個子目錄conf和data,把solr-5.5.0/solr-5.5.0/example/example-DIH/solr/db/conf下面的全部文件所有拷貝到咱們建立的conf目錄中.接下來的配置主要涉及到三個文件, solrconfig.xml, schema.xml和db-data-config.xml.
首先打開db-data-config.xml,修改成如下內容:
<dataConfig> <dataSource name="sgk" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/newsgk" user="root" password="password" batchSize="-1" /> <document name="mysgk"> <entity name="b41sgk" pk="id" query="select * from b41sgk"> <field column="id" name="id"/> <field column="username" name="username"/> <field column="email" name="email"/> <field column="password" name="password"/> <field column="salt" name="salt"/> <field column="ip" name="ip"/> <field column="site" name="site"/> </entity> </document> </dataConfig>
這個文件是負責配置導入數據源的,請按照mysql實際的設置修改datasource的內容,下面entity的內容必須嚴格按照mysql中社工庫表的結構填寫,列名要和數據庫中的徹底同樣.
而後打開solrconfig.xml,先找到這一段:
<schemaFactory class="ManagedIndexSchemaFactory"> <bool name="mutable">true</bool> <str name="managedSchemaResourceName">managed-schema</str> </schemaFactory>
把它所有註釋掉,加上一行,改爲這樣:
<!-- <schemaFactory class="ManagedIndexSchemaFactory"> <bool name="mutable">true</bool> <str name="managedSchemaResourceName">managed-schema</str> </schemaFactory>--> <schemaFactory class="ClassicIndexSchemaFactory"/>
這是由於solr5 以上默認使用managed-schema管理schema,須要更改成能夠手動修改.
而後咱們還須要關閉suggest,它提供搜索智能提示,在社工庫中咱們用不到這樣的功能,重要的是,suggest會嚴重的拖慢solr的啓動速度,在十幾億數據的狀況下,開啓suggest可能會致使solr啓動加載core長達幾個小時!
一樣在solrconfig.xml中,找到這一段:
<searchComponent name="suggest" class="solr.SuggestComponent"> <lst name="suggester"> <str name="name">mySuggester</str> <str name="lookupImpl">FuzzyLookupFactory</str> <!-- org.apache.solr.spelling.suggest.fst --> <str name="dictionaryImpl">DocumentDictionaryFactory</str> <!-- org.apache.solr.spelling.suggest.HighFrequencyDictionaryFactory --> <str name="field">cat</str> <str name="weightField">price</str> <str name="suggestAnalyzerFieldType">string</str> </lst> </searchComponent> <requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <str name="suggest">true</str> <str name="suggest.count">10</str> </lst> <arr name="components"> <str>suggest</str> </arr> </requestHandler>
把這些所有刪除,而後保存solrconfig.xml文件.
接下來把managed-schema拷貝一份,重命名爲schema.xml (原文件不要刪除),打開並找到如下位置:
只保留_version_和_root_節點,而後把全部的field, dynamicField和copyField所有刪除,添加如下的部分:
<field name="id" type="int" indexed="true" stored="true" required="true" multiValued="false" /> <field name="username" type="text_ik" indexed="true" stored="true"/> <field name="email" type="text_ik" indexed="true" stored="true"/> <field name="password" type="text_general" indexed="true" stored="true"/> <field name="salt" type="text_general" indexed="true" stored="true"/> <field name="ip" type="text_general" indexed="true" stored="true"/> <field name="site" type="text_general" indexed="true" stored="true"/> <field name="keyword" type="text_ik" indexed="true" stored="false" multiValued="true"/> <copyField source="username" dest="keyword"/> <copyField source="email" dest="keyword"/> <uniqueKey>id</uniqueKey>
這裏的uniqueKey是配置文件中原有的,用來指定索引字段,必須保留. 新建了一個字段名爲keyword,它的用途是聯合查詢,即當須要同時以多個字段作關鍵字查詢時,能夠用這一個字段名代替,增長查詢效率,下面的copyField即用來指定複製哪些字段到keyword. 注意keyword這樣的字段,後面的multiValued屬性必須爲true.
username和email以及keyword這三個字段,用來檢索查詢關鍵字,它們的類型咱們指定爲text_ik,這是一個咱們創造的類型,由於solr雖然內置中文分詞,但效果並很差,咱們須要添加IKAnalyzer中文分詞引擎來查詢中文.在https://github.com/EugenePig/ik-analyzer-solr5下載IKAnalyzer for solr5的源碼包,而後使用Maven編譯,獲得一個文件IKAnalyzer-5.0.jar,把它放入solr-5.5.0/server/solr-webapp/webapp/WEB-INF/lib目錄中,而後在solrconfig.xml的fieldType部分加入如下內容:
<fieldType name="text_ik" class="solr.TextField"> <analyzer type="index" useSmart="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/> <analyzer type="query" useSmart="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/> </fieldType>
保存後,core的配置就算完成了,不過要導入mysql數據,咱們還須要在mysql網站上下載mysql-connector-java-bin.jar庫文件,連同solr-5.5.0/dist目錄下面的solr-dataimporthandler-5.5.0.jar, solr-dataimporthandler-extras-5.5.0.jar兩個文件,所有拷貝到solr-5.5.0/server/solr-webapp/webapp/WEB-INF/lib目錄中,而後重啓solr,就能夠開始數據導入工做了.
2.3 數據導入
確保以上配置徹底正確且solr已經運行,打開瀏覽器,訪問http://localhost:8983/solr/#/ ,進入solr的管理頁面,點擊左側Core Admin,而後Add Core:
name和instanceDir都填寫前面咱們命名的core名稱solr_mysql,點擊add core後,稍等片刻,core就創建完成了.此時在左邊的下拉菜單選擇建立的core,而後進一步選擇Dataimport項,按照以下設置:
點擊Execute,就會開始從mysql導入數據,選中Auto-Refresh Status會自動刷新進度,接下來就是漫長的等待……
導入完成後,咱們就能夠開始查詢了,solr的查詢所有使用post參數,好比:
由於前面已經創建了複合字段keyword,因此這裏咱們直接用keyword:12345678會自動查找username和email中包含12345678的全部結果, start=10&rows=100指定查詢結果返回第11行到第110行的內容,由於solr採用的是分頁查詢,wt=json指定查詢結果是json格式的,還能夠是xml,php,python,ruby以及csv.
上圖返回結果中的numfound:111892表明一共返回的結果數,不指定 start和rows的狀況下默認只顯示前十個結果.還須要注意IKAnalyzer引擎的幾個問題,在以純數字或者純字母關鍵字查詢時, IKAnalyzer會返回正確的結果,但在查詢數字字母混合關鍵字時,須要在後面加*號,查詢漢字時.默認會進行分詞,即把一段關鍵字分紅幾個詞查詢,而社工庫必須精確查詢,因此漢字查詢必須給關鍵字加雙引號.
到這一步,若是隻是搭建一個本地庫,供本身使用,那麼咱們接下來只需寫一個查詢程序,post關鍵字,而後顯示返回的結果便可,好比這樣:
秒查,速度很是快,但若是要架設成服務器,提供給其餘人使用,咱們還有不少工做要作.
0×03 服務器架構和數據增量更新
儘管solr如今已經自帶了jetty,jetty並不弱於tomcat,且沒有後者那麼臃腫,可是不少人在構建web應用時仍是喜歡用之前的習慣,把solr整合進tomcat,而後和後臺程序一鍋亂燉,坦白說,在下並不喜歡這樣的架構,對於大數據應用來講,各個功能組件各自獨立,互相配合遠比大雜燴要有效率和易於維護的多,因此,我理想中的社工庫查詢服務器,應該是如下的架構:
以上架構中,mysql只負責存儲整理好的數據,並不提供查詢服務,整理和導入新數據庫時,只需操做mysql, solr利用自帶的jetty獨立運行,按期從mysql導入增量更新的數據,Tomcat做爲應用服務器,運行提供查詢的servlet應用,此應用經過http向solr post數據並獲取結果,返回給前端頁面,相互獨立又相輔相成.
而且,solr並不依賴於mysql,它自己就是數據庫能夠獨立運行,而社工庫這種東西,並非常常有新數據的,獲取新數據的間隔可能很長,因此上面的定時增量更新能夠改成手動增量更新,沒有新數據時mysql徹底能夠關閉以節約資源.
那麼咱們先開始着手增量更新的設置,咱們如今已有的數據表b41sgk並不動,在此基礎上創建一個和b41sgk結構基本相同的表b41new,不一樣之處是增長了一個字段updatetime,用來自動存儲添加數據的時間,之後的新數據全寫入這個表, b41sgk再也不作更新:
CREATE TABLE b41new ( id bigint NOT NULL auto_increment, username varchar(255), email varchar(255), password varchar(255), salt varchar(255), ip varchar(255), site varchar(255), updatetime timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (‘id’) )
用和前面一樣的步驟創建一個core命名爲solr_newsgk,在db-data-config.xml中作以下設置:
<dataConfig> <dataSource name="sgk" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/newsgk" user="root" password="password" batchSize="-1" /> <document name="mysgk"> <entity name="b41new" pk="id" query="select * from b41new" deltaQuery="select id from b41new where updatetime > '${dataimporter.last_index_time}'" deltaImportQuery="select * from b41new where id='${dataimporter.delta.id}'"> <field column="id" name="id"/> <field column="username" name="username"/> <field column="email" name="email"/> <field column="password" name="password"/> <field column="salt" name="salt"/> <field column="ip" name="ip"/> <field column="site" name="site"/> </entity> </document> </dataConfig>
last_index_time和delta.id是兩個自動變化的參數,分別記錄最後一次導入數據的時間和已導入的最大id值,存儲於當前core的conf目錄下dataimporter.properties文件中,以上設置保存後,提交以下連接:
http://localhost:8983/solr/solr_newsgk/dataimport?command=delta-import&clean=false&commit=true
若是此時數據表b41new中已經添加了新數據,就會自動增量同步到solr中,若是要天天定時自動增量更新,執行:
$ crontab –e
增長一條:
0 0 * * * curl –s "http://localhost:8983/solr/solr_newsgk/dataimport?command=delta-import&clean=false&commit=true"
保存後執行:
$ sudo service cron restart
Solr就會在天天的零時自動增量導入數據,若是是windows系統,能夠利用powershell和計劃任務達到一樣的目的.
如今咱們的服務器搭建還剩下最後一件事: 既然如今咱們準備把solr查詢提供給別人用,那麼問題來了,咱們只但願別人經過tomcat裏的servlet查詢,而不但願直接調用solr,咱們須要屏蔽外部查詢:
$ sudo iptables -I INPUT -p tcp --dport 8983 -j DROP $ sudo iptables -I INPUT -s 127.0.0.1 -p tcp --dport 8983 -j ACCEPT
若是把solr和tomcat放在不一樣的服務器,只需把127.0.0.1改爲tomcat服務器的ip地址.接下來保存:
$ sudo su
# iptables-save > /etc/iptables.up.rules
編輯/etc/network/interfaces,加入下面這行:
pre-up iptables-restore < /etc/iptables.up.rules
0×04 編寫查詢應用
Solr除了能夠經過http post數據來查詢以外,還提供了一套完整的api solrj,其實solrj底層仍是經過http訪問的,但若是你是用java開發,使用它會比直接http訪問方便的多.
咱們啓動eclipse,配置好和tomcat的鏈接,新建一個項目sgk,在構建路徑中添加solr-5.5.0/dist/solrj-lib下的所有jar包,而後添加solr-5.5.0/server/lib/ext中的log4j-1.2.17.jar, slf4j-api-1.7.7.jar, slf4j-log4j12-1.7.7.jar三個包.
在web.xml中添加以下設置:
<context-param> <param-name>solraddr</param-name> <param-value>http://localhost:8983/solr/solr_mysql</param-value> </context-param> <context-param> <param-name>shards</param-name> <param-value>localhost:8983/solr/solr_newsgk,localhost:8983/solr/solr_mysql</param-value> </context-param> <servlet> <servlet-name>sgk</servlet-name> <servlet-class>com.baiker.sgk</servlet-class> <init-param> <param-name>filter_keywords</param-name> <param-value>」|*</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>sgk</servlet-name> <url-pattern>/sgk</url-pattern> </servlet-mapping>
新建一個servlet命名爲searcher:
package com.baiker.sgk; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.solr.client.solrj.*; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.json.JSONArray; import org.json.JSONObject; public class searcher extends HttpServlet { private static final long serialVersionUID = 1L; private static String baseURL = ""; private static String shards = ""; private static SolrClient solr; private String[] colist ={"username", "email", "password", "salt", "ip", "site"}; //定義要檢索的字段列表 private String filterk; /** * 構造函數 */ public searcher() { super(); } /** * 析構函數 */ public void destroy() { super.destroy(); } /** * 初始化servlet */ public void init() throws ServletException { filterk = this.getServletConfig().getInitParameter("filter_keywords"); //從servlet配置中讀取關鍵字過濾表 baseURL = this.getServletContext().getInitParameter("solraddr"); //從全局配置中讀取solr服務器地址 shards = this.getServletContext().getInitParameter("shards"); //讀取多core聯合查詢地址 solr = new HttpSolrClient(baseURL); //實例化SolrClient對象 } /** * 無心義關鍵字屏蔽:檢測搜索關鍵字是否可用 * @param str 關鍵字 * @return boolean */ private boolean NotLegalString(String str){ boolean notlegal = false; //如下預約義一些須要屏蔽的無心義搜索關鍵詞,這些會耗費不少服務器資源,且返回的結果沒有價值 String[] foollist = {"12345","123456","1234567","12345678","123456789","1234567890", "987654321","87654321","7654321","654321","54321","123123","112233","11223344","111222333","111222333444", "abcde","abcdef","abcdefg","abcdefgh","abcdefghi","abcdefghij","aaa123","abc123","bbb123","aabbcc","abcabc","abcdabcd","aaabbbccc","aabbccdd","ccc123","qwert","qwerty","asdfg","asdfgh","qazwsx","user","guest","admin","administrator","manager"}; for(String s : foollist){ if(str.equals(s)) return true; } char first = str.charAt(0); //檢測關鍵字是否爲一組重複字符 for (int i=1; i<str.length(); i++){ if (str.charAt(i) == first) notlegal = true; else notlegal = false; } return notlegal; } /** * 過濾檢索結果字段中的換行符和空格 * @param Result 檢索結果 * @return String */ private String FormatResult(String Result){ Result = Result.replaceAll("(?:\r|\n| )", "").replace(""","\"").replace("\","\\"); return Result; } /** * 搜索前對關鍵字進行一些處理 * @param keyword 關鍵字 * @return String */ private String FormatKeyword(String keyword){ String keytemp = keyword; if(!keyword.matches("[0-9]+") && !keyword.matches("[a-zA-Z]+")){//判斷關鍵字是否爲純數字或者純字母 if(keyword.getBytes().length != keyword.length())//判斷關鍵字是否包含漢字 keytemp = "\"" + keyword + "\"";//漢字加雙引號精確搜索.不加則會開始分詞 else keytemp = keyword + "*";//關鍵字既非純數字純字母.也非漢字,需後面加*號才能精確搜索 } return keytemp; } /** * 構造檢索發生錯誤或無結果時返回的json對象 * @param message 要返回的錯誤提示內容 * @return JSONObject */ private JSONObject ErrorResult(String message){ JSONObject jo = new JSONObject(); jo.put("count",0); jo.put("result","null"); jo.put("Message",message); return jo; } /** * 調用solrj執行檢索 * @param keyword 搜索關鍵字 * @param start 結果起始行 * @param rows 返回行數 * @return JSONObject */ private JSONObject getResult(String keyword,int start,int rows){ try { JSONObject jo = new JSONObject(); if(keyword.equals("")) { return ErrorResult("請輸入關鍵詞"); } if(keyword.length()<5) { return ErrorResult("關鍵詞長度不能小於5"); } if(keyword.length()>30) { return ErrorResult("關鍵詞長度不能大於30"); } if(NotLegalString(keyword)) { return ErrorResult("搜索範圍太大"); } String[] keyfilter = filterk.split("\\|"); for(int i=0;i<keyfilter.length;i++){ if(keyword.contains(keyfilter[i])) //檢查關鍵字是否包含web.xml中定義的過濾敏感詞 { return ErrorResult("關鍵字含有敏感字符"); } } SolrQuery query = new SolrQuery(); //定義一個SolrQuery query.set("q", "keyword:" + FormatKeyword(keyword)); //關鍵詞 query.set("start", start); //起始行 query.set("rows", rows); //行數 query.set("shards", shards); //多core查詢 QueryResponse rsp = solr.query(query);//執行檢索 SolrDocumentList docs = rsp.getResults(); jo.put("count",docs.getNumFound()); //獲取返回的條目數 if(!String.valueOf(docs.getNumFound()).equals("0")) //若是檢索有結果 { JSONArray ja = new JSONArray(); for (SolrDocument doc : docs) { JSONObject jo1 = new JSONObject(); for(int j=0;j<colist.length;j++){ jo1.put(colist[j], FormatResult(String.valueOf(doc.getFieldValue(colist[j])))); } ja.put(jo1); } jo.put("result",ja); return jo; }else { return ErrorResult("未搜索到任何結果"); } } catch (Exception e) { e.printStackTrace(); return null; } } /** * doGet方法 */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain;charset=GBK"); PrintWriter out = response.getWriter(); String k,start,rows; k = request.getParameter("keyword"); start = request.getParameter("start"); rows = request.getParameter("rows"); if (start == null) start = "0"; if (rows == null) rows = "20"; //若是沒有定義起始行和返回行數,則默認爲0和20 if(k == null) out.println("Keyword error!"); //若是沒有提交keyword參數,返回錯誤 else out.println(getResult(k,Integer.parseInt(start),Integer.parseInt(rows)).toString()); //輸出檢索結果 } /** * doPost方法 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
編譯運行,提交http://localhost:8080/sgk/searcher?keyword=xxxxxxxxxxxx這樣的地址,就會返回json數據,接下來只需寫一個前端頁面,解析並顯示這些結果便可