手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第二十一天,教你做第二十一天_PHP教程

來源:互聯網
上載者:User

手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第二十一天,教你做第二十一天


客串:屌絲的坑人表單神器、資料庫那點事兒

物件導向升華:物件導向的認識----新生的初識、物件導向的番外----思想的夢遊篇(1)、物件導向的認識---如何找出類

負載平衡:負載平衡----概念認識篇、負載平衡----實現配置篇(Nginx)

吐槽:現在欠的文章有物件導向的認識----類的轉化、物件導向的番外---思想的夢遊篇(2)、負載平衡 ---- 檔案服務策略、手把手教你做關鍵詞匹配項目(搜尋引擎)。真心太多了,能不能讓我休息一會兒。

第二十一天

起點:手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第一天

回顧:手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第二十天

今天有個理論知識要理解的,叫做測試驅動編程,之前我提到過概念,在:手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第十一天

今天小帥帥秀逗了一回,使用了這個思想。

好了,以下本文開始。

話說小帥帥把自己寫的業務拆詞方法給了於老大看,於老大很高興。

但是業務拆詞的片語都是有限的,還有就是當業務拆詞的資料量越來越大的時候,就會造成運算時間增加。

於老大就提到,是否可以用其它分詞擴充來彌補拆詞的不足。

畢竟人家專業人士做的,比較靠譜點。

於老大很有經驗,就推薦小帥帥去瞭解SCWS的用法.

SCWS 是 Simple Chinese Word Segmentation 的首字母縮寫(即:簡易中文分詞系統)。
官方網址:http://www.xunsearch.com/scws/index.php

小帥帥聽了當然很開心羅,因為又有新的知識點了。

小帥帥照著SCWS的安裝文檔安裝了SCWS。

並把php擴充裝好了,並嘗試寫了個測試代碼:

phpclass TestSCWS {    public static function split($keyword){        if (!extension_loaded("scws")) {            throw new Exception("scws extension load fail");        }        $so = scws_new();        $so->set_charset('utf8');        $so->send_text($keyword);        $ret = array();        while ($res = $so->get_result()) {            foreach ($res as $tmp) {                if (self::isValidate($tmp)) {                    $ret[] = $tmp;                }            }        }        $so->close();        return $ret;    }    public static function isValidate($scws_words)    {        if ($scws_words['len'] == 1 && ($scws_words['word'] == "\r" || $scws_words['word'] == "\n")) {            return false;        }        return true;    }}var_dump(TestSCWS::split("連衣裙xxl裙連衣裙"));

測試通過,跟理想中的一摸一樣,小帥帥很高興,就去問於老大:於老大我會用SCWS了,下一步該怎麼辦?

於老大也不慌,就對小帥帥說: 你先寫個ScwsSplitter來拆分關鍵詞吧。

小帥帥非常高興,因為他學到了新的知識,就對於老大說到好的。

小帥帥說到做到,代碼如下:

class ScwsSplitter {    public $keyword;        public function split(){        if (!extension_loaded("scws")) {            throw new Exception("scws extension load fail");        }        $keywordEntity = new KeywordEntity($this->keyword);        $so = scws_new();        $so->set_charset('utf8');        $so->send_text($this->keyword);               while ($res = $so->get_result()) {            foreach ($res as $tmp) {                if ($this->isValidate($tmp)) {                    $keywordEntity->addElement($tmp["word"]);                }            }        }        $so->close();        return $keywordEntity;    }    public function isValidate($scws_words)    {        if ($scws_words['len'] == 1 && ($scws_words['word'] == "\r" || $scws_words['word'] == "\n")) {            return false;        }        return true;    }    }

小帥帥又跑去找於老大,說到:我把Scws的分詞代碼寫好了。

於老大也佩服小帥帥的高效率。

又說到:如果我兩個同時用了,我先用業務分詞,遺留下來的詞用Scws分詞,小帥帥有好的方案嗎?

小帥帥就問到: 為啥要這樣,這不是多此一舉。

於老大就說到:業務有些專有名詞,SCWS分不出來丫,那怎麼辦好?

小帥帥又說到:我看文檔的時候看到有詞庫和規則檔案的設定,我們用它好不好?

於老大又說到:這個是可以,但是我們如何保證讓運營人員維護,我們要學會把這些事情交出去丫。

小帥帥: …….

小帥帥沉默了片刻,覺得現在兩個類都寫了,一起用是最快的方案,就答應到:好吧,我回去改改….

首先小帥帥根據測試驅動編程的思想寫了入口代碼:

class SplitterApp {    public static function split($keyword,$cid){        $keywordEntity = new KeywordEntity($keyword);        #業務分詞        $termSplitter = new TermSplitter($keywordEntity);        $seg = new DBSegmentation();        $seg->cid = $cid;        $termSplitter->setDictionary($seg->transferDictionary());        $termSplitter->split();        #SCWS分詞        $scwsSplitter = new ScwsSplitter($keywordEntity);        $scwsSplitter->split();        #後續遺留單詞或者片語處理        $elementWords = $keywordEntity->getElementWords();        $remainKeyword = str_replace($elementWords, "::", $keywordEntity->keyword);        $remainElements = explode("::", $remainKeyword);        foreach($remainElements as $element){            if(!empty($element))                $keywordEntity->addElement($element);        }
     return $keywordEntity; }}

小帥帥嘿了一聲,有了測試入口,還怕其他的搞不定。

首先KeywordEntity的getElementWords,先搞定他.

class KeywordEntity{    public $keyword;    public $elements = array();    public function __construct($keyword)    {        $this->keyword = $keyword;    }    public function addElement($word, $times = 1)    {        if (isset($this->elements[$word])) {            $this->elements[$word]->times += $times;        } else            $this->elements[$word] = new KeywordElement($word, $times);    }    public function getElementWords()    {        $elementWords = array_keys($this->elements);        usort($elementWords, function ($a, $b) {            return (UTF8::length($a) < UTF8::length($b)) ? 1 : -1;        });        return $elementWords;    }    /**     * @desc 計算UTF8字串權重     * @param string $word     * @return float     */    public function calculateWeight($word)    {        $element = $this->elements[$word];        return ROUND(strlen($element->word) * $element->times / strlen($this->keyword), 3);    }}class KeywordElement{    public $word;    public $times;    public function __construct($word, $times)    {        $this->word = $word;        $this->times = $times;    }}

其次就是分詞了,首先先抽出公用類先,Splitter變成了公用類,有哪些方法呢?

  1. 抽象split方法

2. 擷取關鍵詞待拆分的片語

3. 是否需要拆分

按照這寫,小帥帥寫出了以下代碼:

abstract class Splitter {    /**     * @var KeywordEntity $keywordEntity     */    public $keywordEntity;    public function __construct($keywordEntity){        $this->keywordEntity = $keywordEntity;    }    public abstract function split();    /**     * 擷取未分割的字串,過濾單詞     *     * @return array     */    public function getRemainKeywords()    {        $elementWords = $this->keywordEntity->getElementWords();        $remainKeyword = str_replace($elementWords, "::", $this->keywordEntity->keyword);        $remainElements = explode("::", $remainKeyword);        $ret = array();        foreach ($remainElements as $element) {            if ($this->isSplit($element)) {                $ret[] = $element;            }        }        return $ret;    }    /**     * 是否需要拆分     *     * @param $element     * @return bool     */    public function isSplit($element)    {        if (UTF8::isPhrase($element)) {            return true;        }        return false;    }}

然後小帥帥繼續實現業務拆分演算法,以及Scws拆分演算法。小帥帥淫笑了,這點小事情還是可以辦到的。

class TermSplitter extends Splitter {    private $dictionary = array();    public function setDictionary($dictionary = array())    {        usort($dictionary, function ($a, $b) {            return (UTF8::length($a) < UTF8::length($b)) ? 1 : -1;        });        $this->dictionary = $dictionary;    }    public function getDictionary()    {        return $this->dictionary;    }    /**     * 把關鍵詞拆分成片語或者單詞     *     * @return KeywordScore[] $keywordScores     */    public function split()    {        foreach ($this->dictionary as $phrase) {            $remainKeyword = implode("::",$this->getRemainKeywords());            $matchTimes = preg_match_all("/$phrase/", $remainKeyword, $matches);            if ($matchTimes > 0) {                $this->keywordEntity->addElement($phrase, $matchTimes);            }        }    }}class ScwsSplitter extends Splitter{    public function split()    {        if (!extension_loaded("scws")) {            throw new Exception("scws extension load fail");        }        $remainElements = $this->getRemainKeywords();        foreach ($remainElements as $element) {            $so = scws_new();            $so->set_charset('utf8');            $so->send_text($element);            while ($res = $so->get_result()) {                foreach ($res as $tmp) {                    if ($this->isValidate($tmp)) {                        $this->keywordEntity->addElement($tmp['word']);                    }                }            }            $so->close();        }    }    /**     * @param array $scws_words     * @return bool     */    public function isValidate($scws_words)    {        if ($scws_words['len'] == 1 && ($scws_words['word'] == "\r" || $scws_words['word'] == "\n")) {            return false;        }        return true;    }}

小帥帥終於把這些代碼全部搞定了,高興之餘,他還順手畫了UML圖送給大家:

小帥帥的成長真心夠厲害的哦,於老大看後,連稱讚了三次。

為了測試,小帥帥寫了測試代碼,代碼如下:

class SplitterAppTest {    public static function split($keyword){        $keywordEntity = new KeywordEntity($keyword);        #業務分詞        $termSplitter = new TermSplitter($keywordEntity);        $seg = new TestSegmentation();        $termSplitter->setDictionary($seg->transferDictionary());        $termSplitter->split();        #SCWS分詞        $scwsSplitter = new ScwsSplitter($keywordEntity);        $scwsSplitter->split();        #後續遺留單詞或者片語處理        $elementWords = $keywordEntity->getElementWords();        $remainKeyword = str_replace($elementWords, "::", $keywordEntity->keyword);        $remainElements = explode("::", $remainKeyword);        foreach($remainElements as $element){            if(!empty($element))                $keywordEntity->addElement($element);        }       return $keywordEntity;    }}SplitterAppTest::split("連衣裙xl裙寬衣裙");

小帥帥意淫著,想到總有一天把你們踩在腳下。


手把手教你做,很適合上班族與學生想發大財的就不要來了,賺個話費

  每個人一生中都擁有一副好牌,可惜的是許多人都把它浪費了,手上握有一副富人的牌,卻把自己打成了一個窮人。
  許多人心靈上都沾滿了消極的灰塵,失望的汙泥和貧窮落後的思想,甚至還怨恨的種子,這樣你就永遠不會快樂和富有的。窮人:致富和做生意到底有沒有什麼秘訣?
  富人:每件事情都 有它不同的內在規律,所謂的秘訣實際上就只是那麼一點點東西。
  九十九度加一度,水就開了。開水與溫水的區別是這麼一度。有些事情之所以會有天壤之別,往往就是因為這微不足道的一度。我在報上看到這麼一件事。
  兩個下崗女工,各在路邊開了一個早點鋪,都賣包子和油茶。一個生意逐漸興旺,一個30天后收了攤,據說原因是一個雞蛋的問題。
  生意逐漸興旺的那家,每當顧客到來時,總是問在油茶裡打一個雞蛋還是兩個雞蛋;垮掉的那一家問的是要不要。兩種不同的問法總能使第一家賣出較多的雞蛋。雞蛋賣出得多,盈利就大,就付得起各項費用,生意也就做了下去。雞蛋賣得少的,盈利少,去掉費用不賺錢,攤子只好收合。成功與失敗之間僅一個雞蛋的區別。
  名滿天下的可口可樂中,百分之九十九的是水、糖、碳酸和*,世界上一切飲料的構成也大概如此。然而在可口可樂中有1%的東西是其他絕對有的,據說就是這個神秘的1%,使它每年有4億多美的純利潤,而其他品牌的飲料,每年有8000萬美的收入就算滿意了。
  在這世界上成與敗之間的距離就這麼一點點,所謂秘訣也就這一點點,但就這一點點東西是最寶貴的,許多人要用多次的失敗才換回它,然後走向成功。窮人:如果知道了某種生意的秘訣,然後從事這個項目就容易成功嗎?
  富人:各種生意都有自己的小秘密,誰也不會把這小秘密告訴別人,因為有的是不能擺到案頭上的,另外也怕被別人學走了,他們都把它列入了祖傳秘方。那個診所的朋友,他告訴我,一個診所要賺錢,原則上:一要便宜,二要有效。但你如果死照這原則做,是不了錢的。既然便宜你收費就不能貴,有效話,病一次就看好了,這樣賺的錢除了打點主管部門、房租、員工工資,以及七七八八的社會各種收費所剩無幾了……不如剩早關門。你要從事什麼行業,你就要先去跟從事這行業的人做朋友或先到他那裡做僱員最好同,用心就能學到這個祖傳秘方。這比自己損失了不少時間在實踐中慢慢摸索要合算得多。
  小老闆做事,中老闆做市,大老闆做勢!
  我們許多人用體力賺錢,不少人用技術賺錢,很少人用知識賺錢,極少人是用智慧賺錢的。在財富時代,智慧的人太少太少,有智慧又能抓住商機的人更是鳳毛麟角。只要我們開動腦筋,發揮智慧,就可以把握機會,成為財富的主人。
 

手把手教你做兼職,很適合上班族與學生想發大財的就不要來了,賺個話費

???
 

http://www.bkjia.com/PHPjc/874526.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/874526.htmlTechArticle手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第二十一天,教你做第二十一天 客串:屌絲的坑人表單神器、資料庫那點事兒 物件導向升華...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.