[SEO]网站SEO并非一定需要静态化

mikel阅读(772)

在国内,很多“SEO专家”给客户网站的第一诊断结果就是要页面静态化。这倒不是因为动态页面就做不了SEO,而是相对静态页面而言,动态页面的SEO更加难做,受“SEO专家”的技术能力所限而已。

  对于搜索引擎而言,在主观上对静态页面和动态页面并没有特殊的好恶,只是很多动态页面的参数机制不利于搜索引擎收录,而静态页面更容易收录而 已。此外,页面静态化在一定程度上也提高了页面访问速度和系统性能及稳定性——这使得在搜索引擎优化上面,为使得效果更加明显,问题简单快速解决,大家对 站点的静态化趋之若骛。

  然而对于一些大型网站,静态化带来的问题和后续成本也是不容忽视的:

  由于生成的文件数量较多,存储需要考虑文件、文件夹的数量问题和磁盘空间容量的问题———需要大量的服务器设备;

  程序将频繁地读写站点中较大区域内容,考虑磁盘损伤问题及其带来的事故防范与恢复——硬件损耗要更新、站点备份要到位;

  页面维护的复杂性和大工作量,及带来的页面维护及时性问题——需要一整套站点更新制度和专业的站点维护人员;

  站点静态化,增加了更新维护难度和网站管理人员工作强度,增加了硬件设备需求和损耗速度,增加了站点潜在的访问冲突和故障概率。对于一个大型网站而言,这都是必须考虑的问题。

  对于SEO优化,我们不需要真正静态化,只需要假装就可以了。动态页面也一样能够做好SEO优化。

  目前大多数搜索引擎基本都能收录动态页面,使用动态页面的站点数也远远大于静态页面的站点数。

  许多大型网站虽然网址的后缀为。htm,但其实还是动态页面,只是用了URL Rewrite的方式“欺骗”搜索引擎,真正完全静态的没有发现几个。

  目前对于一个动态网站,实施相对静态化的做法基本有如下几种:

  1. 伪静态,URL Rewrite方式。

  2. 类似蜘蛛的方法,动态站点也存在,只是通过一个程序去抓取整个站点并保存发布为需要访问的静态站点。

  不论是真静态页面还是伪静态页面,在方便搜索引擎收录这一点上,效果都是一样的。既然如此,为什么不使用效率更高的“相对静态化”的方法,以避免真正静态化所产生的诸多问题呢?

  在页面更新维护问题上,即使是伪静态,也带来了不少维护的复杂性和工作量。目前较为可取的更新方式有:

  触发式更新:当维护人员在后台更改某些信息后,系统自动或提供手动更新相应显示页面。

  独立、分片式更新:更新与维护分开,页面划分为不同的区,根据一定的规则对于区进行更新。区之间的整合与分离,有的是采用活动域,有的是采用SSI(Server Side Include)。

  对于独立、分片式更新,应当是大型网站相对静态化后较为理想的更新维护模式:

  1. 将各页面定义分区、编号,给定存储规则和更新规则,更新规则分为“依据数据变更更新”和“周期更新”。

  2. 对于各区采用优先级的方式,并提供手工触发的即时更新,以保证部分信息的更新时间需要。

  3. 静态页面替换动态页面,同时保留动态页面,并在静态页面未生成完毕时采用动态页面代替。

  静态化对于网站SEO来说,应当只是一个信号,告诉搜索引擎我的站点很好收录,然后带领搜索引擎尽可能多的“浏览”站点内的内容。只要能够方便浏览和收录,不论是静态页面还是动态页面,搜索引擎都会一视同仁的去收录。

  对于小网站而言,站点静态化或许是解决网站收录量的一个简便的办法,而对于大网站来说,则要认真考虑了,是不是真的有必要去做静态化,还是做一下“相对静态化”就够了。

[Javascript]改变世界的Web前端开发

mikel阅读(782)

乔布斯说:“活着就是为了改变世界,难道还有其它原因吗?” 2008年,在Web前端开发界,无论国外还是国内,都发生了不少事情,有哪些是改变世界或即将改变世界的大事件呢?

JavaScript游戏

2008年4月9日,Dion Almaer发现了一款非常经典的JavaScript游戏:Super Mario. 这款游戏由Jacob Seidelin开发,大小仅14k.
mario
(Super Mario JavaScript版本: http://jsmario.com.ar/)

不少Web开发者们大跌眼镜:这真的是用JavaScript开发出来的?答案是肯定的。这款游戏利用了Canvas元素(IE中用HTML模 拟),图像存储在加密的字符串中,还用base64存储了MIDI背景音乐。除了这些技巧,其它代码就是我们熟悉的HTML、CSS和 JavaScript.

Super Mario JavaScript版本的横空出世(之前也出现过用JavaScript写的游戏,但没有像Super Mario一样引起大家的关注),激起了一股用JavaScript编写游戏的热潮:

许多经典的游戏都有了JavaScript版本:Pac-Man(经典的吃豆子游戏), Space Invaders(太空入侵者),Spacius(百玩不厌的雷电)等等。

甚至还出现了一些比较复杂的角色扮演游戏:Andrew Wooldridge创造的Tombs of Asciiroth 和 CanvasQuest,Pierre Chassaing创造的ProtoRPG等。

伴随JavaScript游戏的热潮,还出现了不少专门用于游戏开发的JavaScript库。最突出的是GameJS(基于Canvas的一个2D游戏开发库) 和 GameQuery(这是JQuery的一个插件)。

除了用Canvas构建2D游戏,用JavaScript还可以构建3D游戏,还出现了非常出色的Processing.js,以及JavaScript PlotTool绘图工具等等。

感慨:JavaScript游戏一段时间内将还只是开发者们的“玩物”,要真正转换为商业应用,可能还有一段漫长的路要走。但是,当Super Mario跳跃在Web网页上时,这昭示着JavaScript的时代已经到来了。JavaScript能做什么?2008年的答案是:JavaScript连游戏都能做!

大放异彩的JQuery

2008年,无论对于jQuery的作者John Resig还是jQuery库本身来说,都是非常棒的一年。jQuery首页上有一行很明显的加粗文字:

jQuery is designed to change the way that you write JavaScript.
jQuery设计成可以改变你书写JavaScript的方式。

jQuery用数据和事实证明了它的魅力。一定程度上,甚至可以毫不夸张地说:jQuery改变了Web前端开发界。下面是用Google Trends统计的常用JavaScript库在2008年的搜索量曲线图:
jslib_trend

2008年9月份,jQuery团队战绩斐然:Microsoft和Nokia正式将jQuery集成进他们的应用程序开发平台。此 外,Google的部分应用里,也早就采纳了jQuery. 从jQuery的首页上还可以看出,DELL, Bank of America, Digg, Technorati, Mozzila等站点都在使用jQuery.

当然,除了jQuery,其它JavaScript在2008年也都有可圈可点的发展。YUI3的Preview版本,是我见过的最具有发展潜力的 框架。ExtJS在国内的普及也非常迅猛,JavaEye社区里,ExtJS一定程度上成了Ajax的代名词,各种有关ExtJS的技术文章和书籍非常多 (遗憾的是书籍的质量不高)。Prototype不温不火。Mootools则在低调中用其优雅的代码吸引了不少忠实用户。

感慨:上面提到的每个JavaScript库都是非常优秀的,掌握任何一个,对于我们的日常工作来说,都绰绰有余了。只是对于 2008年来说,jQuery的表现太突出了,连我这个天天工作用YUI的人,在2008年,都不得不为jQuery鼓掌,为John Resig喝彩!各种JavaScript库的争奇斗艳,这是JavaScript时代已经到来的另一个标志。

蹒跚起步的网页工业化

2008年,如果你是一名Web前端开发工程师,却没有听说过“栅格”两个字,那你一定是工作太忙太专心了。2008年10月份,在淘宝UED博客,出现了一篇“960的秘密”,揭开了网页栅格系统在国内的研究小热潮。
grid

伴随着栅格系统的争论,国内的前端技术博客里还出现不少对CSS框架和布局的探讨。这一切,所要解决的是以下两个问题:

  1. 网页的规范性。随着站点的成长,页面会以几何级数的速度增加。面对成千上万个网页,如何保持风格的一致性是一个不小的挑战。
  2. 网页的工业化产出。在遵守规范和保证质量的基础上,如何让页面制作容易,如何让运营人员能批量制造页面,这是目前许多大型站点面临的另一个问题。

国内站点中,淘宝、百度有啊、网易等站点的已逐步采用栅格系统。淘宝的首页和频道目前已经全部栅格化,同时尝试性开发了TMS(模板管理系统)来解决网页的工业化产出问题。

感慨:网页的高质量工业化产出,在国内很多公司才刚起步。2009年,我相信工业化将依旧是Web前端开发界的关键词。

这些也很出色

  1. 渐进增强。2008年10月份,Aaron Gustafson在ALA网站上发表了一系列有关渐进增强的文章,探讨的核心问题是:JavaScript应该做什么以及Web前端开发的技术流程。 JavaScript游戏让我们看到了JavaScript的魔力,Aaron提醒我们不能滥用JavaScript,我们要仔细考虑 JavaScript的使用场景。可用性,无侵入性,可访问性等等,这些理念是每一个前端开发工程师需要好好思考的。
  2. D2(前端技术论坛)。 2008年,在北京和上海分别举办了两届D2,这是国内前端开发工程师们的两场盛会。前端工程师,这个新生的职位逐步被国内各大公司接受。D2的意义在于,我们聚集在一起,发出了自己的声音!
  3. Google Chrome的诞生。 2008年,Chrome, JS V8引擎,Google迫使各大浏览器厂商开始比拼JavaScript引擎速度,这是JavaScript时代已经到来的另一个标志。Google和 Mozzila的努力,在年末的时候带来鼓舞人心的统计结果:IE的使用率跌破70%. 万恶的IE6,早点灭亡吧。2009年,Google的号角和淘宝网即将掀起的 NO IE6 活动,将加速IE6的灭亡。

最后,用两句话来结束本文:

2008年,我们努力改变世界!
2009年,我们继续改变世界,同时世界将开始为我们而改变!

[C#]用一个实例说说委托,匿名委托,Lamda表达式

mikel阅读(947)

C#到3.0中一直都在不断地提高,增加了很多特性,从2.0的匿名委托到现在的LAMDA表达式,为的就是让大家觉得语言越来越人性化。以下是我写的一个小DEMO,用来简单示例一下他们之间的关系。非常简单易懂。

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
    
public partial class _delegate : System.Web.UI.Page
    {
      
        
delegate string DelegateTest(string s);
        
public static string getString(string t)
        { 
return t; }
        DelegateTest normalDelegate 
= new DelegateTest(getString);
        DelegateTest anonymousDelegate 
= delegate(string a) { return a; };
        DelegateTest lamada 
= s => { return s; };
        
protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(normalDelegate(
"一般委托<br>"));
            Response.Write(anonymousDelegate(
"匿名方法<br>"));
            Response.Write(lamada(
"lamda表达式"));
        }
       
    }
}

[C#]多用户系统如何绑定国际域名

mikel阅读(1234)

多用户系统在网络上很常见,比如淘宝网或者携购网上的店铺就是最典型的多用户系统,每个店主都有一个自己二级域名的小店(如:http://shop88888888.xiegoo.com/),看上去大家都是各自独立的,但从技术曾面来看,其实每个店铺使用的都是同一套程序,唯一的差别就是店铺的界面和数据。

相信实现这样的二级域名指向不同店铺的功能,对大部分程序员来说不是件难事,因为shop后面的88888888里隐藏了店铺唯一的id,通过 shop88888888把这个店铺的界面和数据从数据库里筛选出来是很简单的,我在这里也不详细解释。但是我们经常在网上看到很多“多用户商城”或者“ 建站系统”,支持绑定国际域名,比如携购旗下的独立网店系统http://www.shopxg.com/,只要在线注册,在线绑定国际域名,就能访问自己的网店了。笔者曾经参与开发shopxg,把如何实现这样的功能,拿出来与大家分享,当然可能不是最好最有效的方法,但希望能帮到那些正在为解决这个问题发愁的技术朋友。

因为shopxg是用.NET开发的,所以下面我讲到的情况可能不适合其他语言的系统,但原理是相通的,希望能给您一点启示。

第一步:设计数据库的时候,在“店铺shop”这张表里,要设置一个字段,存放国际域名;

第二步:在shopxg的站点上做泛解析,就是让任何指向到shopxg网站所在服务器的国际域名,都会绑定到shopxg上,至于如何做泛解析,您可以到google查下;

第三步:拿前台的ShopLogin.aspx页面举例,当一个客户输入www.yifull.com/ShopLogin.aspxwww.tiaopidan.com/ShopLogin.aspx的 时候,ShopLogin.aspx页面要马上获取到当前输入的域名,比如使用 Request.ServerVariables["SERVER_NAME"].ToString();当然shopxg使用的是URLRewrite 的重写技术来获取当前域名的,这样的方法有很多,您可以自己选择;

第四步:利用当前的域名,到数据库中精确匹配到某个店铺,然后把该店铺的数据取到前台显示;

当然上面的几步都是非常容易实现的,不是什么难题,但实现了一个多用户系统中每个店铺各自绑定国际域名之后,有很多小问题是不容忽视的:

1.每个页面频繁的获取当前域名,然后到数据库匹配,才知道是哪个店铺在请求数据,会导致系统效率低下,因此我们要让客户在第一次访问一个域名的时 候,把获取回来的店铺编号放进本地cookies,当客户继续访问或者下次来访问的时候,直接从cookies里就能知道当前的域名对应的是哪个店铺了;

2.用户登陆问题:一般的网站都是使用cookies来存放我是否已经登陆某网站的信息的,对于多用户系统,如果用户登陆的时候,cookies没 建好,很容易造成登陆一个网站,就相当于登陆该多用户系统上所有网站;假如可以随意登陆别人的网站后台,那后果将不堪设想;有时候甚至会造成我的定单里有 别人的定单的情况,这都是cookies造成.因此我们在程序建cookies的时候,一定要区分域,在判断用户登陆的过程中,也要严格判断输入的域名和 cookies中的域是否对应;

3.客户在绑定国际域名的时候,一定要判断客户的域名已经存在,并且已经指向了正确的ip,不然一经绑定,客户的网站就无法访问了;

//////获取域名指向的IP

public string GetIPByDomain(string url)
  {
   if (url.Trim() == string.Empty)
    return "";
   try
   {
    System.Net.IPHostEntry host = System.Net.Dns.GetHostByName(url);
    return host.AddressList.GetValue(0).ToString();
   }
   catch (Exception e)
   {
    return "fail";
   }
  }

if(this.GetIPByDomain(this.tbDomian.Text)=="fail")
    {
     Response.Write("<script>alert('系统检测到您的域名不存在,绑定之后会导致您的网站无法访问!');history.go(-1);</script>");
     return;
    }
    if(this.GetIPByDomain(this.tbDomian.Text)!="202.91.243.151")
    {
     Response.Write("<script>alert('系统检测到您的域名还没有指向我们的服务器 202.91.243.151,绑定之后会导致您的网站无法访问!');history.go(-1);</script>");
     return;
    }

4.在程序中任何查询的数据库的操作,必须提供店铺的id才能查询,这样才能避免有人发起恶意操作,把其他网店的信息查询出来.

当然,在实现多用户系统绑定国际域名的时候,会碰到很多其他问题,欢迎大家交流.我的E-mail : cxl@xiegoo.com

[Flex]一周内学会Flex视频合集

mikel阅读(761)

感谢志愿者的辛勤翻译,"一周内学会Flex中文视频翻译"系列终于和众多网友见面了,以下是完整目录。

http://www.riavideo.net/ODT/list.html

第一天

  1. Flex,Flash,Flash Player,AIR概述

  2. 了解Flex Builder

  3. Flex Builder工作空间

  4. 了解Flex预编译组件

  5. 了解MXML

  6. 组件的数据绑定

  7. 处理用户事件

  8. 了解事件对象

  9. 使用ActionScript添加事件侦听器

  10. 使用HttpService获取数据

第二天

  1. 在DataGrid中显示数据

  2. 布局容器的使用

  3. 创建自定义的MXML组件

  4. 实现Value Object类

  5. 创建自定义事件

  6. 创建自定义事件类

  7. 自定义项目渲染器

  8. 探索 Flex Bulider 的使用小窍门

第三天

  1. 数据验证

  2. 使用远程对象来传输数据

  3. 格式化数据

  4. 从列表控件中拖放数据

  5. 使用E4X来过滤XML

  6. 部署Flex和AIR应用

第四天

  1. 执行导航容器

  2. 嵌入图像

  3. 嵌入字体

  4. 创建基于约束的布局

  5. 为MXML组件应用样式

  6. 结合Adobe CS3制作组件皮肤

  7. 创建视图状态

  8. 动画:行为和特效

  9. 结合绘图API绘制图形

  10. 编码实现组件皮肤

  11. 扩展组件

第五天

  1. 了解Flash定时器的行为

更多视频请看:http://www.riavideo.net

[SQLServer]SQL Server2005中文全文搜索问题

mikel阅读(706)

在项目中使用了SQL的全文搜索用来搜索中文的企业名称,但效果一直不理想,比如要搜索“北京三一重工有限公司”,使用“三一”就搜索不到。因是第一次使用SQL的全文搜索,起初以为是SQL的中文分词功能弱的问题,就没有细究。

昨天又重新研究了一下,为了安全起见,我把服务器上的数据导入到开发的机器上做的测试,居然发现在测试的机器上表现相当好。看来不是SQL功能上的问题,是设置上的问题。在网上搜了一下,参考了“一起特殊中文全文检索问题的解决” 这篇文章终于发现了原因。原来是缺少noise.chs文件,补上之后工作正常。

也许这是一个常见的问题,但我想补充一下的就是,大部文章上反应的是少这个文件之后任何查询都会返回“查询子句只包含被忽略的词”,但我遇到的是不 是任何查询都返回“查询子句只包含被忽略的词”,而只是查询功能效果不理想,这样我一直没有想到是noise.chs的问题。

[Lucene]利用Lucene打造站内搜索引擎的思路

mikel阅读(689)

1.为什么要用Lucene,而不用直接从数据库里搜索记录?
主要是考虑到几个因素:(1)性能问题,Lucene是基于文件索引的搜索机制,性能要比数据库里检索更快,特别是数据量大的时候两者区别比较明显。数据 库用Select检索时,默认在执行SQL语句时,会对表锁定,直到查询完成;(2)目前很多网站,都已经将页面静态化,这种情况下,直接用生成的文件编 制索引,再利用Lucene来检索,可以不用查询数据库,减轻了数据库的压力;(3)Lucene可以更方便的进行分词,支持多个关键字检查等操作,在实 现上要比SQL方便;(4)直接基于文件系统的检索,不会有SQL注入风险
2.创建索引
基本上有二种思路,适用于不同的情况
(1)如果网站本身就是静态化的,可以直接读取静态Html文件,来创建索引。注意:如果要实现特定标签的搜索(比如要按产品价格,产品编号,产品摘要, 发布时间等精确搜索产品信息),在读取文件内容时,需要利用正则表达式对Html文件进行匹配分析,得到各个标签的值,再创建Field,加入 Document,最后调用IndexWriter的相应方法创建索引
(2)也可以直接从数据库里查询各标签的值,再按(1)的方法,生成Field–>Document–>加入IndexWriter
3.索引的维护
显然,不可能每次查询都全部将索引生成一次,这里的索引维护主要是索引更新和索引删除,也有两种思路:
(1)找个访问比较少的时段,比如每天晚上0点,做一个C/S程序放在服务器上,用定时器或计划任务全部重新生成索引
(2)更合理有效的方式,是当信息发生修改或删除时,索引维护程序能得到通知,仅更新特定信息的索引就可以了。这里建议用消息队列机制,网站上有信息发生 增,删,改时,将唯一标识值,发送到消息队列,然后索引维护程序监听消息队列,一有消息了,马上根据唯一标识,到数据库里取出修改的信息(或读取修改过的 Html文件),更新指定索引即可
4.分词问题
国内有一些公开的分词组件,可以直接利用,当然有一些是商业化的

[Lucene]DotLucene:37行代码实现全文搜索

mikel阅读(701)

DotLucene是一个强有力的开源全文搜索引擎,它是从Apache的Lucene(java)项目移植到.Net(C#)上的。

DotLucene的效率非常高,并且还具有对搜索结果评级、高光、搜索非结构数据以及本地化等特点。它还和Lucene的索引兼容,因此你可以在不同的平台间迁移而不会丢失任何索引数据。

本文介绍了如何通过简洁的代码来使用DotLucene完成全文搜索功能。

本文翻译自CodeProject上 Dan Letecky 的 DotLucene: Full-Text Search for Your Intranet or Website using 37 Lines of Code 一文,文章版权为原作者所有。

译者:Samuel Chen

Image

DotLucene: 优秀的全文搜索引擎

有可能用37行代码写一个全文搜索么? 恩,我正准备使点小技巧用DotLucene来完成这个麻烦的工作. DotLucene 是一个Jakarta Lucene搜索引擎的移植项目,该项目由 George Aroush et al 维护。下面是它的一些特性:

  • 它能被用在 ASP.NET、WinForms 或者 console 应用;
  • 非常高效的性能; 
  • 搜索结果评级; 
  • 搜索结果中查询关键字高光 ;
  • 搜索结构化和非结构化数据;
  • Metadata 搜索 (时间查询、搜索指定域/字段…)
  • 索引大小大约是索引文本的30%;
  • 并且能存储所有编入索引的文档 Can store also full indexed documents
  • 纯.Net托管代码,单个执行文件 (244 kB)
  • 非常友好的许可 (Apache Software License 2.0)
  • 本地化 (支持 巴西语、捷克语、中文、荷兰语、英语、法语、日语、韩语和俄语)
  • 可扩展 (源代码已包含)
注意

    不要过于在意代码行数。我将用不超过37行代码给你演示他的核心功能,但是要做成一个真正实用的应用,你还需要花更多的时间… 

演示项目

这里,我们将做一个简单的项目演示怎么去做到如下几点:

  • 索引在指定目录(包括子目录)中找到的Html文件
  • 用一个ASP.NET应用程序来搜索索引
  • 搜索结果中高亮显示查询的单词

DotLucene还具有更多的潜力。在实际的应用中你大概想这么去做:

  • 当目录中怎就新文档时添加到索引,而不用重新编译整个索引
  • 包含各种文件类型。DotLuncene能够索引任何能转换成纯文本的文件类型
为什么不使用微软索引服务(Microsoft Indexing Server)?

如果你喜欢用索引服务,没问题。然而,使用DotLucene会有更多好处:

  • DotLucene 是一个100%托管代码的单执行文件,不需要任何依赖
  • 它能被使用到一个共享主机。如果事先准备好索引,你可以不需要磁盘的写权限
  • 使用它,你可以从任何源((数据库、网站…)索引任何类型数据(电子邮件、XML、HTML文件…)。那是因为你需要提供纯文本给索引器(Indexer),载入和解析取决于你
  • 允许你选择要包含在索引中的指定属性("字段"),从而你可以使用这些字段来搜索(例如,作者、日期、关键字等)
  • 它是一个开源软件
  • 它易于扩展
第1行:建立索引

下面的代码从存盘存储建立一个新的索引,directory是存储索引的目录路径参数。

IndexWriter writer = new IndexWriter(directory, new StandardAnalyzer(), true);

这个例子中我们总是重新创建索引(In this example we always create the index from scratch),但这不是必须的,你也可以打开一个已有的索引并添加文档进去。你还可以通过删除然后添加它们的新版本来更新现存的文档(译注:这里应该 是指对象的创建)

第2 – 12行:添加文档

我们为每一个HTML文档添加两个字段到索引:

  • "text" 字段,容纳HTML文件的文本内容(去除了标记),文本数据本身并不会存储在索引中
  • "path" 字段,容纳文件路径,它将会被(索引并)完整的存入索引中
public void AddHtmlDocument(string path)
{
Document doc = new Document();
string rawText;
using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Default))
{
rawText = parseHtml(sr.ReadToEnd());
}
doc.Add(Field.UnStored("text", rawText));
doc.Add(Field.Keyword("path", path));
writer.AddDocument(doc);
}
第13 – 14行:优化并保存索引

添加完文档后,你需要关闭索引器。使用优化将会提高搜索性能。

writer.Optimize();
writer.Close();

第15行:打开索引搜索

在做任何搜索之前,你需要打开索引。directory参数是存储索引的目录路径。

IndexSearcher searcher = new IndexSearcher(directory);
第16 – 27行:搜索

现在,我们解析查询了("text"是默认搜索字段)

Query query = QueryParser.Parse(q, "text", new StandardAnalyzer());
Hits hits = searcher.Search(query);

变量hits是搜索结果文档的集合,我们将通过它来将结果存储到DataTable

DataTable dt = new DataTable();
dt.Columns.Add("path", typeof(string));
dt.Columns.Add("sample", typeof(string));
for (int i = 0; i < hits.Length(); i++)
{
// get the document from index
Document doc = hits.Doc(i);
// get the document filename
// we can't get the text from the index because we didn't store it there
DataRow row = dt.NewRow();
row["path"] = doc.Get("path");
dt.Rows.Add(row);
}
第28 – 37行:高亮Lines 28 – 37: Query Highlighting

我们先创建一个高亮器对象highlighter,并将使用加黑(bold)字体来高亮显示(<B>查询词</B>)。

QueryHighlightExtractor highlighter = new
QueryHighlightExtractor(query, new StandardAnalyzer(), "<B>", "</B>");

通过对结果遍历,我们将载入原文中最相似的部分。

for (int i = 0; i < hits.Length(); i++)
{
// ...
string plainText;
using (StreamReader sr = new StreamReader(doc.Get("filename"),
System.Text.Encoding.Default))
{
plainText = parseHtml(sr.ReadToEnd());
}
row["sample"] = highlighter.GetBestFragments(plainText, 80, 2, "...");
// ...
}
资源

[Lucene]Lucene.Net系列一 ---simple example

mikel阅读(733)

What’s Lucene
Lucene是一个信息检索的函数库(Library),利用它你可以为你的应用加上索引和搜索的功能.

Lucene的使用者不需要深入了解有关全文检索的知识,仅仅学会使用库中的一个类,你就为你的应用实现全文检索的功能.

不过千万别以为Lucene是一个象google那样的搜索引擎,Lucene甚至不是一个应用程序,它仅仅是一个工具,一个Library.你也 可以把它理解为一个将索引,搜索功能封装的很好的一套简单易用的API.利用这套API你可以做很多有关搜索的事情,而且很方便.

What Can Lucene Do

Lucene可以对任何的数据做索引和搜索. Lucene不管数据源是什么格式,只要它能被转化为文字的形式,就可以被Lucene所分析利用.也就是说不管是MS word, Html ,pdf还是其他什么形式的文件只要你可以从中抽取出文字形式的内容就可以被Lucene所用.你就可以用Lucene对它们进行索引以及搜索.

How To Use Lucene — A Simple Example
示例介绍:

为作为输入参数的文件夹下的所有txt类型的文件做索引,做好的索引文件放入index文件夹.

然后在索引的基础上对文件进行全文搜索.

1.       建立索引

IndexWriter writer = new IndexWriter("index"new StandardAnalyzer(), true);
IndexDocs(writer, 
new System.IO.FileInfo(args[0]));               
writer.Optimize();
writer.Close(); 

IndexWriter是对索引进行写操作的一个类,利用它可以创建一个索引对象然后往其中添加文件.需要注意它并不是唯一可以修改索引的类.在索引建好后利用其他类还可以对其进行修改.

构造函数第一个参数是建立的索引所要放的文件夹的名字.第二个参数是一个分析对象,主要用于从文本中抽取那些需要建立索引的内容,把不需要参与建索 引的文本内容去掉.比如去掉一些a the之类的常用词,还有决定是否大小写敏感.不同的选项通过指定不同的分析对象控制.第三个参数用于确定是否覆盖原有索引的.

第二步就是利用这个writer往索引中添加文件.具体后面再说.

第三步进行优化.

第四步关闭writer.

 

下面具体看看第二步:

 

  public static void IndexDirectory(IndexWriter writer, FileInfo file)
         
{
              
if (Directory.Exists(file.FullName))
              
{
                   String[] files 
= Directory.GetFileSystemEntries(file.FullName);
                   
// an IO error could occur
                   if (files != null)
                   
{
                       
for (int i = 0; i < files.Length; i++)
                       
{
                            IndexDirectory(writer, 
new FileInfo(files[i]));  //这里是一个递归
                       }

                   }

              }

              
else if (file.Extension == ".txt")
              
{
                   IndexFile(file, writer);
              }

         }


 

         
private static void IndexFile(FileInfo file, IndexWriter writer)
         
{
              Console.Out.WriteLine(
"adding " + file);
              
try
              
{
                   Document doc 
= new Document();                   
                   doc.Add(Field.Keyword(
"filename", file.FullName));

                   doc.Add(Field.Text(
"contents"new StreamReader(file.FullName)));

                   writer.AddDocument(doc);
              }

              
              
catch (FileNotFoundException fnfe)
              
{
                   
              }

     }


主要就是两个函数一个用于处理文件夹(不是为文件夹建立索引),一个用于真正为文件建立索引.

因此主要集中看一下IndexFile这个方法.首先建立Document对象,然后为Document对象添加一些属性Field.你可以把Document对象看成是虚拟文件,将来将从此获取信息.而Field则看成是描述此虚拟文件的元数据(metadata).

其中Field包括四个类型:

Keywork

该类型的数据将不被分析,而会被索引并保存保存在索引中.
UnIndexed 该类型的数据不会被分析也不会被索引,但是会保存在索引.
UnStored 和UnIndexed刚好相反,被分析被索引,但是不被保存.
Text 和UnStrored类似.如果值的类型为string还会被保存.如果值的类型为Reader就不会被保存和UnStored一样.

 

最后将每一个Document添加到索引当中.

需要注意的是索引不仅可以建立在文件系统上,也可以建立在内存中.

例如

IndexWriter writer = new IndexWriter("index", new StandardAnalyzer(), true);

在第一个参数不是指定文件夹的名字而是使用Directory对象,并使用它的子类RAMDirectory,就可以将索引建立在内存当中.

 

2.       对索引进行搜索

IndexSearcher indexSearcher= new IndexSearcher(indexDir);
Query query 
= QueryParser.Parse(queryString, "contents",new StandardAnalyzer());
Hits hits 
= indexSearcher.Search(query);

第一步利用IndexSearcher打开索引文件用于后面搜索,其中的参数是索引文件的路径.

第二步使用QueryParser将可读性较好的查询语句(比如查询的词lucene ,以及一些高级方式lucene AND .net)转化为Lucene内部使用的查询对象.

第三步执行搜索.并将结果返回到hits集合.需要注意的是Lucene并不是一次将所有的结果放入hits中而是采取一次放一部分的方式.出于空间考虑.

至此,本文演示了如何从一个文件夹下的所有txt文件中查找特定的词。并围绕该个实例介绍了lucene.net的索引的建立以及如何针对索引进行搜索.最后给出源代码供大家学习.