简单的网页关键词匹配工具

简单的网页关键词匹配工具

作者:Monica Pawlan
2003年7月

你是否曾经使用大量的详细信息创建网页,然后希望读者可以使用一种简单的方法,根据特定于用户的关键词分析和进入相应页面?本文解释了如何使用HTML表单和JSP技术来正确地实现上述要求。即使你从没希望得到这种效果,你可能也会发现本文的演示例子和代码练习十分有用,因为这些例子和代码涵盖了如何检索请求的值,并将这些值与静态文件中读到的值进行比较。

  • 工作原理
  • HTML表单
  • 搜索网页
  • 代码训练
  • 捕捉关键词

工作原理

牋牋 这个HTML表单已经放置在你想要搜索的网页里了。该表单给出了一个可选的关键词列表,这些关键词是网页中已知的词,与你的主题不匹配,但是你相信用户可能想要搜索这些词。该表单还为用户提供了一个输入域,如果用户没有在那个列表中找到想要的关键词,就可以在这个输入域中输入他想要的关键字。

牋牋 当用户敲回车键或点击Go按钮时,就会调用JSP逐行分析HTML页面,寻找用户指定的关键词,并返回该HTML页面中包含关键词的所有行。返回的结果根据匹配的关键词来组织。

HTML表单

牋牋 下图左面显示了这个HTML表单,右边给出了创建该表单的HTML代码。这个表单是可以用的,你可以选则或输入关键词并点击Go按钮。

牋牋 当你点击Go按钮之后,一个JSP页面将被调用来分析JavaServer Pages Technology索引页面的一份拷贝,并返回一个文章列表,这些文章的某个或某些条目包含了指定的关键词。举例来说,如果你记得曾经读到一篇Steve写的文章,那么输入“Steve”并点击Go按钮,就可以查看Steve的文章列表。


注意: 这个过程可能持续几秒钟的时间,因为下面描述的这个搜索页需要读取很多标题条、脚注和左侧导航的HTML代码。


表单外观

实现该表单的HTML

Select keywords from the list below:

and/or enter a search phrase:

<form action="findwords.jsp" method="get">
Select keywords from the list below:
<input type="hidden" name="col" value="searchreports">
<select size="4" name="qp" multiple>
<option value="Jakarta">Jakarta
<option value="CachedRowSet">CachedRowSet
<option value="properties">Properties
<option value="Apache">Apache
</select>

and/or enter a search phrase:</font>
<input type="text" name="qt" size="20" maxlength="50" value="">
<input type="image" src="go.gif" border="0">
</form>

搜索页面

这个JSP网页的代码需要搜索页 使用段落标签包含起来。例如,网页入口的代码应该像下面给出的这样。注意,为了使HTML页面更加易读,因而在下面的入口代码中没有使用回车:

<P>
<a href="/pathname/">Maintaining State for HTML Form Buttons</a> by Matthias Laux <br>Here's the scoop on using JavaServer Pages custom tags to maintain button state in your HTML forms. <i>(October 2002)</i>
</p>

相反,下面这个例子在“Laux”和“Here’s”之间使用了回车,以确保源文件更加易于理解。

<P>
<a href="/pathname/">Maintaining State for HTML Form Buttons</a> by Matthias Laux
<br>Here's the scoop on using JavaServer Pages custom tags to maintain button state in your HTML forms. <i>(October 2002)</i>
</p>

为什么没有返回格式?

如果你像上面的第一个例子那样不考虑漏掉用于格式化的回车符,那么JSP代码将读取整行数据,分析其中是否有关键词出现,如果有匹配存在,则在结果页面中返回整行。在第二个例子中,JSP代码读取“Laux”之上的行,然后进行分析,如果有匹配就在结果页面中返回该行。这段代码接下来读取以“Here’s”开始的下一行。

简而言之,由于整个页面被打乱了,因此并没有完全返回整个页面。在上面的例子中,如果搜索条件是“Maintaining”,结果只会返回标题和作者而没有简介;如果搜索条件是“maintain”,结果将返回简介而不是标题和作者。

代码分析

本节对findwords.jsp的每一部分分别进行介绍,findwords.jsp是当用户点击Go按钮时调用的JSP代码。


注意: 源代码在一个txt文件中,因此你可以将其当作文本来浏览。以“jsp”为后缀意味着web服务器需要将该文件编译成一个servlet并且执行它。


JSP看上去就像一个HTML网页,只不过其中通过JSP标签嵌入了servlet代码片段。有许多不同类型的JSP标签,在本小节只涉及了其中的一部分。

指令

JSP指令用<%@ and %>指令标签来包含,当JSP网页被转换为servlet时由JSP引擎处理。 本例中的页面指令告诉JSP引擎脚本语言是Java(language="java"),并且需要包含指定的Java包。

声明

JSP声明由<%! and %>声明标签包含,允许你设置变量以便稍后在程序中使用。你也可以在使用的时候声明变量。只是要记住无论变量在哪里声明,其作用域都是整个JSP页面。本例中的声明声明了一个随机访问文件和一些用于读取搜索页的字符串变量。

设置文件和变量

代码的下一行初始化变量,并且打开一个到searchpage.html的连接,searchpage.html是将要搜索的网页。在这个例子中,该文件是JavaServer Pages Technology索引页面的一份拷贝。这个初始化过程获得要搜索的文件的长度,得到该文件的第一行,并且将一些变量设为0或空值。

  • val变量是一个标志,用于指示一个匹配是否是其类别中的第一个,并且由此判断是必须重新建立一个匹配序列,还是在已有的序列上继续搜索。
  • results变量也是一个标志变量,用于指示是否找到匹配。如果没有任何匹配,则在返回页上向用户返回一个消息。

File inputFile = new File("/pathname/searchpage.html");
in = new RandomAccessFile(inputFile, "r");

long length = in.length();

s = in.readLine();

int val = 0;

int results = 0;
String[] qpValues = null;
String qtValue = null;

结果页和记录条目

接下来的代码用于打印结果网页的标题,检查从可选序列得到的选择值(getParameterValues("qp"))和从表单上的输入域得到的值(getParameter("qt"))。找到的所有值都会被检索,并用于创建在结果页顶部显示的项目列表索引。

out.println("<h4>Keyword Search Results</h4>");
out.println("<ul>");

  for(int j = 0; j < qpValues.length; j++) {

out.println("<li><a href=#" + qpValues[j] + ">"
   + qpValues[j] + "</a>");
 }
}

if(request.getParameter("qt") != null) {
 qtValue=request.getParameter("qt");
 if(qtValue.length() > 0) {
  out.println("<li><a href=#" + qtValue + ">"
      qtValue + "</a>");
 }
}

 out.println("</ul>");

大小写和从文件中读取

检索到的任何选项值都使用它在表单中输入的原始大小写,从而与文件中读到的行的字符进行匹配,并且还被全部转换为小写来进行比较。这是为了捕捉该条目中的所有可能性。例如,“Properties”使用大写的“P”与searchpage.html 中的每行进行一次比较,使用小写“p”也做一次。这样同时满足了“properties”在一个句子的开头和在中间的情况。从输入域得到的值则只使用输入的精确值,或者全大写、或者全小写,或者是输入状态。

每行开头和结尾的空格自动去掉,并且每行都检查是否以“<A HREF”开始。searchpage.html文件的每一行都是用左对齐,但是当一行以空格或tab开头时,去掉空格的操作可以解决可能错误地输入到关键词前面的空格或者制表键的问题。文件中我们感兴趣的所有行都是以“<A HREF” 开头的,而这在另一个文件中理所当然是必然会改变的,例如对以“<li”开头的行感兴趣,或其他的一些什么。

选项值:寻找匹配

这段代码的主要部分将选项值和从searchpage.html读到的行进行比较以便寻找匹配。当寻找到匹配时,将该行在其正确的类别下作为一个项目列表项返回到结果页面。

if(request.getParameterValues("qp") != null) {
 qpValues = request.getParameterValues("qp");

 for (int i = 0; i < qpValues.length; i++) {

 while(s!=null) {
  if(s != null && s.length() > 0 ) {
   if(s.trim().startsWith("<A HREF")
      && qpValues[i].length() > 0) {

    String lower = qpValues[i].toLowerCase();

    if(s.indexOf(qpValues[i]) > 0
     || s.indexOf(lower) > 0) {
     results=1;

     if(val == 0) {
      out.println("<a name=" + qpValues[i] + "></a>");
      out.println("<h4>");
      out.println(qpValues[i]);
      out.println("</h4>");
      out.println("<ul>");
      val=1;
     }

     out.println(s);
     out.println("<p>");
   }
  }
 }

   s = in.readLine();
}
val=0;
out.println("</ul>");

选项值:没有找到的结果

如果没有找到匹配,则在结果页面上返回一条相应的消息。然后文件被重置到开头,并且读入第一行来与另一个选项值进行匹配寻找。

if(results==0) {
out.println("<a name=" + qpValues[i]
+ "></a>");
out.println("<h4>");
out.println("No results found for "
+ qpValues[i]);
out.println("</h4>");
} else {
results=0;
}
in.seek(0);
s = in.readLine();
}
}
输入值:寻找匹配

代码的主体将输入值与读到的searchpage.html的各行作比较以寻找匹配。当寻找到匹配时,该行将作为该类别下的一个项目列表项返回到结果页面上。

if(request.getParameter("qt") != null) {

 qtValue = request.getParameter("qt");
 val=0;

 in.seek(0);

 s = in.readLine();


 while(s!=null) {
  if(s != null && s.length() > 0 ) {
   if(s.trim().startsWith("<A HREF")
    ?amp;& qtValue.length() > 0) {

    String uppercase =
        qtValue.toUpperCase();
    String lowercase =
        qtValue.toLowerCase();
    String firstletter =
        qtValue.substring(0,1);
    String lastletters =
        qtValue.substring(1);
    String upfirst =
        firstletter.toUpperCase();
    String initcap =
        upfirst.concat(lastletters);

    if(s.indexOf(qtValue) > 0 ||
      s.indexOf(lowercase) > 0 ||
      s.indexOf(initcap) > 0 ||
      s.indexOf(uppercase) > 0) {
      results=1;

    if(val == 0) {
      out.println("<a name="
         + qtValue + ">");
      out.println("<h4>");
      out.println(qtValue);
      out.println("</h4>");
      out.println("<ul>");
      val=1;
    }

    out.println(s);
    out.println("<p>");
   }
  }
 }

 s = in.readLine();
}
out.println("</ul>");

输入值:没有找到的结果

如果没有找到匹配,结果页面上将返回一条相应的消息。

    if(results==0 && qtValue.length() > 0) {
out.println("<a name="
+ qtValue + ">");
out.println("<h4>");
out.println("No results found for "
+ qtValue);
out.println("</h4>");
out.println("<p>");
} else {
results=0;
}
}
没有选定的关键词

当用户没有成功选定一个选项值,也没有成功地在输入域输入关键词,那就需要在结果页面上返回一条消息通知用户这种情况。

  if(request.getParameter("qp") == null 
牋牋&& qtValue.length() == 0) {
牋 out.println("<h4>");
牋 out.println("No Keywords were selected or entered.");
牋 out.println("</h4>");
牋 out.println("<p>");
}
%>

捕捉关键词

你可以简单地改写这个程序,以捕捉终端用户选择或输入的关键词。捕捉关键词的原因是了解哪些是用户最常选择或输入的关键词。如果你了解到一个特殊的关键词被输入了很多次,那么这就告诉了你用户的兴趣所在,或说明这个经常被输入的关键词可能应该加入到可选序列的选择值中去。

要捕捉这些关键词,你需要改写代码,打开一个有读写权限的文件的输出流,并且向该文件中写入数据。获取选项值和输入值的代码放在该文件的结尾,写入这些值,并在每个值之间增加一个新行字符(/n)以增加可读性。


注意:由选择框得到的值以独立于机器的UTF字符形式被写入到keywords.txt中,因为UTF字符被用于图形的显示。


findwords.jsp显示了增加了功能的全部代码。

  File outputFile = new File("/pathname/keywords.txt");
  outkw = new RandomAccessFile(outputFile, "rw");

. . .

  if(request.getParameterValues("qp") != null) {
  qpValues = request.getParameterValues("qp");
  for(int j = 0; j < qpValues.length; j++) {
  out.println("<li><a href=#"
      + qpValues[j] + ">" + qpValues[j] + "</a>");
    outkw.seek(outputFile.length());
    outkw.writeUTF(qpValues[j]);
    outkw.writeByte('/n');
   }
  }

  if(request.getParameter("qt") != null) {
   qtValue=request.getParameter("qt");
   if(qtValue.length() > 0) {
    out.println("<li><a href=#" + qtValue + ">"
      + qtValue + "</a>");
    outkw.seek(outputFile.length());
    outkw.writeChars(qtValue);
    outkw.writeByte('/n');
   }
  }

结论

JSP技术使得编写一个简单的搜索引擎来分析HTML页面的关键词匹配变得十分容易。这个简单例子的特定于具有一定格式的HTML页面,但是我们可以很容易的该写它,以便将它用于不同格式的网页。

练习1

一个很好的练习是增加代码,使得不管是否在搜索条目中放置了格式化回车符来简化数据读取,都会读取那些行。

练习2

改写这段程序,使之从一个URL连接读取数据。你将会使用到URL类,可以在The Java Tutorial(Java教程)的Reading Directly from a URL(直接从URL读取)这一章找到使用该类的例子。

关于作者

Monica Pawlan使用和编写Java编程语言已有超过6年的时间了。她想要用剩余的空闲时间发展和学习关于澳大利亚本地植物(Australian Native Plants)的知识。她还是《Java编程语言精髓:快速上手指南》(Addison-Wesley,2000)的作者、《Java 2平台高级编程》(Addison-Wesley,2000)的合著者。

 

http://gceclub.sun.com.cn/staticcontent/html/0926/2/2-1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值