存档

‘挨踢’ 分类的存档

代码优化之殇之SCWS php extension篇

2011年11月28日 wenhui 没有评论

用ab测了下一段scws分词并且入库redis的代码,发现每次请求要花200ms,这个速度实在是弱爆了..

因为一直觉得分词是个工作量极大的工作,所以自然的认为问题处在分词上..

打开scws的phpext的代码,发现scws每次在open的时候都会重新载入分词词库..这是个问题..优化之..将scws的open做成popen(类似mysql_connect和mysql_pconnect的关系),发现速度没有改善.

再次发现scws中phpext获取分词结果scws_get_result的循环是在php中做的.好吧改善之,丢到phpext中用c来做..发现速度依旧没有改善..

最后在代码中到处输出时间..发现悲剧了..发现分词部分用了50ms不到,而入redis库花了150ms..晕..

优化redis入库的php部分..问题解决…

这个问题告诉我们….在发现瓶颈之后,一定得用合理的方式来查找瓶颈的具体位置..而不是靠猜…

分类: 开发, 挨踢 标签:

virtualbox 意外关闭数据丢失

2011年11月23日 wenhui 没有评论

昨晚本本忘带充电器,coding的正high的时候断电了..第二天悲剧的发现..virtualbox中的debian(代码存在这上面).居然数据丢失了…代码杯具的回到了几十分钟前….

分类: 挨踢 标签:

如果我来操盘“西米网”……

2011年10月30日 wenhui 没有评论
原文:http://bbs.paidai.com/topic/65795
《如果我来操盘“西米网”……》

大周日的下午没事做,抻抻脑筋,坚持锻炼胡喷能力。刚好一上派代,发现几篇文章在谈西米网的“暂时歇业”,又刚好看到西米网创始人微博里说:

“……还须关注“每公斤价值高”这一指标。是的,休闲食品毛利没问题(35%),单均没问题(80元),回头率,转化率都没问题,但每公斤价值只有30—40元。……”

我个人感觉,把西米网的失败,归结于“每公斤价值低”,或者如建材老K推导的含义“物流成本占比太高”,是一个奇怪的结论。按照奥卡姆剃刀的逻辑,发明这个词本身就多余,其实赔钱的原因无非两点:一,无法系统性降低成本;二,无法有效提高毛利率。

说通俗点,要么持续扩大规模,依靠规模效应来不断降低成本,以获得未来的利润空间——这是京东、凡客的路。要么,就只能通过价值创新,打差异化,来获得足够高的毛利率,支撑未来更加惨烈的竞争——我个人看法,第一条路只有少数人能走,第二条路才是更多人有可能走通的。

好了,接下来我准备胡喷了。但鉴于之前我喷那篇《也买茶》的文章,有两种跟帖我很蛋疼——其一是准备按照我的胡喷照章执行,嚓!如果您倒闭了可千万别骂我啊……第二种是直接称我在异想天开毫无价值,嗯,对第二种言论我直接回答过了:在任何一个BBS,傻逼都是一种浓度问题。

事实上,我认为我的胡喷,价值在于启发思路。内容肯定不全对,甚至没办法真正去照着做,但一定有其可探讨空间,这种价值在于方向性的拓展。换句话讲,您别盯着“术”的环节跟我死磕较真儿,我其实探讨的是“道”!虽然雕爷经常把小招数聊得天花乱坠,仿佛黄药师的兰花拂穴手,掌来时如落英缤纷,指拂处若春兰葳蕤,上下翻飞闪转腾挪……切,其实我更在乎“小无相功”怎么练!练好了内功,啥招儿不能伤人啊?

我最近真话痨嘿!写个开头,就七百多字……

回题是岸!聊“如果我来操盘西米网”:首先我非常喜欢其定位,办公室女性的休闲小零食,这个人群,是最靠谱的!这个品类,很容易做出差异化——等等,其实,产品本身,什么碧根果、小核桃、牛肉干……口味上质量上,大家都不会相差太多。怎么做出差异化呢?我认为是产品之外的一切:

例如,在办公室吃过零食的都知道,最麻烦的无过于果皮、果壳、和果核了,我上次和壳壳果的壳壳老爹聊天,说,如果你研发一个“灯笼”,就爽死消费者了。灯笼大家见过吧?迷你型的,压扁了时体积就是一片纸,拉开来就是个立体的MINI垃圾筐,可以放在办公桌上,随手吃随手扔,吃完了连灯笼一起扔掉。这种贴心赠品,是否去申请专利还在其次,关键是谁先应用了,谁先收获顾客的忠诚。

说到小贴心,还需要在包裹里,放上2片湿纸巾——成本两毛钱还是三毛钱,我不知道。我就知道,吃前和吃后,洗手很麻烦。如果谁送给我两片消毒湿巾,我一定会觉得这商家太有前途了!

收获了用户的小满意,就可以在价格上做文章了。我必须声明,零食按照一公斤一公斤来标价,简直笨死了!猪饲料才按照公斤来计算……你见过谁在办公室吃零食,一次吃一公斤的?我心目中的零食,都是按照“顿”来标记的。看清楚,不是“吨”……敢情我不谈公斤谈吨啊?又不是喂恐龙……虽说办公室里的MM,肯定是有不少恐龙的说……

又跑题了。

去观察一个MM,每次能吃多少克,你就按照大约的克数封装就OK了。一次刚好能吃完,干净卫生还健康。这时,商机就闪现了:谁说一次非得吃一种口味?我就喜欢,一次零食,五六颗碧根果、七八个山核桃、二十粒开心果、外加一小把葡萄干,最好再配一小捧的开口松子!这时,请各位看官展开你的想象力,跟我一块幻想:盒饭,那种有米饭格、主菜格、配菜格,还有小咸菜格,组合成一个的透明盒子。只需再次MINI化就OK了。

关键在于:这种封装,到底该卖多少钱?什么?每公斤?每你妹啊……每种单品的价格差距很大的,各自重量又给得不同,顾客完全丧失比价能力!我这样封装,比按照公斤的封装,价格高出个30%没人能察觉吧?!

这就好比,传统中国龙井茶,花茶,乌龙茶,你都知道每斤多少钱。但立顿茶,你只知道每一盒,或每喝一次多少钱,你并没计算过立顿茶包所用的一斤散茶叶,是多少钱。

这就叫做“打乱顾客脑海中的比价系统”。

但组合装的意义还不仅仅在于此。因为有了新颖的套餐式包装,我可以卖“功能”了,借由功能阐述,来消灭女人吃零食的“罪恶感”。如同女人买化妆品,经常乱花钱,都是半瓶时就不用了买新的,但女人理直气壮,“为了青春,为了美,这种钱花得天经地义!”

吃零食,女人内心也是有隐隐罪恶感的,不消灭不足以平女愤!刚好有些零食的组合,比如葡萄干里蕴含葡萄多酚,是养颜、抗衰老的。有些含铁量高的小干果,对于办公室电脑辐射,有缓解作用。还有些,比如山核桃、黑芝麻(小昭,说你呢,整天在办公室吃黑芝麻!),对于白领的补脑、乌发,有着无可替代的作用……把这些清晰传达,事实上,不仅仅是多卖些产品,而是做着做着,品牌价值主张,slogan就出来了。

再有,为了提高客单价以及顾客满意度,我一直都认为,应该多发明几种小工具,例如碧根果、山核桃大家都吃过吧?总有些不那么好剥开。如果有一种专用小钳子,咔嚓一下能剥开和不伤果仁,多令人开心啊!还不卖,只是满赠……比如满159元即赠,我想很多人都不自觉会凑够这个钱数。最近大家网上买大闸蟹,价格差不多的情况下,某家满赠送蟹八件,你们说会选哪家?

另外,剥壳小钳子等小工具上,蚀刻上网址,不愁下次顾客不回来继续购买,看,重复购买率也顺便提高了。

说到重复购买率,赠吃小包装,是一百个必须!知道什么零食最好吃?世界上最好吃的就是——吃到一半没有了!意犹未尽才能滴滴香浓,抓耳挠腮才能立即下单,酒喝到微醺才是最想继续往下喝之时,美女把衣服脱到一半才是最性感的状态!(我这都什么比喻啊?!……混乱!)反正,送的试吃装,千万量要恰到好处,刚刚吃出美味,然后……然后吃没啦怎么办?配合代金券啊!配合VIP折扣卡啊,配合包邮策略啊,配合再买再多送额外新奇小干果的试吃装啊……MM们这时候要不再下单,都叫见鬼了!

最后,我要说的是,提高客单价、转化率、连带率、利润率、重复购买率、等等一堆干巴巴的数字,也许靠的是“湿润”——就是对顾客体验的真实理解。所谓创新,也没啥难的,无非就是我曾在内部公司会议上侃的创新三步骤:

1,豌豆公主;2,天马行空;3,再次嫁接。

只要琢磨透顾客真正想要的,能令顾客惊喜满意,我想无论卖点什么都可以赚钱。上面我洋洋洒洒扯的一堆东西,无非“小昭都是浮云”……哈哈。清楚招数背后的逻辑是什么,辅以改善和发挥,离赚钱便不远了。

 

分类: 挨踢, 经营|运维 标签:

[转]【藏】创业心得

2011年10月5日 wenhui 没有评论
来源:http://bbs.paidai.com/topic/62573

第一次做电子商务项目,错误犯了不少,弯路走了不少,学费交了不少。马先生说过:成功的原因成千上万,失败的原因就那么几个。今日发十个感概,作半周年总结:

一、要相信项目,相信自己
连自己做的项目都不相信,要及早回家,留多一分钟都是浪费青春。连自己的能力都不相信,如何能让伙伴信任你?

二、执行力永远是第一位
睡觉想想千百条,早上起来还那样。一个方案执行好了,比十个计划强。创业者要自问,别人做两天的事情,自己一天能否完成?不能的话要自省,连一个好员工都谈不上,莫谈创业。

三、无计划,是瞎子
上个月做了什么?下个月要做什么?为什么要这样做?高级点的员工都要想这个问题,更何况是公司的合伙人。想好了,想清楚了。

四、“说着容易,做起来难啊,不信你来做?”
这是一句话,是一句很多人说的话。创业者,绝不能说这样的话!每位创业者,都要有勇气迎接最困难的挑战。你做的事情,员工也能做,那就让员工做好了。困难的都给伙伴做了,伙伴也就没有跟你合作下去的必要。

五、杜绝条件不成熟论
所有的条件都成熟了,这件事就用不着你来做了。大有大的做法,小有小的做法,聪明的有聪明的做法,笨有笨的做法。创业者就是要创造条件,创造条件的能力越强,创业成功的希望越大。

六、只会抱怨最可怕
抱怨不可怕,只会抱怨最可怕!创业是摸着石头过河,压力、质疑、沮丧、愤怒、消极…时时刻刻会出现。抱怨之余要记住,该是你做的事情,还请你做好,做好之余,还是要尽自己的能力帮助团队成员。最忌本份未做好,吐沫四溅。

七、危机感不足,时间观念不强
温水煮青蛙的故事大家都听过。可是有多少人问过自己,自己现在是不是就在锅里呆着呢?说点狠点的,不见棺材不落泪。

八、投机心理不可取
做事情最忌讳猜测,自认为,想当然。不作准备,不做功课。如此创业和买彩票没什么区别,上头条的都是那千万份之一,被别人的成功蒙蔽了眼睛!

九、认错容易,改错难
说出自己的不足和错误很容易,短则3秒,长则3天。要不断的吸取教训,不断进步,难。心中要有一面镜子,照一照一个月前的你,照一照一年前的你!

十、和谐社会论,中国式虚伪
和谐创业,和气收场。生得和气,死得和谐!一个团队中如果没有人来指出你的缺点,而你看见别人的缺点也无动于衷,等于自杀!引用第一条结语:要及早回家,留多一分钟都是浪费青春。场下是朋友,场上是战友,容不得中国式虚伪。

条条深刻,句句尖锐!文字不残酷,现实更残酷。十条不多,是反省的不多。有自检,亦有牢骚。致己,及网站团队,希望团队及网站能以最出色的面貌迎接下半年的挑战。这是一个最好的时代,也是一个最坏的时代。网站是我们团队的第一个项目,但绝不是我们最后一个项目。有一个人人都能独当一面的团队,比这个网站项目更有价值。

分类: 经营|运维 标签:

[转]创业公司CEO每天应该做的13件事

2011年10月5日 wenhui 没有评论

来源:http://www.36kr.com/p/20382.html

Mr. Jamie说,一般人大概很难想像创业公司 CEO 的工作有多难,你的公司在烧钱,说不定只剩下 6 个月的粮草,你怎么可能不担心?偏偏在团队面前你又必须装作若无其事,一切都在你的掌控之中。

Jason Goldberg 整理了一个列表,列出创业公司CEO每天应该做的13件事,以下是36氪编译版本:

  1. 记住你的“一件事”:你的创业公司在一段时间内只能把一件事做好,明确你的“一件事”,写在墙上,每天重复出现在自己眼中,将“一件事”作为公司例会最高级别的事情,不要让任何事情让你和你的团队分心。
  2. 记住,只有当你的团队优秀时,你才一起优秀:花时间培养你的团队,招聘那些在他们工作上比你曾经做得更棒的人,激励他们,让他们完成他们从来没想过他们能做到的事情,在引导他们去做“一件事”的同时给他们自由,像对待家人那样对待你的同事,创业不容易,让你的团队愿意成为公司一员是能够成功的重要因素,创业公司并不只是一个工作的地方,更是一种生活的方式,作为CEO,你的工作不是把每个人的工作都做了,你的工作是帮助他们把工作做得更好,确保定期给你的主管们反馈,告诉他们你的期望,需要他们改进哪些地方。
  3. 设定风格:每个人 – 你的同事,客户,合作伙伴,投资者,你的Twitter和Facebook关注者 – 都会从你身上得到暗示。从你公司的增值速度,数据,创新,客户服务直到公司文化都会反映出你作为一个CEO的职能,所以,不要做一个粗鲁的混蛋,付出行动,如果你希望人们想到你公司时是按照你想让他们想的那样,你需要付出行动并从个人做起。如果你自己无精打采,你的公司也会,如果你忘记微笑,你的公司也会,如果你缺乏耐心,你的公司也会,如果你不说请和谢谢,你的公司也会,公司高于每个人,但公司是由每个人和每个人的工作风格反映出来的,而你是领导者。
  4. 花至少75%的个人时间在你的产品上:只有当你的产品优秀的时候,你的公司才能优秀,亲自参与管理功能和用户利益,我的观点是CEO必须是首席产品官,作为CEO你必须为屏幕上每一个像素负责,我知道这听起来有点过了但是你的产品是你们所有努力工作对用户的输出,所以它的每个功能都应该反映出你们的目标和目的。
  5. 审视数字:我不是在谈论预算和现金流,而是一些关键指标,每周发一封邮件给你的团队,提炼出那些影响公司业务的关键数据,亲自写这封邮件,写邮件会强迫你自己去挖掘和分析你的数据,真正拥有那些数据,让你的工作能够确保公司的每个人都能专注在那些能给公司带来业务的数字上。
  6. 锻炼:我实在忍不住要强调这一点,让自己每周去至少4次健身房,最好是5-6次,锻炼能给你能力和耐心去解决复杂的问题,作为CEO对身体是很大的挑战,让健身房作为一个使自己头脑清醒和保持快活的一种方式,如果你还没有这么做,我保证去了之后你会震惊的,当你有规律的出去锻炼你会发现生活是多么的容易!离开你的键盘,去健身!
  7. 要求反馈:你猜怎样?你并不像你认为的那样聪明,你会犯错误,去问你的雇员,你的客户,你的合作伙伴等,确保你的管理团队中有一个人敢直言不讳,确保你有一个董事会之外的成员或朋友能够给在公司发展上给你提供建议(例如在融资上,董事会管理上)。
  8. 离开办公室:人们太容易生活躲在键盘后面,生活在收件箱里,离开办公室,去和你真正的客户,合作伙伴,供应商,博主们讨论
  9. 写博客,写微博,阅读,参与CEO论坛:写类似于这篇的文章,分享你学到的经验教训,和你工作的技巧等,不要担心没人看,从网络中获得反馈,阅读Hacker News,看其他创业者和科技极客们在分享什么,利用投资者的网络从其他CEO那里获得建议。
  10. 管理现金:现金是你的生命线,你必须一直清楚你还剩多少现金,能够你维持你多久,什么样的决定会影响你的现金状况,不要等到需要钱的时候才去融资。
  11. 像投资者一样去做:在每周结束的时候,问问你自己下面的问题:我们这周所做的提升了我们的价值么?过去的一周你对时间的投资回报率是多少?如果你连续2周或者一个月内有2周没有一个积极的投资回报率,你可能就在做错误的事情了。
  12. 享受乐趣:这很难,需要很大的精力,确保每一天都是愉快的一天,即使很糟糕的一天也需要一下乐趣,如果你觉得不快乐,你可能在作错误的事情,我最喜欢的一句格言:成熟,但不要长大。
  13. 爱:爱你的公司,爱你的同事,爱你的投资者,爱你的合作伙伴,爱你的供应商,但最重要的是,爱呆在家里等你的人 – 那些支持你让你能够日复一日战斗在最前线的人!

这是我的版本,欢迎提出你的!

来源:图片英文原文,译文有参考Mr. Jamie的文章

 

分类: 经营|运维 标签:

[转]如何提高客户的购买能力

2011年7月19日 wenhui 没有评论

原文:http://www.hieoem.cn/goumainengli/

我所需要的就是你帮我找到我在寻找的东西,并且将我从A点(产品页)带到B点(结账页)。如果你给我指了条明路,我会愿意乖乖的把我的钱给你。因此我的购物之旅到底是容易的还是困难的都是由你决定的。需要一些建议吗?下面有一些想法是可以考虑的:

1、在结账的过程中别强迫我注册。如果我点了结账,这通常表示我做了一个要购买的决定。在我改变主意之前请别挡我的道儿,这样你就能尽快拿到我的钱了。别给我介绍不必要的注册步骤或者是其他会减慢我支付的无用信息。如果你想给我一个注册的选项,请在结账以后吧,这样相信我还是会考虑一下的。
2、记住,谷歌不是你的目标客户–我才是。别为了一味地取悦谷歌,把你的产品描述或者其他内容写得包含一大堆SEO关键词。当然你需要重视SEO,但是产品描述首先要以客户为先的。最终,你也许会在谷歌上得到一个很好的排名,但是顾客无法理解你网站上的内容,你所做的也是没有什么意义的。
3、别在我把某商品加入购物车以后才告诉我它脱销了。如果你早就知道这件东西脱销了,请你在产品页的最前面告诉我好吗?这样我们都不会浪费彼此的时间。
4、你是否有哪个分类栏里是没有任何商品的?能请你关了这些分类栏吗?这样我就不会点到这些分类栏,然后显示给我的只有“没有找到任何商品”的信息。
5、就算在你网站上有很多促销活动和产品,你也没必要把它们全都罗列到你的主页上啊!!请保持你主页干净,把注意力放在一些关键的促销或者商品信息上,这样才能让人信服。如果你主页上有100条以上的链接,你真是太“牛逼”了
6、如果我能知道我什么时候收到货而不只是你什么时候发货,这样就太好不过了。你知道我的邮政编码,你知道UPS和FedEx的送货时间,你知道你们的处理时间,那么你能给我一个明确的日期,让我能够在那天看到它出现在我的门口,而不是我自己在那猜。(以国内的物流来说,有点困难,哈哈哈)
7、如果我把某件商品加入了购物车,在给我看其他我可能感兴趣的建议商品前请先给我看看购物车啊。别给我看什么10个推荐商品之类,这样会减慢了我到达购物车页的速度。我注意力有限,如果我看了太多无用的信息,我可能会离开。
8、如果你在我结账后获得了我的Email地址,请好好利用它!比如,你在我结账后的几天跟进向我询问商品是否顺利抵达,询问我是否有兴趣写一个商品评论,这些都是挺好的。我不介意写一个诚实的评论–你只需询问和提醒我就行了!那对下一点来说就是个很好的继续。
9、如果我写了一个消极的产品评论,请别用一个积极的评论取代了我的评论的那个位置来“缓和”评论。请记住客户写评论本是“没有偏见的”。你这边任何隐藏或者压制消极评论的尝试都是会丢失你忠诚用户的信任的。
10、别等到结账的最后一步才显示我的最终价格包括折扣优惠,税费以及运费。我希望能够在购物车页就得到这些信息,这样在最后的步骤就不会游任何“惊讶”。如果你在购物车页需要我的邮政编码去计算运费,请告知我,我会很乐意提供信息给你的。这就把我带到了下一点–
11、如果我已经告诉了你我的信息如邮政编码,请记住它。别让我在结账的时候重新输入信息。一般来说我都是不会更改这些信息的,但还是给我一个能更改它们的选项以备不时之需。
12、请别因为想把客户服务电话数量降低到最少而去尝试隐藏你的联系信息。如果你有个800号码藏在你网站的某处,请显著的标明它。如果顾客的订单出了问题,他们需要一个简单的方式去联系你。
13、当我在提供我信用卡信息的时候,你真的不需要问我我用的是那种信用卡,因为你可以从我的信用卡号码上得知的。你只需让我确认是不是这个类型的信用卡,我会让你知道是否有问题
14、当你在考虑结账的用户体验时,你能做一些关于验证码的吗?我很高兴知道你是关心我们的安全并想确认我是一个人类。但是为了人类着想,请别让我去识别1有0个元素验证码图像。如果可能的话,尽量保持简单就行了。
15、如果你在你的零售商店里展示了任何AdSense广告,请你能把他们关掉吗?那会给作为顾客的我一个混淆信息。如果你是一个真正的网络零售商,你应该专注在销售产品上,而不是从顾客那里赚一些偶然点击广告的小钱。
以上的几点似乎看起来很明显,但是这看起是十分惊人的甚至是对那些建立了复杂的结账过程的大型网络零售商们也是如此。纵观上面的一些观点,他们之所以惊讶,就是因为他们有一个“复杂的”生意。如果你从用户的观点考虑,他们真的一点也不关心商业体上的复杂性–他们追求的是一个简单而直观的购物体验。

在redis中对不同集合类型进行sort操作的性能粗测

2011年1月21日 wenhui 没有评论

由于考虑到网站运行后期的数据量比较大,使用redis的sort指令来获取查询结果的性能问题(见文章尾部题设1),在系统设计之初就得确定好哪一种集合类型的数据进行sort操作的速度最快.

以下测试均在虚拟机中完成,虚拟机ram为384M

在这里测试的数据类型:list/set/sorted set
测试方法: 对list键lpush 100w条数据 (1~1024*1024的整数)
对set键sadd 100w条数据(1~1024*1024的整数)
对sorted set键zadd 100w条数据(value为1~1024*1024的整数,score与value相同)

使用 sort {$keyname} limit 0 10 来测试sort的大致时间
采用python脚本粗测执行时间的结果为(多次测试的结果求平均值)

list                1.52050209045
set                1.97175097466
sorted set       2.02180504799

对于结果我表示纠结,sorted set反而最慢,预计对于所有的元素都重新进行了sort操作,而没有直接采用已经排好的结果
另:在这个测试之前做了个对1000w条数据的排序,虚拟机中的redis-server直接被block不给我响应了(内存太小)..

题设1:
我们所采用的开发环境为PHP+Redis,采用phpredis扩展作为php连redis的driver
假设我们的数据如下
用一个set(或list或sorted set)储存所有的照片的id(key定位photo:set),然后想提取特定数量的照片的基本信息(采用hash数据类型,假定内容为array(‘name’=>{$photoname},’addtime’=>{$nowtime}),key定为photo:{$photoid})
假设要求获取最新100张照片的名字
如果是set或sorted set,只有一种方式
$r->sort(“photo:set”,array(‘get’=>’name’,'sort’=>’desc’,'limit’=>array(0,10)));
如果是list那就有两种方式
1)$r->sort(“photo:set”,array(‘get’=>’photo:*->name’,'sort’=>’desc’,'limit’=>array(0,10)));
2)$photos = $r->lGetRange(“photo:set”,array(‘limit’=>array(0,100))); //这条速度块
forearch($photos as $photo){ //这里就不快了,这里的pipeline批量执行未测
$r->hGet(“photo:{$}”,”name”);
}
显然list的第二种方式的处理速度比较慢,它有100次请求(第一种只有一次请求),redis的内部处理速度显然快于外部的请求速度.
在这种情况下我们要做的就是对 list的sort方式及set的sort方式进行速度对比.

分类: redis 标签: , , , ,

redis fulltext search egine cn,在github上开项目了

2011年1月12日 wenhui 没有评论

项目地址:https://github.com/frozendeath/redis-fulltext-search-cn

项目目的,用php+scws+redis实现一个中文的全文搜索引擎,替代mysql的fulltext来提高搜索精度和速度

当前实现的功能:
1.搜索结果按时间排序

分类: 开发, 项目 标签:

用redis+swcs实现的简单搜索引擎

2011年1月10日 wenhui 没有评论

在上一篇文章:搜索引擎的多重分词算法及分词词典更新时对索引的重新生成的简单想法 中,我用十分纠结的语言描述了一种基于redis+swcs实现简单搜索引擎的思路,今天就做了一个简单的demo,测试了下搜索的可行性.
悲剧,下面的代码被wordpress过滤的很严重,大家先将就着看,我研究研究

首先是分词及索引:

//以下代码的使用前提是已经安装了scws的php扩展和phpredis扩展
//scws init
$nowtime =time(); //获取当前的系统时间,搜索引擎已内容的发表时间作为搜索结果的排序权重
$cws = scws_new();
$cws->set_charset('utf8'); //注意!!!!redis良好支持utf8!!!!!!gbk编码未测!!!!
$multi = 8;
$cws->set_duality(false); //是否开启二元分词
$cws->set_ignore(true); //是否忽略标点
$cws->set_multi($multi); //设置多元分词模式,8表示将句子拆成单字,返回的分词结果为"正常分词"+"所有单字"
//假设"魔兽争霸"的正常分词结果为"魔兽"和"争霸",它的单字为"魔","兽","争","霸"
//那么将multi设为8的时候的结果就是"魔兽","争霸","魔","兽","争","霸"
//更详细的内容参加scws的文档
//end
$r = Redis();
$r->connect('127.0.0.1');
$r->select(15);//用redis第15号数据库作为测试数据库
$postid = $r->incr("global:nextPostId"); //获取当前数据的id,很redis的写法
$post = $_POST['content'];
$r->set("post:{$postid}",$post); //$post中保存为获取到的内容

//word split and index
$cws->send_text($post);      //将$post中的内容发往scws分词程序
while ($res = $cws->get_result()){    //scws的结果并非一次性返回,而是分多次,若取到的结果为空则表示分词完毕
    foreach ($res as $tmp)
    {
        if ($tmp['len'] == 1 && $tmp['word'] == "\r"){
            continue;
        }elseif ($tmp['len'] == 1 && $tmp['word'] == "\n"){
            continue;
        }else{
            $r->zAdd("index:time:{$tmp['word']}",$nowtime,$postid);  //将分好的词作为索引的key,时间作为权重,$postid作为zset的内容
//在这里我采用zset(sorted sets)来保存索引的内容,方便对搜索结果进行排行
        }
    }
}
$cws->close();
//end

然后是搜索部分:

$r = Redis();  //初始化redis
$r->connect('127.0.0.1');
$r->select(15);

$keyword = $_GET['k'];  //获取搜索的关键字

// scws init
$nowtime = time();
$cws = scws_new();
$cws->set_charset('utf8');
$cws->set_duality(false);
$cws->set_ignore(true);
$cws->set_multi(0);   //这里的0表示,只返回正常的分词结果
//end

//word split and search
$cws->send_text($keyword);   //对关键字进行分词
$keyarray = array();        //用于保存用于查询的key的数组,这么做的原因是phpredis扩展在使用zinter来判断zset的相同内容时所传递的参数为key的数组
while ($res = $cws->get_result()){
    foreach ($res as $tmp)
    {
        if ($tmp['len'] == 1 && $tmp['word'] == "\r"){
            continue;
        }elseif ($tmp['len'] == 1 && $tmp['word'] == "\n"){
            continue;
        }else{
            $keyarray[] = "index:time:{$tmp['word']}";  //将需要查询的key放入数组
        }
    }
}
$cws->close();
$tmpkeyname = "tmpkey:{$nowtime}";  //用于保存zinter命令产生的临时搜索结果列表
//redis的另一个好处就是,你可以很方便的给搜索结果做缓存
$r->zInter($tmpkeyname ,$keyarray);  //获取搜索结果
//这里我们还是以"魔兽争霸"做例子,"魔兽争霸"被分词为"魔兽"和"争霸"
//那么在$keyarray中保存的内容就应该是 array("index:time:魔兽","index:time:争霸")
//zInter所返回的结果,就是post内容中既包含"魔兽",又包含"争霸"的$postid号,继续看下面
$data = $r->sort($tmpkeyname,array('get'=>"post:*"));//通过sort指令对$tmpkeyname中的$postid数据按score(这里是时间)排序
//并根据排序结果get到post的内容 参见redis 的sort指令
foreach($data as $d){   //输出结果
  echo "{$d}";
}

$r->delete($tmpkeyname );   //删除临时搜索结果,此例子没有用到缓存
//end

此代码仅仅实现了一个很简单的索引,和搜索功能,不过值得惊叹的是,就这么几十行代码就能实现一个简单的搜索引擎.
文章写的不是很清楚,各位看官有什么不清楚的地方可以跟我留言交流.谢谢:-)

搜索引擎的多重分词算法及分词词典更新时对索引的重新生成的简单想法

2011年1月9日 wenhui 没有评论

由于最近的项目中需要用到搜索引擎,由于之前采用的是mysql数据库,而且在对索引没什么要求的情况下,就直接采用的mysql的fulltext索引.

不过最近开始考虑到尝试新技术和对系统性能的担心,在系统中引入redis(一个性能及功能都十分强劲的NoSQL数据库),来承担一部分比较适合NoSQL数据库做的工作,如排行榜/关注列表等.

恰恰不小心看到redis的一个做搜索引擎的非常简单的思路(英文索引,参考:http://playnice.ly/blog/2010/05/05/a-fast-fuzzy-full-text-index-using-redis/),便留意起了在redis上实现一套简单的中文搜索引擎.

说道做搜索引擎就不得不提到两点十分关键的内容:一是分词,就是将一个句子拆成不同的词和字;二是索引(及排行),用于快速的定位到需要的内容.

在这里主要讲下我对分词和简单索引建立的一点思路:

分词方面
分词有现成的工具可以用 scws,一个中文分词系统,可以作为php扩展,自带的词库就有28W词量,准确率高达95%.
不过分词有一个很大的不确定性,比如说”魔兽争霸”这个词,它可以作为一个单独的词表示一款游戏,但是很多人把它直接简称为”魔兽”,这就导致了在分词的时候,必须将”魔兽争霸”分为不同的单词组合如(“魔兽争霸”)和(“魔兽”,”争霸”)这两种可能,而这这就意味着必须进行两次分词,来保证搜索结果的准确性.感谢scws的作者hightman,他已经实现了不同级别的分词算法,我们用起来就简单很多了.

索引重新建立方面
比如我之前不知道有”魔兽争霸”这么个词,然后很利索地把它给拆成了”魔兽”和”争霸”,于是乎我搜”魔兽争霸”的结果很有可能是”魔兽们平时都以争霸为乐趣”,这显然有点不靠谱.因此当我知道一个新的词的时候,需要对原有的索引进行一次重构,将原先即包含”魔兽”也包含”争霸”的句子提取出来,判断是否包含词组”魔兽争霸”,然后丢到索引”魔兽争霸”里面.

代码见这里:用redis+swcs实现的简单搜索引擎