青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

學著站在巨人的肩膀上

金融數學,InformationSearch,Compiler,OS,

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  12 隨筆 :: 0 文章 :: 8 評論 :: 0 Trackbacks

2010年3月15日 #

這里做個記錄,[分布式跨平臺監控系統]肯定離不開的要配置windows下的環境,linux的一鍵安裝程序有apt,zyyper,yum等傻瓜工具,windows下有時候還成了問題。

1,將windows版python2.5裝入d:/python25,將d:/python25添加入環境變量path

2,下載下django,在django目錄里運行,python setup.py install ,會自動查找path環境變量,將django的庫放入d:/python25/lib

3,裝一個setuptools-0.6c11.win32-py2.5.rar,會在 D:\Python25\Scripts 中出現 easy_install.exe

4,裝mysql api和memcahe api,在D:\Python25\Scripts 目錄下運行 easy_install.exe install mysqldb,或easy_install.exe install memcahe提示要去 http://pypi.python.org/simple/ 找具體下載安裝的包,打開網址找到相應的url然后 easy_install.exe install url即可

5,如果沒有自動安裝程序 setuptools-0.6c11.win32-py2.5 或裝不了,可以直接復制以前 D:\Python25\Lib\site-packages下的 MySQLdb 文件夾到 現在的D:\Python25\Lib\site-packages的目錄下,只要版本對得上就可以正常運行,完全綠色的。

6,如果url安裝不了,以前也沒有用過,可以下載安裝包,例如memcache的api安裝可以去這里ftp://ftp.tummy.com/pub/python-memcached/old-releases/python-memcached-1.45.tar.gz 下載

然后解壓進入目錄執行python setup.py install

7,建立新的django項目或在以往的工程目錄下運行 python manage.py syncdb (這里只會檢測庫中的表,沒有表明就建立,如果有表明,結構被改變了是不會做任何修改的),同步數據庫表結構,事先要在mysql里建立setting.py里設置的數據庫。

posted @ 2010-03-15 19:25 學者站在巨人的肩膀上 閱讀(661) | 評論 (0)編輯 收藏

前一陣花了點時間學習python,近段時間完成了一個監控服務器基本信息的項目,都是為了滿足大家監控的欲望,特殊日志并報警的分布式系統,單臺服務器采集粒度為1次/1分鐘,一天大約1440條,目前監控了20多臺服務器,一天大約31680條日志,現在單點監控中心服務器在性能上還綽綽有余,有更多的服務器來測試就好了,估計可以支持到100臺以上服務器監控的級別。

現在遇到一個需求是發現報警時實時發送消息給相關人員,由于公司短信網關只買了上海電信用戶沒有上海電信的號碼,汗一個,只好通過發郵件來實施。

支持發送GB18030編碼的文本內容,任意編碼附件,可以做出適當修改支持群發。

 

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. #coding=utf-8   
  2. #!/usr/lib/python2.5/bin/python   
  3. import os   
  4. import sys   
  5. from smtplib import SMTP   
  6. from email.MIMEMultipart import MIMEMultipart   
  7. from email.mime.application import MIMEApplication   
  8. from email.MIMEText import MIMEText   
  9. from email.MIMEBase import MIMEBase   
  10. from email import Utils,Encoders   
  11. import mimetypes   
  12. import time   
  13.   
  14. STMP_SERVER = "mail.×××.com"  
  15. STMP_PORT = "25"  
  16. USERNAME = "×××@×××.com"  
  17. USERPASSWORD = "×××"  
  18. FROM = "MonitorCenterWarning@×××.com"  
  19. TO = "×××@gmail.com"  
  20.   
  21. def sendFildByMail(config):   
  22.     print 'Preparing...'  
  23.     message = MIMEMultipart( )   
  24.     message['from'] = config['from']   
  25.     message['to'] = config['to']   
  26.     message['Reply-To'] = config['from']   
  27.     message['Subject'] = config['subject']   
  28.     message['Date'] = time.ctime(time.time())   
  29.     message['X-Priority'] =  '3'  
  30.     message['X-MSMail-Priority'] =  'Normal'  
  31.     message['X-Mailer'] =  'Microsoft Outlook Express 6.00.2900.2180'  
  32.     message['X-MimeOLE'] =  'Produced By Microsoft MimeOLE V6.00.2900.2180'  
  33.        
  34.     if 'file' in config:   
  35.         #添加附件   
  36.         f=open(config['file'], 'rb')   
  37.         file = MIMEApplication(f.read())   
  38.         f.close()   
  39.         file.add_header('Content-Disposition''attachment', filename= os.path.basename(config['file']))   
  40.         message.attach(file)   
  41.        
  42.     if 'content' in config:   
  43.         #添加文本內容   
  44.         f=open(config['content'], 'rb')   
  45.         f.seek(0)   
  46.         content = f.read()   
  47.         body = MIMEText(content, 'base64''gb2312')   
  48.         message.attach(body)   
  49.   
  50.     print 'OKay'  
  51.     print 'Logging...'  
  52.     smtp = SMTP(config['server'], config['port'])   
  53.     #如果SMTP服務器發郵件時不需要驗證登錄則對下面這行加上注釋   
  54.     smtp.login(config['username'], config['password'])   
  55.     print 'OK'  
  56.        
  57.     print 'Sending...',   
  58.     smtp.sendmail (config['from'], [config['from'], config['to']], message.as_string())   
  59.     print 'OK'  
  60.     smtp.close()   
  61.     time.sleep(1)   
  62.   
  63. if __name__ == "__main__":   
  64.     if len(sys.argv) < 2:   
  65.         print 'Usage: python %s contentfilename' % os.path.basename(sys.argv[0])   
  66.         print 'OR Usage: python %s contentfilename attachfilename' % os.path.basename(sys.argv[0])   
  67.         wait=raw_input("quit.")   
  68.         sys.exit(-1)   
  69.     elif len(sys.argv) == 2:   
  70.         sendFildByMail({   
  71.             'from': FROM,   
  72.             'to': TO,   
  73.             'subject''[MonitorCenter]Send Msg %s' % sys.argv[1],   
  74.             'content': sys.argv[1],   
  75.             'server': STMP_SERVER,   
  76.             'port': STMP_PORT,   
  77.             'username': USERNAME,   
  78.             'password': USERPASSWORD})   
  79.     elif len(sys.argv) == 3:   
  80.         sendFildByMail({   
  81.             'from': FROM,   
  82.             'to': TO,   
  83.             'subject''[MonitorCenter]Send Msg and File %s %s' % (sys.argv[1], sys.argv[2]),   
  84.             'content': sys.argv[1],   
  85.             'file': sys.argv[2],   
  86.             'server': STMP_SERVER,   
  87.             'port': STMP_PORT,   
  88.             'username': USERNAME,   
  89.             'password': USERPASSWORD})   
  90.     wait=raw_input("end.")  

 

windows xp下:

例子

 linux ubuntu,suse下:

1

收到的結果:

2

posted @ 2010-03-15 19:24 學者站在巨人的肩膀上 閱讀(677) | 評論 (0)編輯 收藏

由于上證所,深交所level1,level2金融數據服務器在上午9:00開始到11:30和下午13:00開始到15:30一共大約5個小時的時間內流量比較大所以被監控服務器的網絡流速算是一個被監控的重要指標??梢酝ㄟ^累加一段時間內各個網卡的上行,下行流量除以這個時間間隔計算出這段時間內的平均網速,我現在的采集頻率是1分鐘采集一次,在實際開盤期間運行過程中得到的網速監控信息用還是比較準確的,都保持在5M/S左右的速度,有時候在平時非服務期看見某臺服務器的內網網卡網速達到5M/S ,果然就是有人在大手筆傳輸。

獨立的監控腳本是返回一個列表嵌套元組的數據結構,最后再匯總成一個完整的XML數據島,為了調試方便腳本的每一個中間結果都導出到一個臨時文本中。

運行以下腳本要確定你的linux裝了ethtool工具,在ubuntu2.6.27-7-server,ubuntu22.6.27.19-5-default,suse 2.6.27.19-5-default 測試通過。

代碼:

 

  1. #coding=utf-8   
  2. #!/usr/bin/python   
  3. import re   
  4. import os   
  5. import time   
  6.   
  7. import utils   
  8. def sortedDictValues3(adict):   
  9.     keys = adict.keys()   
  10.     keys.sort()   
  11.     return map(adict.get, keys)   
  12.   
  13. def run():   
  14.     if utils.isLinux() == False:   
  15.         return [('ifconfig_collect os type error','this is windows')]   
  16.     #not first run   
  17.     if os.path.isfile('./oldifconfig'):   
  18.         fileold = open('./oldifconfig''r')   
  19.         fileold.seek(0)   
  20.         #讀入上次記錄的臨時流量數據文件,和時間戳   
  21.         (oldtime, fileoldcontent) = fileold.read().split('#')   
  22.         fileold.close;   
  23.         netcard = {}   
  24.         tempstr = ''  
  25.         key = ''  
  26.         for strline in fileoldcontent.split('\n'):   
  27.             reobj = re.compile('^lo*.')   
  28.             if reobj.search(strline):   
  29.                 break;   
  30.             reobj = re.compile('^eth*.')   
  31.             if reobj.search(strline):   
  32.                 key = strline.split()[0]   
  33.             tempstr = tempstr + strline + '\n'  
  34.             netcard[key] = tempstr   
  35.         RXold = {}   
  36.         TXold = {}   
  37.         for key,value in netcard.items():   
  38.             tempsplit = value.split('\n')   
  39.             netcard[key] = ''  
  40.             for item in tempsplit:   
  41.                 item = item + '<br>'  
  42.                 netcard[key] = netcard[key] + item   
  43.                 tempcount = 1  
  44.                 for match in re.finditer("(bytes:)(.*?)( \()", item):   
  45.                     if tempcount == 1:   
  46.                         RXold[key] = match.group(2)   
  47.                         tempcount = tempcount + 1  
  48.                     elif tempcount == 2:   
  49.                         TXold[key] = match.group(2)   
  50.                         netcard[key] = netcard[key] + 'net io percent(bytes/s): 0 <br>'  
  51.            
  52.         #記錄當前網卡信息到臨時文件中   
  53.         os.system('ifconfig > ifconfigtemp')   
  54.         file = open('./ifconfigtemp','r');   
  55.         fileold = open('./oldifconfig''w')   
  56.         temptimestr = str(int(time.time()));   
  57.         fileold.write(temptimestr)   
  58.         fileold.write('#')   
  59.         file.seek(0)   
  60.         fileold.write(file.read())   
  61.         fileold.close()   
  62.         returnkeys = []   
  63.         returnvalues = []   
  64.         netcard = {}   
  65.         tempcountcard = 0  
  66.         file.seek(0)   
  67.         key = ''  
  68.         for strline in file.readlines():   
  69.             reobj = re.compile('^lo*.')   
  70.             if reobj.search(strline):   
  71.                 break;   
  72.             reobj = re.compile('^eth*.')   
  73.             if reobj.search(strline):   
  74.                 key = strline.split()[0]   
  75.                 netcard[key] = ''  
  76.             netcard[key] = netcard[key] + strline   
  77.         newnetcard = {}   
  78.         file.seek(0)   
  79.         key = ''  
  80.         for strline in file.readlines():   
  81.             reobj = re.compile('^lo*.')   
  82.             if reobj.search(strline):   
  83.                 break;   
  84.             if re.search("^eth", strline):   
  85.                 templist = strline.split()   
  86.                 key = templist[0]   
  87.                 newnetcard[key] = ''  
  88.                 newnetcard[key] = templist[4] + newnetcard[key] + ' '  
  89.             if re.search("^ *inet ", strline):   
  90.                 templist = strline.split()   
  91.                 newnetcard[key] = templist[1][5:] + ' ' + newnetcard[key] + ' '  
  92.         for key,value in newnetcard.items():   
  93.             #記錄每張網卡是否工作狀態信息到臨時文件   
  94.             os.system('ethtool %s > ethtooltemp'%(key))   
  95.             file = open('./ethtooltemp','r');   
  96.             tempethtooltemplist = file.read().split('\n\t')   
  97.             file.close   
  98.             if re.search("yes", tempethtooltemplist[-1]):   
  99.                 templist = newnetcard[key].split()   
  100.                 newnetcard[key] = templist[0] + ' runing! ' + templist[1]   
  101.             else:   
  102.                 templist = newnetcard[key].split()   
  103.                 if len(templist) > 1:   
  104.                     newnetcard[key] = templist[0] + ' stop! ' + templist[1]   
  105.                 else:   
  106.                     newnetcard[key] =  'stop! ' + templist[0]   
  107.         file.close()   
  108.         RX = {}   
  109.         TX = {}   
  110.         for key,value in netcard.items():   
  111.             tempsplit = value.split('\n')   
  112.             netcard[key] = ''  
  113.             for item in tempsplit:   
  114.                 item = item + '<br>'  
  115.                 netcard[key] = netcard[key] + item   
  116.                 tempcount = 1  
  117.                 for match in re.finditer("(bytes:)(.*?)( \()", item):   
  118.                     if tempcount == 1:   
  119.                         RX[key] = str(int(match.group(2)) - int(RXold[key]))   
  120.                         tempcount = tempcount + 1  
  121.                     elif tempcount == 2:   
  122.                         TX[key] = str(int(match.group(2)) - int(TXold[key]))   
  123.                         divtime = float(int(time.time()) - int(oldtime))   
  124.                         if divtime == 0:   
  125.                             rate = (float(TX[key]) + float(RX[key]))   
  126.                         else:   
  127.                             rate = (float(TX[key]) + float(RX[key]))/(divtime)   
  128.                         if rate == 0:   
  129.                             newnetcard[key] = '0' + ' ' + newnetcard[key]   
  130.                         else:   
  131.                             newnetcard[key] = '%.2f'%rate + ' ' + newnetcard[key]   
  132.         return zip(['order'], ['48']) + newnetcard.items();   
  133.     else:   
  134.         os.system('ifconfig > ifconfigtemp')   
  135.         file = open('./ifconfigtemp','r');   
  136.         fileold = open('./oldifconfig''w')   
  137.         temptimestr = str(int(time.time()));   
  138.         fileold.write(temptimestr)   
  139.         fileold.write('#')   
  140.         file.seek(0)   
  141.         fileold.write(file.read())   
  142.         fileold.close()   
  143.   
  144.         netcard = {}   
  145.         file.seek(0)   
  146.         key = ''  
  147.         for strline in file.readlines():   
  148.             reobj = re.compile('^lo*.')   
  149.             if reobj.search(strline):   
  150.                 break;   
  151.             reobj = re.compile('^eth*.')   
  152.             if reobj.search(strline):   
  153.                 key = strline.split()[0]   
  154.                 netcard[key] = ''  
  155.             netcard[key] = netcard[key] + strline   
  156.         RX = {}   
  157.         TX = {}   
  158.            
  159.         key = ''  
  160.         newnetcard = {}   
  161.         file.seek(0)   
  162.         for strline in file.readlines():   
  163.             reobj = re.compile('^lo*.')   
  164.             if reobj.search(strline):   
  165.                 break;   
  166.             if re.search("^eth", strline):   
  167.                 templist = strline.split()   
  168.                 key = templist[0]   
  169.                 newnetcard[key] = templist[4] + ' '  
  170.             if re.search("^ *inet ", strline):   
  171.                 templist = strline.split()   
  172.                 newnetcard[key] = newnetcard[key] + templist[1][5:] + ' '  
  173.         for key,value in newnetcard.items():   
  174.             os.system('ethtool %s > ethtooltemp'%(key))   
  175.             file = open('./ethtooltemp','r');   
  176.             tempethtooltemplist = file.read().split('\n')   
  177.             file.close   
  178.             if re.search("yes", tempethtooltemplist[-1]):   
  179.                 newnetcard[key] = newnetcard[key] + 'runing!'  
  180.             else:   
  181.                 newnetcard[key] = newnetcard[key] + 'stop!'  
  182.         file.close()   
  183.         for key,value in netcard.items():   
  184.             tempsplit = value.split('\n')   
  185.             netcard[key] = ''  
  186.             for item in tempsplit:   
  187.                 item = item + '<br>'  
  188.                 #print item   
  189.                 netcard[key] = netcard[key] + item   
  190.                 tempcount = 1  
  191.                 for match in re.finditer("(bytes:)(.*?)( \()", item):   
  192.                     if tempcount == 1:   
  193.                         RX[key] = match.group(2)   
  194.                         tempcount = tempcount + 1  
  195.                     elif tempcount == 2:   
  196.                         TX[key] = match.group(2)   
  197.                         netcard[key] = netcard[key] + 'net io percent(bytes/s): 0 <br>'  
  198.                         newnetcard[key] = newnetcard[key] + ' ' + '0 <br>'  
  199.         return zip(['order'], ['48']) + newnetcard.items();   
  200. if __name__ == '__main__':   
  201.     print run()  

 

使用例子:

1 

每一個列表元素元組里面第二個元素第一個字段為網速 Bytes/S,例如eth1網卡的網速就是3.3KB/s,eth0網速是2.9KB/s,今天是周六這個流量很正常

posted @ 2010-03-15 19:22 學者站在巨人的肩膀上 閱讀(591) | 評論 (0)編輯 收藏

2009年12月10日 #

以下是根據正向索引建立倒排索引的注釋

 

int main(int argc, char* argv[])    //./CrtInvertedIdx moon.fidx.sort > sun.iidx
{
    ifstream ifsImgInfo(argv[1]);
    if (!ifsImgInfo) 
    {
        cerr << "Cannot open " << argv[1] << " for input\n";
        return -1;
    }

    string strLine,strDocNum,tmp1="";
    int cnt = 0;
    while (getline(ifsImgInfo, strLine)) 
    {
        string::size_type idx;
        string tmp;


        idx = strLine.find("\t");
        tmp = strLine.substr(0,idx);

        if (tmp.size()<2 || tmp.size() > 8) continue;

        if (tmp1.empty()) tmp1=tmp;

        if (tmp == tmp1) 
        {
            strDocNum = strDocNum + " " + strLine.substr(idx+1);
        }
        else 
        {
            if ( strDocNum.empty() )
                strDocNum = strDocNum + " " + strLine.substr(idx+1);

            cout << tmp1 << "\t" << strDocNum << endl;
            tmp1 = tmp;
            strDocNum.clear();
            strDocNum = strDocNum + " " + strLine.substr(idx+1);
        }

        cnt++;
        //if (cnt==100) break;
    }
    cout << tmp1 << "\t" << strDocNum << endl;  //倒排索引中每個字典單詞后的文檔編號以table鍵為間隔

    return 0;
}

 

 

posted @ 2009-12-10 23:03 學者站在巨人的肩膀上 閱讀(1602) | 評論 (3)編輯 收藏

這里介紹正向索引的建立,如果直接建立倒排索引效率上可能會很低,所以可以先產生正向索引為后面的倒排索引打下基礎。

 

詳細的文件功能和介紹都在這里有了介紹自頂向下學搜索引擎——北大天網搜索引擎TSE分析及完全注釋[5]倒排索引的建立及文件介紹

 

CrtForwardIdx.cpp文件

 

int main(int argc, char* argv[])    //./CrtForwardIdx Tianwang.raw.***.seg > moon.fidx
{
    ifstream ifsImgInfo(argv[1]);
    if (!ifsImgInfo) 
    {
        cerr << "Cannot open " << argv[1] << " for input\n";
        return -1;
    }

    string strLine,strDocNum;
    int cnt = 0;
    while (getline(ifsImgInfo, strLine)) 
    {
        string::size_type idx;

        cnt++;
        if (cnt%2 == 1) //奇數行為文檔編號
        {
            strDocNum = strLine.substr(0,strLine.size());
            continue;
        }
        if (strLine[0]=='\0' || strLine[0]=='#' || strLine[0]=='\n')
        {
            continue;
        }

        while ( (idx = strLine.find(SEPARATOR)) != string::npos ) //指定查找分界符
        {
            string tmp1 = strLine.substr(0,idx);
            cout << tmp1 << "\t" << strDocNum << endl;
            strLine = strLine.substr(idx + SEPARATOR.size());
        }

        //if (cnt==100) break;
    }

    return 0;
}

 

author:http://hi.baidu.com/jrckkyy

author:http://blog.csdn.net/jrckkyy

 

 

posted @ 2009-12-10 23:02 學者站在巨人的肩膀上 閱讀(1209) | 評論 (1)編輯 收藏

前面的DocIndex程序輸入一個Tianwang.raw.*****文件,會產生一下三個文件 Doc.idx, Url.idx, DocId2Url.idx,我們這里對DocSegment程序進行分析。

這里輸入 Tianwang.raw.*****,Doc.idx,Url.idx.sort_uniq等三個文件,輸出一個Tianwang.raw.***.seg 分詞完畢的文件

int main(int argc, char* argv[])
{
    string strLine, strFileName=argv[1];
    CUrl iUrl;
    vector<CUrl> vecCUrl;
    CDocument iDocument;
    vector<CDocument> vecCDocument;
    unsigned int docId = 0;

    //ifstream ifs("Tianwang.raw.2559638448");
    ifstream ifs(strFileName.c_str());  //DocSegment Tianwang.raw.****
    if (!ifs) 
    {
        cerr << "Cannot open tianwang.img.info for input\n";
        return -1;
    }

    ifstream ifsUrl("Url.idx.sort_uniq");   //排序并消重后的url字典
    if (!ifsUrl) 
    {
        cerr << "Cannot open Url.idx.sort_uniq for input\n";
        return -1;
    }
    ifstream ifsDoc("Doc.idx"); //字典文件
    if (!ifsDoc) 
    {
        cerr << "Cannot open Doc.idx for input\n";
        return -1;
    }

    while (getline(ifsUrl,strLine)) //偏離url字典存入一個向量內存中
    {
        char chksum[33];
        int  docid;

        memset(chksum, 0, 33);
        sscanf( strLine.c_str(), "%s%d", chksum, &docid );
        iUrl.m_sChecksum = chksum;
        iUrl.m_nDocId = docid;
        vecCUrl.push_back(iUrl);
    }

    while (getline(ifsDoc,strLine))     //偏離字典文件將其放入一個向量內存中
    {
        int docid,pos,length;
        char chksum[33];

        memset(chksum, 0, 33);
        sscanf( strLine.c_str(), "%d%d%d%s", &docid, &pos, &length,chksum );
        iDocument.m_nDocId = docid;
        iDocument.m_nPos = pos;
        iDocument.m_nLength = length;
        iDocument.m_sChecksum = chksum;
        vecCDocument.push_back(iDocument);
    }

 

    strFileName += ".seg";
    ofstream fout(strFileName.c_str(), ios::in|ios::out|ios::trunc|ios::binary);    //設置完成分詞后的數據輸出文件
    for ( docId=0; docId<MAX_DOC_ID; docId++ )
    {

        // find document according to docId
        int length = vecCDocument[docId+1].m_nPos - vecCDocument[docId].m_nPos -1;
        char *pContent = new char[length+1];
        memset(pContent, 0, length+1);
        ifs.seekg(vecCDocument[docId].m_nPos);
        ifs.read(pContent, length);

        char *s;
        s = pContent;

        // skip Head
        int bytesRead = 0,newlines = 0;
        while (newlines != 2 && bytesRead != HEADER_BUF_SIZE-1) 
        {
            if (*s == '\n')
                newlines++;
            else
                newlines = 0;
            s++;
            bytesRead++;
        }
        if (bytesRead == HEADER_BUF_SIZE-1) continue;


        // skip header
        bytesRead = 0,newlines = 0;
        while (newlines != 2 && bytesRead != HEADER_BUF_SIZE-1) 
        {
            if (*s == '\n')
                newlines++;
            else
                newlines = 0;
            s++;
            bytesRead++;
        }
        if (bytesRead == HEADER_BUF_SIZE-1) continue;

        //iDocument.m_sBody = s;
        iDocument.RemoveTags(s);    //去除<>
        iDocument.m_sBodyNoTags = s;

        delete[] pContent;
        string strLine = iDocument.m_sBodyNoTags;

        CStrFun::ReplaceStr(strLine, " ", " ");
        CStrFun::EmptyStr(strLine); // set " \t\r\n" to " "


        // segment the document 具體分詞處理
        CHzSeg iHzSeg;
        strLine = iHzSeg.SegmentSentenceMM(iDict,strLine);
        fout << docId << endl << strLine;
        fout << endl;
        
    }

    return(0);
}
這里只是浮光掠影式的過一遍大概的代碼,后面我會有專題詳細講解 parse html 和 segment docment 等技術

 

 

posted @ 2009-12-10 23:02 學者站在巨人的肩膀上 閱讀(1170) | 評論 (1)編輯 收藏

author:http://hi.baidu.com/jrckkyy

author:http://blog.csdn.net/jrckkyy

上一篇主要介紹了倒排索引建立相關的文件及中間文件。
TSE建立索引在運行程序上的大致步驟可以簡化分為以下幾步:

1、運行命令#./DocIndex
會用到一個文件 tianwang.raw.520    //爬取回來的原始文件,包含多個網頁的所有信息,所以很大,這也是一個有待解決的問題,到底存成大文件(如果過大會超過2G或4G的限制,而且文件過大索引效率過低)還是小文件(文件數過多用于打開關閉文件句柄的消耗過大)還有待思考,還就是存儲方案的解決最終肯定是要存為分布式的,最終總文件量肯定是會上TB的,TSE只支持小型的搜索引擎需求。          
會產生一下三個文件 Doc.idx, Url.idx, DocId2Url.idx    //Data文件夾中的Doc.idx DocId2Url.idx和Doc.idx

2、運行命令#sort Url.idx|uniq > Url.idx.sort_uniq    //Data文件夾中的Url.idx.sort_uniq
會用到一個文件 Url.idx文件 //md5 hash 之后的url完整地址和document id值對
會產生一個文件 Url.idx.sort_uniq //URL消重,md5 hash排序,提高檢索效率

3、運行命令#./DocSegment Tianwang.raw.2559638448 
會用到一個文件 Tianwang.raw.2559638448  //Tianwang.raw.2559638448為爬回來的文件 ,每個頁面包含http頭,分詞為后面建立到排索引做準備
會產生一個文件 Tianwang.raw.2559638448.seg //分詞文件,由一行document id號和一行文檔分詞組(只對每個文檔<html></html>中<head></head><body></body>等文字標記中的文本進行分組)構成

4、運行命令#./CrtForwardIdx Tianwang.raw.2559638448.seg > moon.fidx //建立獨立的正向索引

5、運行命令
#set | grep "LANG"
#LANG=en; export LANG;
#sort moon.fidx > moon.fidx.sort

6、運行命令#./CrtInvertedIdx moon.fidx.sort > sun.iidx //建立倒排索引

我們先從建立索引的第一個程序DocIndex.cpp開始分析。(注釋約定:Tianwang.raw.2559638448是抓回來合并成的大文件,后面就叫大文件,里面包含了很多篇html文檔,里面的文檔有規律的分隔就叫做一篇一篇的文檔)


//DocIndex.h start-------------------------------------------------------------

 


#ifndef _COMM_H_040708_
#define _COMM_H_040708_

#include

#include
#include
#include
#include
#include
#include
#include


using namespace std;

const unsigned HEADER_BUF_SIZE = 1024;
const unsigned RstPerPage = 20; //前臺搜索結果數據集返回條數

//iceway
//const unsigned MAX_DOC_IDX_ID = 21312;  //DocSegment.cpp中要用到
const unsigned MAX_DOC_IDX_ID = 22104;


//const string IMG_INFO_NAME("./Data/s1.1");
const string INF_INFO_NAME("./Data/sun.iidx"); //倒排索引文件
//朱德  14383 16151 16151 16151 1683 207 6302 7889 8218 8218 8637
//朱古力  1085 1222

//9萬多條 字元文件 包括特殊符號,標點,漢字
const string DOC_IDX_NAME("./Data/Doc.idx"); //倒排索引文件
const string RAWPAGE_FILE_NAME("./Data/Tianwang.swu.iceway.1.0");

//iceway
const string DOC_FILE_NAME = "Tianwang.swu.iceway.1.0";  //Docindex.cpp中要用到
const string Data_DOC_FILE_NAME = "./Data/Tianwang.swu.iceway.1.0";  //Snapshot.cpp中要用到


//const string RM_THUMBNAIL_FILES("rm -f ~/public_html/ImgSE/timg/*");

//const string THUMBNAIL_DIR("/ImgSE/timg/");


#endif _COMM_H_040708_
//DocIndex.h end--------------------------------------------------------------//DocIndex.cpp start-----------------------------------------------------------

#include
#include
#include "Md5.h"
#include "Url.h"
#include "Document.h"

//iceway(mnsc)
#include "Comm.h"
#include

using namespace std;

int main(int argc, char* argv[])
{
    //ifstream ifs("Tianwang.raw.2559638448");
 //ifstream ifs("Tianwang.raw.3023555472");
 //iceway(mnsc)
 ifstream ifs(DOC_FILE_NAME.c_str()); //打開Tianwang.raw.3023555472文件,最原始的文件
 if (!ifs)
 {
     cerr << "Cannot open " << "tianwang.img.info" << " for input\n";
     return -1;
    }
 ofstream ofsUrl("Url.idx", ios::in|ios::out|ios::trunc|ios::binary); //建立并打開Url.idx文件
 if( !ofsUrl )
 {
  cout << "error open file " << endl;
 }

 ofstream ofsDoc("Doc.idx", ios::in|ios::out|ios::trunc|ios::binary); //建立并打開Doc.idx文件
 if( !ofsDoc )
 {
  cout << "error open file " << endl;
 }

 ofstream ofsDocId2Url("DocId2Url.idx", ios::in|ios::out|ios::trunc|ios::binary); //建立并打開DocId2Url.idx文件
 if( !ofsDocId2Url )
 {
  cout << "error open file " << endl;
 }

 int cnt=0; //文檔編號從0開始計算
 string strLine,strPage;
 CUrl iUrl;
 CDocument iDocument;
 CMD5 iMD5;
 
 int nOffset = ifs.tellg();
 while (getline(ifs, strLine))
 {
  if (strLine[0]=='\0' || strLine[0]=='#' || strLine[0]=='\n')
  {
   nOffset = ifs.tellg();
   continue;
  }

  if (!strncmp(strLine.c_str(), "version: 1.0", 12)) //判斷第一行是否是version: 1.0如果是就解析下去
  { 
   if(!getline(ifs, strLine)) break;
   if (!strncmp(strLine.c_str(), "url: ", 4)) //判斷第二行是否是url: 如果是則解析下去
   {
    iUrl.m_sUrl = strLine.substr(5); //截取url: 五個字符之后的url內容
    iMD5.GenerateMD5( (unsigned char*)iUrl.m_sUrl.c_str(), iUrl.m_sUrl.size() ); //對url用md5 hash處理
    iUrl.m_sChecksum = iMD5.ToString(); //將字符數組組合成字符串這個函數在Md5.h中實現

   } else
   {
    continue;
   }

   while (getline(ifs, strLine))
   {
    if (!strncmp(strLine.c_str(), "length: ", 8)) //一直讀下去直到判斷澹澹(相對第五行)惺欠袷莑ength: 是則接下下去
    {
     sscanf(strLine.substr(8).c_str(), "%d", &(iDocument.m_nLength)); //將該塊所代表網頁的實際網頁內容長度放入iDocument數據結構中
     break;
    }
   }

   getline(ifs, strLine); //跳過相對第六行故意留的一個空行

   iDocument.m_nDocId = cnt; //將文檔編號賦值到iDocument數據結構中
   iDocument.m_nPos = nOffset; //文檔結尾在大文件中的結束行號
   char *pContent = new char[iDocument.m_nLength+1]; //新建該文檔長度的字符串指針

   memset(pContent, 0, iDocument.m_nLength+1); //每一位初始化為0
   ifs.read(pContent, iDocument.m_nLength); //根據獲得的文檔長度讀取澹(其中包含協議頭)讀取文檔內容
   iMD5.GenerateMD5( (unsigned char*)pContent, iDocument.m_nLength );
   iDocument.m_sChecksum = iMD5.ToString(); //將字符數組組合成字符串這個函數在Md5.h中實現
   
   delete[] pContent;
   
   ofsUrl << iUrl.m_sChecksum ; //將md5hash后的url寫入Url.idx文件
   ofsUrl << "\t" << iDocument.m_nDocId << endl; //在一行中一個tab距離分隔,將文件編號寫入Url.idx文件

   ofsDoc << iDocument.m_nDocId ; //將文件編號寫入Doc.idx文件
   ofsDoc << "\t" << iDocument.m_nPos ; //在一行中一個tab距離分隔,將該文檔結束行號澹(同樣也是下一文檔開始行號)寫入Doc.idx文件
   //ofsDoc << "\t" << iDocument.m_nLength ;
   ofsDoc << "\t" << iDocument.m_sChecksum << endl; //在一行中一個tab距離分隔,將md5hash后的url寫入Doc.idx文件

   ofsDocId2Url << iDocument.m_nDocId ; //將文件編號寫入DocId2Url.idx文件
   ofsDocId2Url << "\t" << iUrl.m_sUrl << endl; //將該文檔的完整url寫入DocId2Url.idx文件

   cnt++; //文檔編號加一說明該以文檔分析完畢,生成下一文檔的編號
  }

  nOffset = ifs.tellg();

 }

 //最后一行只有文檔號和上一篇文檔結束號
 ofsDoc << cnt ;
 ofsDoc << "\t" << nOffset << endl;


 return(0);
}

//DocIndex.cpp end-----------------------------------------------------------author:http://hi.baidu.com/jrckkyy

author:http://blog.csdn.net/jrckkyy

 

 

posted @ 2009-12-10 23:00 學者站在巨人的肩膀上 閱讀(1341) | 評論 (1)編輯 收藏

不好意思讓大家久等了,前一陣一直在忙考試,終于結束了。呵呵!廢話不多說了下面我們開始吧!

TSE用的是將抓取回來的網頁文檔全部裝入一個大文檔,讓后對這一個大文檔內的數據整體統一的建索引,其中包含了幾個步驟。

view plaincopy to clipboardprint?
1.  The document index (Doc.idx) keeps information about each document.  
 
It is a fixed width ISAM (Index sequential access mode) index, orderd by docID.  
 
The information stored in each entry includes a pointer into the repository,  
 
a document length, a document checksum.  
 
 
 
//Doc.idx  文檔編號 文檔長度    checksum hash碼  
 
0   0   bc9ce846d7987c4534f53d423380ba70  
 
1   76760   4f47a3cad91f7d35f4bb6b2a638420e5  
 
2   141624  d019433008538f65329ae8e39b86026c  
 
3   142350  5705b8f58110f9ad61b1321c52605795  
 
//Doc.idx   end  
 
 
 
  The url index (url.idx) is used to convert URLs into docIDs.  
 
 
 
//url.idx  
 
5c36868a9c5117eadbda747cbdb0725f    0 
 
3272e136dd90263ee306a835c6c70d77    1 
 
6b8601bb3bb9ab80f868d549b5c5a5f3    2 
 
3f9eba99fa788954b5ff7f35a5db6e1f    3 
 
//url.idx   end  
 
 
 
It is a list of URL checksums with their corresponding docIDs and is sorted by  
 
checksum. In order to find the docID of a particular URL, the URL's checksum  
 
is computed and a binary search is performed on the checksums file to find its  
 
docID.  
 
 
 
    ./DocIndex  
 
        got Doc.idx, Url.idx, DocId2Url.idx //Data文件夾中的Doc.idx DocId2Url.idx和Doc.idx中  
 
 
 
//DocId2Url.idx  
 
0   http://*.*.edu.cn/index.aspx  
 
1   http://*.*.edu.cn/showcontent1.jsp?NewsID=118  
 
2   http://*.*.edu.cn/0102.html  
 
3   http://*.*.edu.cn/0103.html  
 
//DocId2Url.idx end  
 
 
 
2.  sort Url.idx|uniq > Url.idx.sort_uniq    //Data文件夾中的Url.idx.sort_uniq  
 
 
 
//Url.idx.sort_uniq  
 
//對hash值進行排序  
 
000bfdfd8b2dedd926b58ba00d40986b    1111 
 
000c7e34b653b5135a2361c6818e48dc    1831 
 
0019d12f438eec910a06a606f570fde8    366 
 
0033f7c005ec776f67f496cd8bc4ae0d    2103 
 
 
 
3. Segment document to terms, (with finding document according to the url)  
 
    ./DocSegment Tianwang.raw.2559638448        //Tianwang.raw.2559638448為爬回來的文件 ,每個頁面包含http頭  
 
        got Tianwang.raw.2559638448.seg       
 
 
 
//Tianwang.raw.2559638448   爬取的原始網頁文件在文檔內部每一個文檔之間應該是通過version,</html>和回車做標志位分割的  
 
version: 1.0 
 
url: http://***.105.138.175/Default2.asp?lang=gb  
 
origin: http://***.105.138.175/  
 
date: Fri, 23 May 2008 20:01:36 GMT  
 
ip: 162.105.138.175 
 
length: 38413 
 
 
 
HTTP/1.1 200 OK  
 
Server: Microsoft-IIS/5.0 
 
Date: Fri, 23 May 2008 11:17:49 GMT  
 
Connection: keep-alive  
 
Connection: Keep-Alive  
 
Content-Length: 38088 
 
Content-Type: text/html; Charset=gb2312  
 
Expires: Fri, 23 May 2008 11:17:49 GMT  
 
Set-Cookie: ASPSESSIONIDSSTRDCAB=IMEOMBIAIPDFCKPAEDJFHOIH; path=/  
 
Cache-control: private 
 
 
 
 
 
 
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
 
" 
<html>  
 
<head>  
 
<title>Apabi數字資源平臺</title>  
 
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
 
<META NAME="ROBOTS" CONTENT="INDEX,NOFOLLOW">  
 
<META NAME="DESCRIPTION" CONTENT="數字圖書館 方正數字圖書館 電子圖書 電子書 ebook e書 Apabi 數字資源平臺">  
 
<link rel="stylesheet" type="text/css" href="css\common.css">  
 
 
 
<style type="text/css">  
 
<!--  
 
.style4 {color: #666666}  
 
-->  
 
</style>  
 
 
 
<script LANGUAGE="vbscript">  
 
...  
 
</script>  
 
 
 
<Script Language="javascript">  
 
...  
 
</Script>  
 
</head>  
 
<body leftmargin="0" topmargin="0">  
 
</body>  
 
</html>  
 
//Tianwang.raw.2559638448   end  
 
 
 
//Tianwang.raw.2559638448.seg   將每個頁面分成一行如下(注意中間沒有回車作為分隔)  
 

 
...  
 
...  
 
...  
 

 
...  
 
...  
 
...  
 
//Tianwang.raw.2559638448.seg   end  
 
 
 
//下是 Tiny search 非必須因素  
 
4. Create forward index (docic-->termid)     //建立正向索引  
 
    ./CrtForwardIdx Tianwang.raw.2559638448.seg > moon.fidx  
 
 
 
//Tianwang.raw.2559638448.seg 將每個頁面分成一行如下<BR>//分詞   DocID<BR>1<BR>三星/  s/  手機/  論壇/  ,/  手機/  鈴聲/  下載/  ,/  手機/  圖片/  下載/  ,/  手機/<BR>2<BR>...<BR>...<BR>... 

1.  The document index (Doc.idx) keeps information about each document.

It is a fixed width ISAM (Index sequential access mode) index, orderd by docID.

The information stored in each entry includes a pointer into the repository,

a document length, a document checksum.

 

//Doc.idx  文檔編號 文檔長度 checksum hash碼

0 0 bc9ce846d7987c4534f53d423380ba70

1 76760 4f47a3cad91f7d35f4bb6b2a638420e5

2 141624 d019433008538f65329ae8e39b86026c

3 142350 5705b8f58110f9ad61b1321c52605795

//Doc.idx end

 

  The url index (url.idx) is used to convert URLs into docIDs.

 

//url.idx

5c36868a9c5117eadbda747cbdb0725f 0

3272e136dd90263ee306a835c6c70d77 1

6b8601bb3bb9ab80f868d549b5c5a5f3 2

3f9eba99fa788954b5ff7f35a5db6e1f 3

//url.idx end

 

It is a list of URL checksums with their corresponding docIDs and is sorted by

checksum. In order to find the docID of a particular URL, the URL's checksum

is computed and a binary search is performed on the checksums file to find its

docID.

 

 ./DocIndex

  got Doc.idx, Url.idx, DocId2Url.idx //Data文件夾中的Doc.idx DocId2Url.idx和Doc.idx中

 

//DocId2Url.idx

http://*.*.edu.cn/index.aspx

http://*.*.edu.cn/showcontent1.jsp?NewsID=118

http://*.*.edu.cn/0102.html

http://*.*.edu.cn/0103.html

//DocId2Url.idx end

 

2.  sort Url.idx|uniq > Url.idx.sort_uniq //Data文件夾中的Url.idx.sort_uniq

 

//Url.idx.sort_uniq

//對hash值進行排序

000bfdfd8b2dedd926b58ba00d40986b 1111

000c7e34b653b5135a2361c6818e48dc 1831

0019d12f438eec910a06a606f570fde8 366

0033f7c005ec776f67f496cd8bc4ae0d 2103

 

3. Segment document to terms, (with finding document according to the url)

 ./DocSegment Tianwang.raw.2559638448  //Tianwang.raw.2559638448為爬回來的文件 ,每個頁面包含http頭

  got Tianwang.raw.2559638448.seg  

 

//Tianwang.raw.2559638448 爬取的原始網頁文件在文檔內部每一個文檔之間應該是通過version,</html>和回車做標志位分割的

version: 1.0

url: http://***.105.138.175/Default2.asp?lang=gb

origin: http://***.105.138.175/

date: Fri, 23 May 2008 20:01:36 GMT

ip: 162.105.138.175

length: 38413

 

HTTP/1.1 200 OK

Server: Microsoft-IIS/5.0

Date: Fri, 23 May 2008 11:17:49 GMT

Connection: keep-alive

Connection: Keep-Alive

Content-Length: 38088

Content-Type: text/html; Charset=gb2312

Expires: Fri, 23 May 2008 11:17:49 GMT

Set-Cookie: ASPSESSIONIDSSTRDCAB=IMEOMBIAIPDFCKPAEDJFHOIH; path=/

Cache-control: private

 

 

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"

<html>

<head>

<title>Apabi數字資源平臺</title>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

<META NAME="ROBOTS" CONTENT="INDEX,NOFOLLOW">

<META NAME="DESCRIPTION" CONTENT="數字圖書館 方正數字圖書館 電子圖書 電子書 ebook e書 Apabi 數字資源平臺">

<link rel="stylesheet" type="text/css" href="css\common.css">

 

<style type="text/css">

<!--

.style4 {color: #666666}

-->

</style>

 

<script LANGUAGE="vbscript">

...

</script>

 

<Script Language="javascript">

...

</Script>

</head>

<body leftmargin="0" topmargin="0">

</body>

</html>

//Tianwang.raw.2559638448 end

 

//Tianwang.raw.2559638448.seg 將每個頁面分成一行如下(注意中間沒有回車作為分隔)

1

...

...

...

2

...

...

...

//Tianwang.raw.2559638448.seg end

 

//下是 Tiny search 非必須因素

4. Create forward index (docic-->termid)  //建立正向索引

 ./CrtForwardIdx Tianwang.raw.2559638448.seg > moon.fidx

 

//Tianwang.raw.2559638448.seg 將每個頁面分成一行如下//分詞   DocID1三星/  s/  手機/  論壇/  ,/  手機/  鈴聲/  下載/  ,/  手機/  圖片/  下載/  ,/  手機/2.........view plaincopy to clipboardprint?
//Tianwang.raw.2559638448.seg end  
 
 
//moon.fidx  
 
//每篇文檔號對應文檔內分出來的    分詞  DocID  
 
都會  2391 
 
使   2391 
 
那些  2391 
 
擁有  2391 
 
它   2391 
 
的   2391 
 
人   2391 
 
的   2391 
 
視野  2391 
 
變   2391 
 
窄   2391 
 
在   2180 
 
研究生部    2180 
 
主頁  2180 
 
培養  2180 
 
管理  2180 
 
欄目  2180 
 
下載  2180 
 
)   2180 
 
、   2180 
 
關于  2180 
 
做好  2180 
 
年   2180 
 
國家  2180 
 
公派  2180 
 
研究生 2180 
 
項目  2180 
 
//moon.fidx end  
 
 
 
5.# set | grep "LANG" 
 
LANG=en; export LANG;  
 
sort moon.fidx > moon.fidx.sort  
 
 
 
6. Create inverted index (termid-->docid)    //建立倒排索引  
 
    ./CrtInvertedIdx moon.fidx.sort > sun.iidx  
 
 
 
//sun.iidx  //文件規模大概減少1/2  
 
花工   236 
 
花海   2103 
 
花卉   1018 1061 1061 1061 1730 1730 1730 1730 1730 1852 949 949 
 
花蕾   447 447 
 
花木   1061 
 
花呢   1430 
 
花期   447 447 447 447 447 525 
 
花錢   174 236 
 
花色   1730 1730 
 
花色品種     1660 
 
花生   450 526 
 
花式   1428 1430 1430 1430 
 
花紋   1430 1430 
 
花序   447 447 447 447 447 450 
 
花絮   136 137 
 
花芽   450 450 
 
//sun.iidx  end  
 
 
 
TSESearch   CGI program for query  
 
Snapshot    CGI program for page snapshot  
 
 
<P>  
author:http://hi.baidu.com/jrckkyy  
 
author:http://blog.csdn.net/jrckkyy  
</P> 

 

posted @ 2009-12-10 22:55 學者站在巨人的肩膀上 閱讀(1317) | 評論 (1)編輯 收藏

通過前面的三篇文章相信你已經對神秘的搜索引擎有了一個感性的認識,和普通的php類似的腳本語言服務器類似,通過獲取前臺關鍵字,通過字典分詞,和事先建立建立好的倒排索引進行相關性分析,得出查詢結構格式化輸出結果。而這里的技術難點在于

1、字典的選取(事實上根據不同時代不同地方人們的語言習慣是不一樣的所以說字典的最小元的取值是不同的)

2、倒排索引的建立(這里就要涉及到爬蟲的抓取和索引的建立后面將重點介紹這2點,搜索引擎的效率和服務質量實效性瓶頸在這里)

3、相關性分析(對抓回來的文檔分詞建索引和用戶關鍵字分詞算法上要對應)

后面文章會重點介紹爬蟲的抓取和索引的建立。

posted @ 2009-12-10 22:54 學者站在巨人的肩膀上 閱讀(1005) | 評論 (0)編輯 收藏

有前面注釋我們可以知道查詢關鍵字和字典文件準備好好后,將進入用戶關鍵字分詞階段

//TSESearch.cpp中:

view plaincopy to clipboardprint?
CHzSeg iHzSeg;      //include ChSeg/HzSeg.h  
 
//  
iQuery.m_sSegQuery = iHzSeg.SegmentSentenceMM(iDict, iQuery.m_sQuery);  //將get到的查詢變量分詞分成 "我/        愛/      你們/ 的/      格式"  
 
vector<STRING></STRING> vecTerm;  
iQuery.ParseQuery(vecTerm);     //將以"/"劃分開的關鍵字一一順序放入一個向量容器中  
 
set<STRING></STRING> setRelevantRst;   
iQuery.GetRelevantRst(vecTerm, mapBuckets, setRelevantRst);   
 
gettimeofday(&end_tv,&tz);  
// search end  
//搜索完畢 

 CHzSeg iHzSeg;  //include ChSeg/HzSeg.h

 //
 iQuery.m_sSegQuery = iHzSeg.SegmentSentenceMM(iDict, iQuery.m_sQuery); //將get到的查詢變量分詞分成 "我/  愛/  你們/ 的/  格式"
 
 vector vecTerm;
 iQuery.ParseQuery(vecTerm);  //將以"/"劃分開的關鍵字一一順序放入一個向量容器中
 
 set setRelevantRst;
 iQuery.GetRelevantRst(vecTerm, mapBuckets, setRelevantRst);
 
 gettimeofday(&end_tv,&tz);
 // search end
 //搜索完畢view plaincopy to clipboardprint?
看CHzSeg 中的這個方法 

看CHzSeg 中的這個方法view plaincopy to clipboardprint?
//ChSeg/HzSeg.h 

//ChSeg/HzSeg.hview plaincopy to clipboardprint?
/**  
 * 程序翻譯說明  
 * 進一步凈化數據,轉換漢字  
 * @access  public  
 * @param   CDict, string 參數的漢字說明:字典,查詢字符串  
 * @return  string 0  
 */  
// process a sentence before segmentation  
//在分詞前處理句子  
string CHzSeg::SegmentSentenceMM (CDict &dict, string s1) const  
{  
    string s2="";  
    unsigned int i,len;  
 
    while (!s1.empty())   
    {  
        unsigned char ch=(unsigned char) s1[0];  
        if(ch<128)   
        { // deal with ASCII  
            i=1;  
            len = s1.size();  
            while (i<LEN len="s1.length();" i="0;" 中文標點等非漢字字符="" if="" else="" yhf="" s1="s1.substr(i);" by="" added="" ch="=13)" s2="" cr=""></LEN>=161)  
              && (!((unsigned char)s1[i]==161 && ((unsigned char)s1[i+1]>=162 && (unsigned char)s1[i+1]<=168)))  
              && (!((unsigned char)s1[i]==161 && ((unsigned char)s1[i+1]>=171 && (unsigned char)s1[i+1]<=191)))  
              && (!((unsigned char)s1[i]==163 && ((unsigned char)s1[i+1]==172 || (unsigned char)s1[i+1]==161)   
              || (unsigned char)s1[i+1]==168 || (unsigned char)s1[i+1]==169 || (unsigned char)s1[i+1]==186  
              || (unsigned char)s1[i+1]==187 || (unsigned char)s1[i+1]==191)))   
                {   
                    ii=i+2; // 假定沒有半個漢字  
                }  
 
                if (i==0) ii=i+2;  
 
                // 不處理中文空格  
                if (!(ch==161 && (unsigned char)s1[1]==161))   
                {   
                    if (i <= s1.size())  // yhf  
                        // 其他的非漢字雙字節字符可能連續輸出  
                        s2 += s1.substr(0, i) + SEPARATOR;   
                    else break; // yhf  
                }  
 
                if (i <= s1.size())  // yhf  
                    s1s1=s1.substr(i);  
                else break;     //yhf  
 
                continue;  
            }  
        }  
      
 
    // 以下處理漢字串  
 
        i = 2;  
        len = s1.length();  
 
        while(i<LEN></LEN>=176)   
//    while(i<LEN></LEN>=128 && (unsigned char)s1[i]!=161)  
            i+=2;  
 
        s2+=SegmentHzStrMM(dict, s1.substr(0,i));  
 
        if (i <= len)    // yhf  
            s1s1=s1.substr(i);  
        else break; // yhf  
    }  
 
    return s2;  

/**
 * 程序翻譯說明
 * 進一步凈化數據,轉換漢字
 * @access  public
 * @param   CDict, string 參數的漢字說明:字典,查詢字符串
 * @return  string 0
 */
// process a sentence before segmentation
//在分詞前處理句子
string CHzSeg::SegmentSentenceMM (CDict &dict, string s1) const
{
 string s2="";
 unsigned int i,len;

 while (!s1.empty())
 {
  unsigned char ch=(unsigned char) s1[0];
  if(ch<128)
  { // deal with ASCII
   i=1;
   len = s1.size();
   while (i=161)
              && (!((unsigned char)s1[i]==161 && ((unsigned char)s1[i+1]>=162 && (unsigned char)s1[i+1]<=168)))
              && (!((unsigned char)s1[i]==161 && ((unsigned char)s1[i+1]>=171 && (unsigned char)s1[i+1]<=191)))
              && (!((unsigned char)s1[i]==163 && ((unsigned char)s1[i+1]==172 || (unsigned char)s1[i+1]==161)
              || (unsigned char)s1[i+1]==168 || (unsigned char)s1[i+1]==169 || (unsigned char)s1[i+1]==186
              || (unsigned char)s1[i+1]==187 || (unsigned char)s1[i+1]==191)))
    {
     i=i+2; // 假定沒有半個漢字
    }

    if (i==0) i=i+2;

    // 不處理中文空格
    if (!(ch==161 && (unsigned char)s1[1]==161))
    {
     if (i <= s1.size()) // yhf
      // 其他的非漢字雙字節字符可能連續輸出
      s2 += s1.substr(0, i) + SEPARATOR;
     else break; // yhf
    }

    if (i <= s1.size()) // yhf
     s1=s1.substr(i);
    else break;  //yhf

    continue;
   }
  }
   

    // 以下處理漢字串

  i = 2;
  len = s1.length();

  while(i=176)
//    while(i=128 && (unsigned char)s1[i]!=161)
   i+=2;

  s2+=SegmentHzStrMM(dict, s1.substr(0,i));

  if (i <= len) // yhf
   s1=s1.substr(i);
  else break; // yhf
 }

 return s2;
}view plaincopy to clipboardprint?
  

 view plaincopy to clipboardprint?
//Query.cpp 

//Query.cppview plaincopy to clipboardprint?
<PRE class=csharp name="code">/**  
 * 程序翻譯說明  
 * 將以"/"劃分開的關鍵字一一順序放入一個向量容器中  
 *  
 * @access  public  
 * @param   vector<STRING></STRING> 參數的漢字說明:向量容器  
 * @return  void  
 */  
void CQuery::ParseQuery(vector<STRING></STRING> &vecTerm)  
{  
    string::size_type idx;   
    while ( (idx = m_sSegQuery.find("/  ")) != string::npos ) {   
        vecTerm.push_back(m_sSegQuery.substr(0,idx));   
        m_sSegQuerym_sSegQuery = m_sSegQuery.substr(idx+3);   
    }  
}  
</PRE> 
<PRE class=csharp name="code"> </PRE> 
<PRE class=csharp name="code"><PRE class=csharp name="code">/**  
 * 程序翻譯說明  
 * 相關性分析查詢,構造結果集合setRelevantRst //瓶頸所在  
 *  
 * @access  public  
 * @param   vector<STRING></STRING> map set<STRING></STRING> 參數的漢字說明: 用戶提交關鍵字的分詞組,倒排索引映射,相關性結果集合  
 * @return  string 0  
 */  
bool CQuery::GetRelevantRst  
(  
    vector<STRING></STRING> &vecTerm,   
    map &mapBuckets,   
    set<STRING></STRING> &setRelevantRst  
) const  
{  
    set<STRING></STRING> setSRst;  
 
    bool bFirst=true;  
    vector<STRING></STRING>::iterator itTerm = vecTerm.begin();  
 
    for ( ; itTerm != vecTerm.end(); ++itTerm )  
    {  
 
        setSRst.clear();  
        copy(setRelevantRst.begin(), setRelevantRst.end(), inserter(setSRst,setSRst.begin()));  
 
        map mapRstDoc;  
        string docid;  
        int doccnt;  
 
        map::iterator itBuckets = mapBuckets.find(*itTerm);  
        if (itBuckets != mapBuckets.end())  
        {  
            string strBucket = (*itBuckets).second;  
            string::size_type idx;  
            idx = strBucket.find_first_not_of(" ");  
            strBucketstrBucket = strBucket.substr(idx);  
 
            while ( (idx = strBucket.find(" ")) != string::npos )   
            {  
                docid = strBucket.substr(0,idx);  
                doccnt = 0;  
 
                if (docid.empty()) continue;  
 
                map::iterator it = mapRstDoc.find(docid);  
                if ( it != mapRstDoc.end() )  
                {  
                    doccnt = (*it).second + 1;  
                    mapRstDoc.erase(it);  
                }  
                mapRstDoc.insert( pair(docid,doccnt) );  
 
                strBucketstrBucket = strBucket.substr(idx+1);  
            }  
 
            // remember the last one  
            docid = strBucket;  
            doccnt = 0;  
            map::iterator it = mapRstDoc.find(docid);  
            if ( it != mapRstDoc.end() )  
            {  
                doccnt = (*it).second + 1;  
                mapRstDoc.erase(it);  
            }  
            mapRstDoc.insert( pair(docid,doccnt) );  
        }  
 
        // sort by term frequencty  
        multimap > newRstDoc;  
        map::iterator it0 = mapRstDoc.begin();  
        for ( ; it0 != mapRstDoc.end(); ++it0 ){  
            newRstDoc.insert( pair((*it0).second,(*it0).first) );  
        }  
 
        multimap::iterator itNewRstDoc = newRstDoc.begin();  
        setRelevantRst.clear();  
        for ( ; itNewRstDoc != newRstDoc.end(); ++itNewRstDoc ){  
            string docid = (*itNewRstDoc).second;  
 
            if (bFirst==true) {  
                setRelevantRst.insert(docid);  
                continue;  
            }  
 
            if ( setSRst.find(docid) != setSRst.end() ){      
                setRelevantRst.insert(docid);  
            }  
        }  
 
        //cout << "setRelevantRst.size(): " << setRelevantRst.size() << "<BR>";  
        bFirst = false;  
    }  
    return true;  
}</PRE> 
</PRE> 
接下來的就是現實了,前面都只是處理數據得到 setRelevantRst 這個查詢結構集合,這里就不多說了下面就和php之類的腳本語言差不多,格式化結果集合并顯示出來。 

view plaincopy to clipboardprint?/**   * 程序翻譯說明   * 將以"/"劃分開的關鍵字一一順序放入一個向量容器中   *   * @access  public   * @param   vector<STRING></STRING> 參數的漢字說明:向量容器   * @return  void   */  void CQuery::ParseQuery(vector<STRING></STRING> &vecTerm)   {       string::size_type idx;        while ( (idx = m_sSegQuery.find("/  ")) != string::npos ) {            vecTerm.push_back(m_sSegQuery.substr(0,idx));            m_sSegQuery = m_sSegQuery.substr(idx+3);        }   }  /**
 * 程序翻譯說明
 * 將以"/"劃分開的關鍵字一一順序放入一個向量容器中
 *
 * @access  public
 * @param   vector 參數的漢字說明:向量容器
 * @return  void
 */
void CQuery::ParseQuery(vector &vecTerm)
{
 string::size_type idx;
 while ( (idx = m_sSegQuery.find("/  ")) != string::npos ) {
  vecTerm.push_back(m_sSegQuery.substr(0,idx));
  m_sSegQuery = m_sSegQuery.substr(idx+3);
 }
}

view plaincopy to clipboardprint?   
view plaincopy to clipboardprint?<PRE class=csharp name="code">/**   * 程序翻譯說明   * 相關性分析查詢,構造結果集合setRelevantRst //瓶頸所在   *   * @access  public   * @param   vector<STRING></STRING> map set<STRING></STRING> 參數的漢字說明: 用戶提交關鍵字的分詞組,倒排索引映射,相關性結果集合   * @return  string 0   */  bool CQuery::GetRelevantRst   (       vector<STRING></STRING> &vecTerm,        map &mapBuckets,        set<STRING></STRING> &setRelevantRst   ) const  {       set<STRING></STRING> setSRst;         bool bFirst=true;       vector<STRING></STRING>::iterator itTerm = vecTerm.begin();         for ( ; itTerm != vecTerm.end(); ++itTerm )       {             setSRst.clear();           copy(setRelevantRst.begin(), setRelevantRst.end(), inserter(setSRst,setSRst.begin()));             map mapRstDoc;           string docid;           int doccnt;             map::iterator itBuckets = mapBuckets.find(*itTerm);           if (itBuckets != mapBuckets.end())           {               string strBucket = (*itBuckets).second;               string::size_type idx;               idx = strBucket.find_first_not_of(" ");               strBucket = strBucket.substr(idx);                 while ( (idx = strBucket.find(" ")) != string::npos )                {                   docid = strBucket.substr(0,idx);                   doccnt = 0;                     if (docid.empty()) continue;                     map::iterator it = mapRstDoc.find(docid);                   if ( it != mapRstDoc.end() )                   {                       doccnt = (*it).second + 1;                       mapRstDoc.erase(it);                   }                   mapRstDoc.insert( pair(docid,doccnt) );                     strBucket = strBucket.substr(idx+1);               }                 // remember the last one               docid = strBucket;               doccnt = 0;               map::iterator it = mapRstDoc.find(docid);               if ( it != mapRstDoc.end() )               {                   doccnt = (*it).second + 1;                   mapRstDoc.erase(it);               }               mapRstDoc.insert( pair(docid,doccnt) );           }             // sort by term frequencty           multimap > newRstDoc;           map::iterator it0 = mapRstDoc.begin();           for ( ; it0 != mapRstDoc.end(); ++it0 ){               newRstDoc.insert( pair((*it0).second,(*it0).first) );           }             multimap::iterator itNewRstDoc = newRstDoc.begin();           setRelevantRst.clear();           for ( ; itNewRstDoc != newRstDoc.end(); ++itNewRstDoc ){               string docid = (*itNewRstDoc).second;                 if (bFirst==true) {                   setRelevantRst.insert(docid);                   continue;               }                 if ( setSRst.find(docid) != setSRst.end() ){                       setRelevantRst.insert(docid);               }           }             //cout << "setRelevantRst.size(): " << setRelevantRst.size() << "<BR>";           bFirst = false;       }       return true;   }</PRE>  view plaincopy to clipboardprint?/**   * 程序翻譯說明   * 相關性分析查詢,構造結果集合setRelevantRst //瓶頸所在   *   * @access  public   * @param   vector<STRING></STRING> map set<STRING></STRING> 參數的漢字說明: 用戶提交關鍵字的分詞組,倒排索引映射,相關性結果集合   * @return  string 0   */  bool CQuery::GetRelevantRst   (       vector<STRING></STRING> &vecTerm,        map &mapBuckets,        set<STRING></STRING> &setRelevantRst   ) const  {       set<STRING></STRING> setSRst;         bool bFirst=true;       vector<STRING></STRING>::iterator itTerm = vecTerm.begin();         for ( ; itTerm != vecTerm.end(); ++itTerm )       {             setSRst.clear();           copy(setRelevantRst.begin(), setRelevantRst.end(), inserter(setSRst,setSRst.begin()));             map mapRstDoc;           string docid;           int doccnt;             map::iterator itBuckets = mapBuckets.find(*itTerm);           if (itBuckets != mapBuckets.end())           {               string strBucket = (*itBuckets).second;               string::size_type idx;               idx = strBucket.find_first_not_of(" ");               strBucket = strBucket.substr(idx);                 while ( (idx = strBucket.find(" ")) != string::npos )                {                   docid = strBucket.substr(0,idx);                   doccnt = 0;                     if (docid.empty()) continue;                     map::iterator it = mapRstDoc.find(docid);                   if ( it != mapRstDoc.end() )                   {                       doccnt = (*it).second + 1;                       mapRstDoc.erase(it);                   }                   mapRstDoc.insert( pair(docid,doccnt) );                     strBucket = strBucket.substr(idx+1);               }                 // remember the last one               docid = strBucket;               doccnt = 0;               map::iterator it = mapRstDoc.find(docid);               if ( it != mapRstDoc.end() )               {                   doccnt = (*it).second + 1;                   mapRstDoc.erase(it);               }               mapRstDoc.insert( pair(docid,doccnt) );           }             // sort by term frequencty           multimap > newRstDoc;           map::iterator it0 = mapRstDoc.begin();           for ( ; it0 != mapRstDoc.end(); ++it0 ){               newRstDoc.insert( pair((*it0).second,(*it0).first) );           }             multimap::iterator itNewRstDoc = newRstDoc.begin();           setRelevantRst.clear();           for ( ; itNewRstDoc != newRstDoc.end(); ++itNewRstDoc ){               string docid = (*itNewRstDoc).second;                 if (bFirst==true) {                   setRelevantRst.insert(docid);                   continue;               }                 if ( setSRst.find(docid) != setSRst.end() ){                       setRelevantRst.insert(docid);               }           }             //cout << "setRelevantRst.size(): " << setRelevantRst.size() << "<BR>";           bFirst = false;       }       return true;   }  /**
 * 程序翻譯說明
 * 相關性分析查詢,構造結果集合setRelevantRst //瓶頸所在
 *
 * @access  public
 * @param   vector map set 參數的漢字說明: 用戶提交關鍵字的分詞組,倒排索引映射,相關性結果集合
 * @return  string 0
 */
bool CQuery::GetRelevantRst
(
 vector &vecTerm,
 map &mapBuckets,
 set &setRelevantRst
) const
{
 set setSRst;

 bool bFirst=true;
 vector::iterator itTerm = vecTerm.begin();

 for ( ; itTerm != vecTerm.end(); ++itTerm )
 {

  setSRst.clear();
  copy(setRelevantRst.begin(), setRelevantRst.end(), inserter(setSRst,setSRst.begin()));

  map mapRstDoc;
  string docid;
  int doccnt;

  map::iterator itBuckets = mapBuckets.find(*itTerm);
  if (itBuckets != mapBuckets.end())
  {
   string strBucket = (*itBuckets).second;
   string::size_type idx;
   idx = strBucket.find_first_not_of(" ");
   strBucket = strBucket.substr(idx);

   while ( (idx = strBucket.find(" ")) != string::npos )
   {
    docid = strBucket.substr(0,idx);
    doccnt = 0;

    if (docid.empty()) continue;

    map::iterator it = mapRstDoc.find(docid);
    if ( it != mapRstDoc.end() )
    {
     doccnt = (*it).second + 1;
     mapRstDoc.erase(it);
    }
    mapRstDoc.insert( pair(docid,doccnt) );

    strBucket = strBucket.substr(idx+1);
   }

   // remember the last one
   docid = strBucket;
   doccnt = 0;
   map::iterator it = mapRstDoc.find(docid);
   if ( it != mapRstDoc.end() )
   {
    doccnt = (*it).second + 1;
    mapRstDoc.erase(it);
   }
   mapRstDoc.insert( pair(docid,doccnt) );
  }

  // sort by term frequencty
  multimap > newRstDoc;
  map::iterator it0 = mapRstDoc.begin();
  for ( ; it0 != mapRstDoc.end(); ++it0 ){
   newRstDoc.insert( pair((*it0).second,(*it0).first) );
  }

  multimap::iterator itNewRstDoc = newRstDoc.begin();
  setRelevantRst.clear();
  for ( ; itNewRstDoc != newRstDoc.end(); ++itNewRstDoc ){
   string docid = (*itNewRstDoc).second;

   if (bFirst==true) {
    setRelevantRst.insert(docid);
    continue;
   }

   if ( setSRst.find(docid) != setSRst.end() ){ 
    setRelevantRst.insert(docid);
   }
  }

  //cout << "setRelevantRst.size(): " << setRelevantRst.size() << "";
  bFirst = false;
 }
 return true;
}

接下來的就是現實了,前面都只是處理數據得到 setRelevantRst 這個查詢結構集合,這里就不多說了下面就和php之類的腳本語言差不多,格式化結果集合并顯示出來。
//TSESearch.cpp

view plaincopy to clipboardprint?
//下面開始顯示  
    CDisplayRst iDisplayRst;   
    iDisplayRst.ShowTop();   
 
    float used_msec = (end_tv.tv_sec-begin_tv.tv_sec)*1000   
        +((float)(end_tv.tv_usec-begin_tv.tv_usec))/(float)1000;   
 
    iDisplayRst.ShowMiddle(iQuery.m_sQuery,used_msec,   
            setRelevantRst.size(), iQuery.m_iStart);  
 
    iDisplayRst.ShowBelow(vecTerm,setRelevantRst,vecDocIdx,iQuery.m_iStart);

 

posted @ 2009-12-10 22:53 學者站在巨人的肩膀上 閱讀(1005) | 評論 (0)編輯 收藏

僅列出標題  下一頁
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产小视频| 欧美精品一区二区三区四区 | 欧美在线播放高清精品| 亚洲一区二区三区高清| 亚洲一区二区三区在线播放| 99精品视频一区| 一区二区三区四区在线| 亚洲一区精品视频| 欧美在线视频免费观看| 老司机午夜精品| 欧美色另类天堂2015| 国产精品视频99| 亚洲国产成人在线视频| 一区二区三区你懂的| 亚洲女与黑人做爰| 久久婷婷久久| 亚洲久久成人| 欧美一区二区三区精品电影| 免费在线一区二区| 国产精品热久久久久夜色精品三区| 国产欧美一区二区三区另类精品 | 欧美黑人多人双交| 国产精品久久久久久久午夜片| 国产日韩欧美日韩大片| 一区二区视频在线观看| 亚洲免费电影在线观看| 午夜精品久久久久久久99水蜜桃| 欧美在线视频播放| 亚洲日本欧美| 久久国产毛片| 欧美日韩在线不卡一区| 国产亚洲欧美日韩精品| 妖精视频成人观看www| 久久精品视频亚洲| 999在线观看精品免费不卡网站| 性欧美在线看片a免费观看| 欧美国产日韩一区二区在线观看| 国产亚洲欧美一区| 亚洲一区二区三区四区五区午夜| 美日韩精品免费观看视频| 亚洲精品一二区| 欧美一级片久久久久久久| 亚洲国产精品电影在线观看| 欧美一级片在线播放| 欧美视频一区在线| 日韩视频在线一区| 女人天堂亚洲aⅴ在线观看| 亚洲与欧洲av电影| 欧美日韩一区二区三区免费看| 在线不卡中文字幕播放| 欧美一区二区三区免费视| 日韩亚洲一区二区| 欧美国产另类| 亚洲国产精品黑人久久久| 久久香蕉国产线看观看网| 午夜精品福利一区二区蜜股av| 欧美日韩精品欧美日韩精品| 亚洲精品乱码| 欧美激情精品久久久久久变态| 久久国产99| 韩国av一区二区三区在线观看 | 国产人妖伪娘一区91| 午夜精品久久久久久久久久久久久| 欧美激情网友自拍| 亚洲欧美一区二区在线观看| 国产精品入口66mio| 亚洲一区二区在线| 亚洲最黄网站| 国产精品毛片高清在线完整版| 亚洲一区尤物| 先锋影音久久| 狠狠入ady亚洲精品经典电影| 久久久久久久精| 久久久久国色av免费观看性色| 精品福利电影| 亚洲成人资源| 欧美日本亚洲韩国国产| 亚洲一区影院| 欧美影视一区| 亚洲高清免费在线| 亚洲精品久久嫩草网站秘色| 欧美三日本三级少妇三2023 | 老**午夜毛片一区二区三区| 亚洲经典视频在线观看| 亚洲美女中文字幕| 国产精品永久免费视频| 久久偷看各类wc女厕嘘嘘偷窃| 久久久久久久尹人综合网亚洲| 亚洲欧洲精品一区二区| 一本久久综合亚洲鲁鲁| 国产香蕉久久精品综合网| 蜜桃av综合| 欧美日韩精品免费看| 欧美在线视频在线播放完整版免费观看| 午夜宅男欧美| 99精品国产99久久久久久福利| 亚洲一区二区在线| 免费成人美女女| 亚洲一区二区高清| 久久看片网站| 午夜一区在线| 欧美1区视频| 久久国产主播精品| 欧美精品一区二区在线观看| 欧美在线啊v| 欧美精品三级日韩久久| 久久一区二区三区av| 欧美日韩午夜| 欧美国产激情| 欧美一级淫片播放口| 99re热这里只有精品免费视频| 亚洲婷婷国产精品电影人久久| 激情五月***国产精品| 亚洲一级一区| 9色精品在线| 久久影院亚洲| 久久天天狠狠| 国产精品影院在线观看| 日韩视频不卡中文| 91久久夜色精品国产九色| 欧美在线短视频| 亚洲欧美日韩精品久久亚洲区 | 欧美一区三区三区高中清蜜桃 | 一本色道久久综合亚洲精品小说| 久久午夜精品一区二区| 欧美一级二级三级蜜桃| 欧美日韩第一区日日骚| 欧美成人综合网站| 国内欧美视频一区二区| 亚洲欧美日韩区| 亚洲一二三区在线| 欧美区一区二| 亚洲欧洲综合另类| 亚洲精品久久| 欧美成人按摩| 亚洲东热激情| 亚洲人成毛片在线播放女女| 久久男人av资源网站| 久久综合色天天久久综合图片| 国产午夜久久久久| 欧美中文字幕精品| 久久久久久久精| 国产一区香蕉久久| 久久免费精品视频| 欧美激情一区二区在线| 亚洲激情另类| 欧美日韩999| 亚洲视频你懂的| 欧美在线你懂的| 激情综合色综合久久| 久久综合狠狠综合久久综合88 | 女同性一区二区三区人了人一| 亚洲第一二三四五区| 免费成人高清在线视频| 亚洲激情av| 国产乱码精品一区二区三区五月婷| 亚洲成在人线av| 日韩视频免费观看高清完整版| 欧美国产日韩xxxxx| 亚洲最新色图| 欧美在线视频一区| 在线成人av.com| 欧美精品成人在线| 亚洲神马久久| 久久米奇亚洲| 日韩午夜三级在线| 国产精品入口福利| 卡通动漫国产精品| 亚洲精品字幕| 久久精品国产第一区二区三区| 尤物yw午夜国产精品视频| 欧美高清视频在线观看| 亚洲特级毛片| 欧美成年人网| 欧美一区二区在线观看| 亚洲国产国产亚洲一二三| 欧美日韩亚洲高清| 久久精品一区二区| 中文久久精品| 欧美国产免费| 午夜伦欧美伦电影理论片| 亚洲国产欧美一区| 国产日韩欧美在线一区| 欧美精品一区视频| 久久综合久色欧美综合狠狠 | 亚洲欧美中日韩| 91久久精品国产91久久性色tv| 久久精品av麻豆的观看方式| 一区二区av在线| 亚洲国产91精品在线观看| 国产欧美精品在线观看| 国产精品电影观看| 欧美精品v国产精品v日韩精品 | 欧美成人综合在线| 久久精品亚洲一区二区三区浴池| 亚洲桃色在线一区| 在线视频亚洲欧美| 一本大道av伊人久久综合| 亚洲激情二区| 欧美黄色成人网|