上周開(kāi)發(fā)了一個(gè)磁力鏈接和 BT 種子的搜索引擎 {Magnet & Torrent},本文簡(jiǎn)單介紹一下主要的系統(tǒng)功能和用到的技術(shù)。
系統(tǒng)包括幾個(gè)獨(dú)立的部分:
使用 Python 的 Scrapy 框架開(kāi)發(fā)的網(wǎng)絡(luò)爬蟲(chóng),用來(lái)爬取磁力鏈接和種子;
使用 PHP CI 框架開(kāi)發(fā)的簡(jiǎn)易網(wǎng)站;
搜索引擎目前直接使用的 MySQL,將來(lái)可以考慮使用 sphinx;
-
中文分詞。
用 PHP 寫(xiě)了一個(gè)簡(jiǎn)陋版的基于逆向最大匹配算法的小類(lèi),詞庫(kù)呢,哈哈,直接使用了 Chrome 的分詞表,分詞表可以在這個(gè)地址下載:http://www.mdbg.net/chindict/chindict.php?page=cedict。
-
新詞發(fā)現(xiàn)機(jī)制
基于搜索關(guān)鍵詞的新詞發(fā)現(xiàn)機(jī)制。
目前詞庫(kù)方面還有一個(gè)很大的問(wèn)題,比如最新的電影無(wú)法分詞,例如星際穿越 會(huì)被分詞為“星際”和“穿越”,因此“被偷走的那五年,穿越火線(xiàn),極速蝸牛,了不起的蓋茨比,摩登年代,星際迷航,喬布斯傳。”也出現(xiàn)在了搜索結(jié)果中。
當(dāng)然這也不算事大問(wèn)題,但是霍比特人卻被分詞為了“霍”、“比特”、“人”了,好在搜索結(jié)果里面沒(méi)有啥東西亂入。這些屬于過(guò)度分詞,通過(guò)增加詞庫(kù)內(nèi)容可以解決,因此準(zhǔn)備些一個(gè)豆瓣爬蟲(chóng),將豆瓣的所有電影都加入詞庫(kù),用來(lái)輔助分詞。
-
資源別名
這會(huì)使我們的系統(tǒng)更加智能,更加人性化。我們?cè)诎俣人阉鲿r(shí),經(jīng)常會(huì)遇到這樣的情況,當(dāng)我們搜索“開(kāi)核桃利器”,百度提示我們“您要找的是不是諾基亞?”。當(dāng)我們搜索“世界上最好的語(yǔ)言”,百度提示我們“您要找的是不是PHP?”。同樣,當(dāng)用戶(hù)搜索“星際穿越”時(shí),應(yīng)該為用戶(hù)提供Interstellar的匹配結(jié)果。
我們不用實(shí)現(xiàn)復(fù)雜的在線(xiàn)翻譯,只需要繼續(xù)爬取豆瓣,將電影的中英文都做成對(duì)照表就可以了。而且,為了考慮到某些宅男的特殊需求,我們還需要做一個(gè)日語(yǔ)的對(duì)照表。
-
英文分詞
英文還需要分詞?空格不就是詞語(yǔ)邊界嗎?你有這樣的譯文很正常,我最初也是這么想的,因此英文只是簡(jiǎn)單的使用了 PHP 的
explode(' ', $query)
函數(shù)。但是我剛才(2015-02-01 21:59:35)看搜索日志時(shí)發(fā)現(xiàn)了一些問(wèn)題,今天 xart 關(guān)鍵詞被搜索了 169 次,而 x-art 關(guān)鍵詞僅僅被搜索了 54 次,但是 x-art 才是它的官方名詞啊(不要問(wèn)我為什么知道的這么多)。因此我剛剛調(diào)整了一下代碼,將 xart 和 x-art 統(tǒng)一定向到了 x-art。
BitTorrent 低版本最初使用 Python 開(kāi)發(fā),而且是開(kāi)源的,因此很多類(lèi)庫(kù)都是直接使用的 BitTorrent 的,也有一些類(lèi)庫(kù)和輔助函數(shù)直接移植到了 PHP 平臺(tái)上;(Petru Paler 寫(xiě)的 bencode 太贊了,老婆問(wèn)我:你為什么跪著寫(xiě)代碼?)
了解 P2P 原理的人都知道,BT 不需要中心服務(wù)器,因?yàn)槊總€(gè)節(jié)點(diǎn)既是客戶(hù)端,同時(shí)也是服務(wù)器,因此基于 0x0d 大神的 dhtfck 寫(xiě)了一個(gè) DHT 爬蟲(chóng),它偽裝為 DHT 網(wǎng)絡(luò)中的一個(gè)節(jié)點(diǎn),這樣當(dāng)其他客戶(hù)端想下載某個(gè) torrent 時(shí),就會(huì)在 DHT 網(wǎng)絡(luò)發(fā)起廣播,當(dāng)它詢(xún)問(wèn)到我的節(jié)點(diǎn)時(shí),我就知道了:哦,原來(lái)有人要下載這個(gè)種子啊,那么在 DHT 網(wǎng)絡(luò)中肯定有這個(gè)種子。于是我把這個(gè)種子的信息保存到 MySQL 中。
以上 DHT 的整個(gè)過(guò)程可以具體看看 DHT 協(xié)議。
注意:我只是保存了 torrent 的 infohash 信息,用這個(gè)信息,可以構(gòu)建一個(gè)磁力鏈接,但是卻還沒(méi)有得到種子文件,我們還得通過(guò)其它方式取得種子文件。
Python 的爬蟲(chóng)程序是主動(dòng)出擊,盲目尋找。在互聯(lián)網(wǎng)的海量網(wǎng)頁(yè)中尋找種子和磁力鏈接。而 DHT 爬蟲(chóng)則變成了被動(dòng)等待,當(dāng)別人來(lái)詢(xún)問(wèn)時(shí),就把它的詢(xún)問(wèn)結(jié)果記錄下來(lái),如果一個(gè)種子被詢(xún)問(wèn)了很多次,則說(shuō)明這個(gè)種子是一個(gè)熱門(mén)種子,這是 Python 爬蟲(chóng)無(wú)法做到的。
由于 BitTorrent 開(kāi)源版本使用的 Python,因此我的 DHT 爬蟲(chóng)也使用了 Python。作為一個(gè)服務(wù)器,肯定要使用 twisted 框架,熟悉 nodejs 的同學(xué)一定知道這個(gè)框架的特性:異步網(wǎng)絡(luò) IO,雖然大部分開(kāi)發(fā)者都是通過(guò) nodejs 才了解了異步 IO,但是 twisted 要比 nodejs 早了 N 年。
當(dāng)前運(yùn)行的爬蟲(chóng)是一個(gè)非常簡(jiǎn)陋的版本,是我一周前寫(xiě)的一個(gè)多線(xiàn)程的基于 Socket 的 DHT 服務(wù)器。截至到寫(xiě)這篇文章時(shí),已經(jīng)運(yùn)行了 6 天了,總共收集到了 45,234,859 個(gè)磁力鏈接。