官术网_书友最值得收藏!

1.1 30分鐘實現的搜索引擎

首先從一個簡單的搜索引擎入手,實現一個簡單的指定目錄文件的搜索引擎。實現之前需要讀者具有Java開發方面的基礎知識。

1.1.1 準備工作環境(10分鐘)

首先要準備一個Java的開發環境。當前可以使用JDK 1.6。JDK 1.6可以從Sun的官方網站java.sun.com下載得到。使用默認方式安裝即可。

然后要使用的是一個用來管理搜索引擎索引庫的jar包,叫做Lucene。目前可以從http://lucene.apache.org/java/docs/index.html下載到最新的Lucene,當前的版本是2.3。另外,使用集成開發環境Eclipse,其開發界面如圖1-1所示。

圖1-1 Java開發界面

如果需要用Web界面搜索,還要下載Tomcat,當前可以從http://tomcat.apache.org/下載到,推薦使用Tomcat 5.5以上的版本。

然后增加Tomcat的內存使用量,防止內存溢出。

如果是在Linux下,可以用vi編輯器修改./catalina.sh文件,增加行:

            JAVA_OPTS=-Xmx600m

如果是在Windows下,可以用文本編輯器“記事本”修改./catalina.bat文件,增加行:

            set JAVA_OPTS=-Xmx600m

【作者提示】如果不增加內存使用量,運行時可能會出現java.lang.OutOfMemoryError異常。

1.1.2 編寫代碼(15分鐘)

搜索引擎的基礎在于對全文索引庫的管理,在Lucene中,通過IndexWriter來寫入索引庫。偽代碼如下:

1.創建IndexWriter,準備寫索引;

2.遍歷要索引的路徑;

3.優化索引。

下面是主要的實現代碼:

            public void go() throws Exception  {
                  long start = System.currentTimeMillis();
                  if (verbose) {
                      System.out.println("Creating index in: " + indexDir);
                      //創建索引目錄或者建立增量索引
                      if (incremental) System.out.println("- using incremental mode");
                  }
                  Index = new IndexWriter(new File(indexDir), new StandardAnalyzer(),
                      !incremental);//打開或創建索引庫,indexDir是索引存放的路徑
                  File dir = new File(sSourceDir);//待索引的文件存放的路徑
                  indexDir(dir);//索引路徑
                  index.optimize();//索引優化
                  index.close();//關閉索引庫
                  if(verbose)
                  System.out.println("index complete in :"+(System. currentTime
        Millis() - start)/1000);
            }

下面這段代碼把文件內容加到索引庫:

            private void indexFile(File item) {
              if (verbose) System.out.println("Adding FILE: " + item);
              News news = loadFile(item);//把文件中的內容加載到news對象
              if ( news!= null && news.body != null) {
                  Document doc = new Document();
                  //創建網址列
                  Field f = new Field("url", news.URL ,
                        Field.Store.YES, Field.Index.UN_TOKENIZED,
                        Field.TermVector.NO);
                  doc.add(f);
                  //創建標題列
                  f = new Field("title", news.title ,
                        Field.Store.YES, Field.Index.TOKENIZED,
                        Field.TermVector.WITH_POSITIONS_OFFSETS);
                  doc.add(f);
                  //創建內容列
                  f = new Field("body", news.body.toString() ,
                        Field.Store.YES, Field.Index.TOKENIZED,
                        Field.TermVector.WITH_POSITIONS_OFFSETS);
                  doc.add(f);
                  try{
                    //文檔增加到索引庫
                    index.addDocument(doc);
                  }
                  catch(Exception e)
                  {
                    e.printStackTrace();
                    System.exit(-1);
                  }
              }
        }

完整的代碼可以在本書附帶的光盤中找到。

運行以后,一般會生成以下三個索引文件:

● _0.cfs

● segments.gen

● segments_2

其中任何索引庫都會包括的一個文件是:segments.gen。可以通過判斷一個路徑下是否包括這個文件來判斷一個路徑下是否已經存在Lucene索引。

1.1.3 發布運行(5分鐘)

把搜索頁面index.jsp放到Tomcat中。

            <% if (!query.equals("")) { %>
              <jsp:useBean   id="search"   class="com.bitmechanic.spindle.Search"
        scope="application">
              <!-- Specify the directory that stores our Lucene index created by the
        spindle spider -->
              <% search.init("d:/index"); %>
              </jsp:useBean>
              <jsp:setProperty name="search" property="query"/>
              <list:init name="customers"  listCreator="search" max="10">
              <hr>
              <list:hasResults>
                  <list:iterate>
                          <TABLE width="65%">
                                <TR>
                                <TD>
                                      <a href="<list:iterateProp property="url"/>">
                                      <B><FONT    style="FONT-SIZE:    14px"><list:
                                      iterateProp property="title"/></FONT></B></a>
                                      &nbsp;&nbsp;<FONT   size=-1   color=#6f6f6f>
        (<list:iterateProp     property="source"/>)&nbsp;&nbsp;<list:iterateProp
        property="accessDate"/></FONT>
                                </TD>
                              </TR>
                              <TR>
                                    <TD>
                                            <FONT size=-1><list:iterateProp
                                            property="desc"/></FONT>
                                    </TD>
                              </TR>
                        </TABLE>
                        </list:iterate>
                <pg:pager
                        url="/index.jsp"
                        items="<%=Integer.parseInt(listSize)%>"
                        maxPageItems="10"
                        maxIndexPages="10"
                        export="currentPageNumber=pageNumber"
                        scope="request">

                  <pg:param name="query" value="<%=query%>"/>

                <pg:index export="totalItems=itemCount">

                <pg:page export="firstItem, lastItem">
                <div class="resultInfo">
                當前顯示結果 <strong><%= firstItem %>-<%= lastItem %></strong> 找
                到相關文檔 <strong><%=listSize%></strong> 篇
                </div>
                </pg:page>

                <div class="rnav">
                <table border=0 cellpadding=0 width=1% cellspacing=0 align=
                center><tr align=center valign=top>
                        <td valign=bottom nowrap><font size=-1>結果頁碼:&nbsp;

                        <pg:first unless="current">
                        <td nowrap><a href="<%= pageUrl %>" class="rnavLink">
                        <nobr>首頁</nobr></a>
                          </pg:first>

                          <pg:prev export="pageUrl">
                          <td nowrap><a href="<%= pageUrl %>" class="rnavLink">&#
                          171;&nbsp;上一頁</a>&nbsp;
                          </pg:prev>

                          <pg:pages><%
                            if (pageNumber.intValue() < 10) {
                                %>&nbsp;<%
                            }
                            if (pageNumber == currentPageNumber) {
                                %><b><%= pageNumber %></b><%
                            } else {
                                %><td nowrap>&nbsp;<a href="<%= pageUrl %>"><%=
                                pageNumber %></a>&nbsp;<%
                            }
                          %>
                          </pg:pages>

                          <pg:next export="pageUrl">
                          &nbsp;&nbsp;<td nowrap><a href="<%= pageUrl %>" class=
                          "rnavLink">下一頁&nbsp;&#187;</a>
                          </pg:next>

                          <pg:last unless="current">
                          &nbsp;<td nowrap><a href="<%= pageUrl %>" class=
                          "rnavLink"><nobr>末頁</nobr></a>
                          </pg:last>
                    </table>
                    </div>

                    </pg:index>

                    </pg:pager>

                  </list:hasResults>

                  <list:hasNoResults>
                        對不起,沒有結果返回。<p>建議你換用更少的文字查詢以擴大搜索范圍。
                  </list:hasNoResults>

            </list:init>

            <% } %>

需要使用Tomcat的版本為5.5.X或6.0。為了讓Tomcat支持中文,要修改server.xml文件。設置值URIEncoding:

            <Connector port="8080" maxThreads="150" minSpareThreads="25"
             maxSpareThreads="75" enableLookups="false" redirectPort="8443"
            acceptCount="100" debug="0" connectionTimeout="20000"
            disableUploadTimeout="true" URIEncoding="UTF-8" useBodyEncodingForURI=
            "true" />

同時修改WEB-INF目錄下的web.xml文件,設置Filter:

            <filter>
                <filter-name>Set Character Encoding</filter-name>
                <filter-class>filters.SetCharacterEncodingFilter</filter-class>
                <init-param>
                  <param-name>encoding</param-name>
                  <param-value>utf-8</param-value>
                </init-param>
            </filter>
            <filter-mapping>
                <filter-name>Set Character Encoding</filter-name>
                <url-pattern>/*</url-pattern>
                </filter-mapping>

本節通過使用Lucene實現了一個可以在互聯網上發布的搜索引擎,而世界上最大的互聯網搜索引擎來自Google。

主站蜘蛛池模板: 鸡西市| 普兰县| 达拉特旗| 贵溪市| 潞西市| 灌南县| 扶余县| 和林格尔县| 丹江口市| 措勤县| 工布江达县| 军事| 塘沽区| 屏东县| 屯门区| 宣汉县| 合川市| 基隆市| 丰顺县| 安图县| 孟州市| 呈贡县| 衡山县| 依兰县| 会同县| 江孜县| 沧州市| 胶南市| 壶关县| 宜昌市| 怀集县| 汶川县| 紫云| 同心县| 宁武县| 陈巴尔虎旗| 黑山县| 新民市| 昭苏县| 调兵山市| 璧山县|