北大天网搜索引擎TSE分析及完全注释[3]来到关键字分词及相关性分析程序

本文主要是介绍北大天网搜索引擎TSE分析及完全注释[3]来到关键字分词及相关性分析程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

有前面注释我们可以知道查询关键字和字典文件准备好好后,将进入用户关键字分词阶段

//TSESearch.cpp中:

view plain copy to clipboard print ?
  1. CHzSeg iHzSeg;      //include ChSeg/HzSeg.h   
  2.   
  3. //   
  4. iQuery.m_sSegQuery = iHzSeg.SegmentSentenceMM(iDict, iQuery.m_sQuery);  //将get到的查询变量分词分成 "我/        爱/      你们/ 的/      格式"   
  5.   
  6. vector<STRING></STRING> vecTerm;   
  7. iQuery.ParseQuery(vecTerm);     //将以"/"划分开的关键字一一顺序放入一个向量容器中   
  8.   
  9. set<STRING></STRING> setRelevantRst;    
  10. iQuery.GetRelevantRst(vecTerm, mapBuckets, setRelevantRst);    
  11.   
  12. gettimeofday(&end_tv,&tz);   
  13. // search end   
  14. //搜索完毕  
	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 plain copy to clipboard print ?
  1. 看CHzSeg 中的这个方法  
看CHzSeg 中的这个方法
view plain copy to clipboard print ?
  1. //ChSeg/HzSeg.h  
//ChSeg/HzSeg.h
view plain copy to clipboard print ?
  1. /**   
  2.  * 程序翻译说明   
  3.  * 进一步净化数据,转换汉字   
  4.  * @access  public   
  5.  * @param   CDict, string 参数的汉字说明:字典,查询字符串   
  6.  * @return  string 0   
  7.  */   
  8. // process a sentence before segmentation   
  9. //在分词前处理句子   
  10. string CHzSeg::SegmentSentenceMM (CDict &dict, string s1) const   
  11. {   
  12.     string s2="";   
  13.     unsigned int i,len;   
  14.   
  15.     while (!s1.empty())    
  16.     {   
  17.         unsigned char ch=(unsigned char) s1[0];   
  18.         if(ch<128)    
  19.         { // deal with ASCII   
  20.             i=1;   
  21.             len = s1.size();   
  22.             while (i<LEN len="s1.length();" i="0;" 中文标点等非汉字字符="" if="" else="" yhf="" s1="s1.substr(i);" by="" added="" ch="=13)" s2="" cr=""></LEN>=161)   
  23.               && (!((unsigned char)s1[i]==161 && ((unsigned char)s1[i+1]>=162 && (unsigned char)s1[i+1]<=168)))   
  24.               && (!((unsigned char)s1[i]==161 && ((unsigned char)s1[i+1]>=171 && (unsigned char)s1[i+1]<=191)))   
  25.               && (!((unsigned char)s1[i]==163 && ((unsigned char)s1[i+1]==172 || (unsigned char)s1[i+1]==161)    
  26.               || (unsigned char)s1[i+1]==168 || (unsigned char)s1[i+1]==169 || (unsigned char)s1[i+1]==186   
  27.               || (unsigned char)s1[i+1]==187 || (unsigned char)s1[i+1]==191)))    
  28.                 {    
  29.                     ii=i+2; // 假定没有半个汉字   
  30.                 }   
  31.   
  32.                 if (i==0) ii=i+2;   
  33.   
  34.                 // 不处理中文空格   
  35.                 if (!(ch==161 && (unsigned char)s1[1]==161))    
  36.                 {    
  37.                     if (i <= s1.size())  // yhf   
  38.                         // 其他的非汉字双字节字符可能连续输出   
  39.                         s2 += s1.substr(0, i) + SEPARATOR;    
  40.                     else break; // yhf   
  41.                 }   
  42.   
  43.                 if (i <= s1.size())  // yhf   
  44.                     s1s1=s1.substr(i);   
  45.                 else break;     //yhf   
  46.   
  47.                 continue;   
  48.             }   
  49.         }   
  50.        
  51.   
  52.     // 以下处理汉字串   
  53.   
  54.         i = 2;   
  55.         len = s1.length();   
  56.   
  57.         while(i<LEN></LEN>=176)    
  58. //    while(i<LEN></LEN>=128 && (unsigned char)s1[i]!=161)   
  59.             i+=2;   
  60.   
  61.         s2+=SegmentHzStrMM(dict, s1.substr(0,i));   
  62.   
  63.         if (i <= len)    // yhf   
  64.             s1s1=s1.substr(i);   
  65.         else break; // yhf   
  66.     }   
  67.   
  68.     return s2;   
  69. }  
/**
* 程序翻译说明
* 进一步净化数据,转换汉字
* @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 plain copy to clipboard print ?
  1.    
 
view plain copy to clipboard print ?
  1. //Query.cpp  
//Query.cpp
view plain copy to clipboard print ?
  1. <PRE class=csharp name="code">/**   
  2.  * 程序翻译说明   
  3.  * 将以"/"划分开的关键字一一顺序放入一个向量容器中   
  4.  *   
  5.  * @access  public   
  6.  * @param   vector<STRING></STRING> 参数的汉字说明:向量容器   
  7.  * @return  void   
  8.  */   
  9. void CQuery::ParseQuery(vector<STRING></STRING> &vecTerm)   
  10. {   
  11.     string::size_type idx;    
  12.     while ( (idx = m_sSegQuery.find("/  ")) != string::npos ) {    
  13.         vecTerm.push_back(m_sSegQuery.substr(0,idx));    
  14.         m_sSegQuerym_sSegQuery = m_sSegQuery.substr(idx+3);    
  15.     }   
  16. }   
  17. </PRE>  
  18. <PRE class=csharp name="code"> </PRE>  
  19. <PRE class=csharp name="code"><PRE class=csharp name="code">/**   
  20.  * 程序翻译说明   
  21.  * 相关性分析查询,构造结果集合setRelevantRst //瓶颈所在   
  22.  *   
  23.  * @access  public   
  24.  * @param   vector<STRING></STRING> map set<STRING></STRING> 参数的汉字说明: 用户提交关键字的分词组,倒排索引映射,相关性结果集合   
  25.  * @return  string 0   
  26.  */   
  27. bool CQuery::GetRelevantRst   
  28. (   
  29.     vector<STRING></STRING> &vecTerm,    
  30.     map &mapBuckets,    
  31.     set<STRING></STRING> &setRelevantRst   
  32. ) const   
  33. {   
  34.     set<STRING></STRING> setSRst;   
  35.   
  36.     bool bFirst=true;   
  37.     vector<STRING></STRING>::iterator itTerm = vecTerm.begin();   
  38.   
  39.     for ( ; itTerm != vecTerm.end(); ++itTerm )   
  40.     {   
  41.   
  42.         setSRst.clear();   
  43.         copy(setRelevantRst.begin(), setRelevantRst.end(), inserter(setSRst,setSRst.begin()));   
  44.   
  45.         map mapRstDoc;   
  46.         string docid;   
  47.         int doccnt;   
  48.   
  49.         map::iterator itBuckets = mapBuckets.find(*itTerm);   
  50.         if (itBuckets != mapBuckets.end())   
  51.         {   
  52.             string strBucket = (*itBuckets).second;   
  53.             string::size_type idx;   
  54.             idx = strBucket.find_first_not_of(" ");   
  55.             strBucketstrBucket = strBucket.substr(idx);   
  56.   
  57.             while ( (idx = strBucket.find(" ")) != string::npos )    
  58.             {   
  59.                 docid = strBucket.substr(0,idx);   
  60.                 doccnt = 0;   
  61.   
  62.                 if (docid.empty()) continue;   
  63.   
  64.                 map::iterator it = mapRstDoc.find(docid);   
  65.                 if ( it != mapRstDoc.end() )   
  66.                 {   
  67.                     doccnt = (*it).second + 1;   
  68.                     mapRstDoc.erase(it);   
  69.                 }   
  70.                 mapRstDoc.insert( pair(docid,doccnt) );   
  71.   
  72.                 strBucketstrBucket = strBucket.substr(idx+1);   
  73.             }   
  74.   
  75.             // remember the last one   
  76.             docid = strBucket;   
  77.             doccnt = 0;   
  78.             map::iterator it = mapRstDoc.find(docid);   
  79.             if ( it != mapRstDoc.end() )   
  80.             {   
  81.                 doccnt = (*it).second + 1;   
  82.                 mapRstDoc.erase(it);   
  83.             }   
  84.             mapRstDoc.insert( pair(docid,doccnt) );   
  85.         }   
  86.   
  87.         // sort by term frequencty   
  88.         multimap > newRstDoc;   
  89.         map::iterator it0 = mapRstDoc.begin();   
  90.         for ( ; it0 != mapRstDoc.end(); ++it0 ){   
  91.             newRstDoc.insert( pair((*it0).second,(*it0).first) );   
  92.         }   
  93.   
  94.         multimap::iterator itNewRstDoc = newRstDoc.begin();   
  95.         setRelevantRst.clear();   
  96.         for ( ; itNewRstDoc != newRstDoc.end(); ++itNewRstDoc ){   
  97.             string docid = (*itNewRstDoc).second;   
  98.   
  99.             if (bFirst==true) {   
  100.                 setRelevantRst.insert(docid);   
  101.                 continue;   
  102.             }   
  103.   
  104.             if ( setSRst.find(docid) != setSRst.end() ){       
  105.                 setRelevantRst.insert(docid);   
  106.             }   
  107.         }   
  108.   
  109.         //cout << "setRelevantRst.size(): " << setRelevantRst.size() << "<BR>";   
  110.         bFirst = false;   
  111.     }   
  112.     return true;   
  113. }</PRE>  
  114. </PRE>  
  115. 接下来的就是现实了,前面都只是处理数据得到 setRelevantRst 这个查询结构集合,这里就不多说了下面就和php之类的脚本语言差不多,格式化结果集合并显示出来。  
view plaincopy to clipboardprint?
  1. /**  
  2.  * 程序翻译说明  
  3.  * 将以"/"划分开的关键字一一顺序放入一个向量容器中  
  4.  *  
  5.  * @access  public  
  6.  * @param   vector<STRING></STRING> 参数的汉字说明:向量容器  
  7.  * @return  void  
  8.  */  
  9. void CQuery::ParseQuery(vector<STRING></STRING> &vecTerm)   
  10. {   
  11.     string::size_type idx;    
  12.     while ( (idx = m_sSegQuery.find("/  ")) != string::npos ) {    
  13.         vecTerm.push_back(m_sSegQuery.substr(0,idx));    
  14.         m_sSegQuery = m_sSegQuery.substr(idx+3);    
  15.     }   
  16. }  
view plaincopy to clipboardprint?
  1.    
 
view plaincopy to clipboardprint?
  1. <PRE class=csharp name="code">/**  
  2.  * 程序翻译说明  
  3.  * 相关性分析查询,构造结果集合setRelevantRst //瓶颈所在  
  4.  *  
  5.  * @access  public  
  6.  * @param   vector<STRING></STRING> map set<STRING></STRING> 参数的汉字说明: 用户提交关键字的分词组,倒排索引映射,相关性结果集合  
  7.  * @return  string 0  
  8.  */  
  9. bool CQuery::GetRelevantRst   
  10. (   
  11.     vector<STRING></STRING> &vecTerm,    
  12.     map &mapBuckets,    
  13.     set<STRING></STRING> &setRelevantRst   
  14. const  
  15. {   
  16.     set<STRING></STRING> setSRst;   
  17.   
  18.     bool bFirst=true;   
  19.     vector<STRING></STRING>::iterator itTerm = vecTerm.begin();   
  20.   
  21.     for ( ; itTerm != vecTerm.end(); ++itTerm )   
  22.     {   
  23.   
  24.         setSRst.clear();   
  25.         copy(setRelevantRst.begin(), setRelevantRst.end(), inserter(setSRst,setSRst.begin()));   
  26.   
  27.         map mapRstDoc;   
  28.         string docid;   
  29.         int doccnt;   
  30.   
  31.         map::iterator itBuckets = mapBuckets.find(*itTerm);   
  32.         if (itBuckets != mapBuckets.end())   
  33.         {   
  34.             string strBucket = (*itBuckets).second;   
  35.             string::size_type idx;   
  36.             idx = strBucket.find_first_not_of(" ");   
  37.             strBucket = strBucket.substr(idx);   
  38.   
  39.             while ( (idx = strBucket.find(" ")) != string::npos )    
  40.             {   
  41.                 docid = strBucket.substr(0,idx);   
  42.                 doccnt = 0;   
  43.   
  44.                 if (docid.empty()) continue;   
  45.   
  46.                 map::iterator it = mapRstDoc.find(docid);   
  47.                 if ( it != mapRstDoc.end() )   
  48.                 {   
  49.                     doccnt = (*it).second + 1;   
  50.                     mapRstDoc.erase(it);   
  51.                 }   
  52.                 mapRstDoc.insert( pair(docid,doccnt) );   
  53.   
  54.                 strBucket = strBucket.substr(idx+1);   
  55.             }   
  56.   
  57.             // remember the last one   
  58.             docid = strBucket;   
  59.             doccnt = 0;   
  60.             map::iterator it = mapRstDoc.find(docid);   
  61.             if ( it != mapRstDoc.end() )   
  62.             {   
  63.                 doccnt = (*it).second + 1;   
  64.                 mapRstDoc.erase(it);   
  65.             }   
  66.             mapRstDoc.insert( pair(docid,doccnt) );   
  67.         }   
  68.   
  69.         // sort by term frequencty   
  70.         multimap > newRstDoc;   
  71.         map::iterator it0 = mapRstDoc.begin();   
  72.         for ( ; it0 != mapRstDoc.end(); ++it0 ){   
  73.             newRstDoc.insert( pair((*it0).second,(*it0).first) );   
  74.         }   
  75.   
  76.         multimap::iterator itNewRstDoc = newRstDoc.begin();   
  77.         setRelevantRst.clear();   
  78.         for ( ; itNewRstDoc != newRstDoc.end(); ++itNewRstDoc ){   
  79.             string docid = (*itNewRstDoc).second;   
  80.   
  81.             if (bFirst==true) {   
  82.                 setRelevantRst.insert(docid);   
  83.                 continue;   
  84.             }   
  85.   
  86.             if ( setSRst.find(docid) != setSRst.end() ){       
  87.                 setRelevantRst.insert(docid);   
  88.             }   
  89.         }   
  90.   
  91.         //cout << "setRelevantRst.size(): " << setRelevantRst.size() << "<BR>";   
  92.         bFirst = false;   
  93.     }   
  94.     return true;   
  95. }</PRE>  
view plaincopy to clipboardprint?
  1. /**  
  2.  * 程序翻译说明  
  3.  * 相关性分析查询,构造结果集合setRelevantRst //瓶颈所在  
  4.  *  
  5.  * @access  public  
  6.  * @param   vector<STRING></STRING> map set<STRING></STRING> 参数的汉字说明: 用户提交关键字的分词组,倒排索引映射,相关性结果集合  
  7.  * @return  string 0  
  8.  */  
  9. bool CQuery::GetRelevantRst   
  10. (   
  11.     vector<STRING></STRING> &vecTerm,    
  12.     map &mapBuckets,    
  13.     set<STRING></STRING> &setRelevantRst   
  14. const  
  15. {   
  16.     set<STRING></STRING> setSRst;   
  17.   
  18.     bool bFirst=true;   
  19.     vector<STRING></STRING>::iterator itTerm = vecTerm.begin();   
  20.   
  21.     for ( ; itTerm != vecTerm.end(); ++itTerm )   
  22.     {   
  23.   
  24.         setSRst.clear();   
  25.         copy(setRelevantRst.begin(), setRelevantRst.end(), inserter(setSRst,setSRst.begin()));   
  26.   
  27.         map mapRstDoc;   
  28.         string docid;   
  29.         int doccnt;   
  30.   
  31.         map::iterator itBuckets = mapBuckets.find(*itTerm);   
  32.         if (itBuckets != mapBuckets.end())   
  33.         {   
  34.             string strBucket = (*itBuckets).second;   
  35.             string::size_type idx;   
  36.             idx = strBucket.find_first_not_of(" ");   
  37.             strBucket = strBucket.substr(idx);   
  38.   
  39.             while ( (idx = strBucket.find(" ")) != string::npos )    
  40.             {   
  41.                 docid = strBucket.substr(0,idx);   
  42.                 doccnt = 0;   
  43.   
  44.                 if (docid.empty()) continue;   
  45.   
  46.                 map::iterator it = mapRstDoc.find(docid);   
  47.                 if ( it != mapRstDoc.end() )   
  48.                 {   
  49.                     doccnt = (*it).second + 1;   
  50.                     mapRstDoc.erase(it);   
  51.                 }   
  52.                 mapRstDoc.insert( pair(docid,doccnt) );   
  53.   
  54.                 strBucket = strBucket.substr(idx+1);   
  55.             }   
  56.   
  57.             // remember the last one   
  58.             docid = strBucket;   
  59.             doccnt = 0;   
  60.             map::iterator it = mapRstDoc.find(docid);   
  61.             if ( it != mapRstDoc.end() )   
  62.             {   
  63.                 doccnt = (*it).second + 1;   
  64.                 mapRstDoc.erase(it);   
  65.             }   
  66.             mapRstDoc.insert( pair(docid,doccnt) );   
  67.         }   
  68.   
  69.         // sort by term frequencty   
  70.         multimap > newRstDoc;   
  71.         map::iterator it0 = mapRstDoc.begin();   
  72.         for ( ; it0 != mapRstDoc.end(); ++it0 ){   
  73.             newRstDoc.insert( pair((*it0).second,(*it0).first) );   
  74.         }   
  75.   
  76.         multimap::iterator itNewRstDoc = newRstDoc.begin();   
  77.         setRelevantRst.clear();   
  78.         for ( ; itNewRstDoc != newRstDoc.end(); ++itNewRstDoc ){   
  79.             string docid = (*itNewRstDoc).second;   
  80.   
  81.             if (bFirst==true) {   
  82.                 setRelevantRst.insert(docid);   
  83.                 continue;   
  84.             }   
  85.   
  86.             if ( setSRst.find(docid) != setSRst.end() ){       
  87.                 setRelevantRst.insert(docid);   
  88.             }   
  89.         }   
  90.   
  91.         //cout << "setRelevantRst.size(): " << setRelevantRst.size() << "<BR>";   
  92.         bFirst = false;   
  93.     }   
  94.     return true;   
  95. }  
接下来的就是现实了,前面都只是处理数据得到 setRelevantRst 这个查询结构集合,这里就不多说了下面就和php之类的脚本语言差不多,格式化结果集合并显示出来。

//TSESearch.cpp

view plain copy to clipboard print ?
  1. //下面开始显示   
  2.     CDisplayRst iDisplayRst;    
  3.     iDisplayRst.ShowTop();    
  4.   
  5.     float used_msec = (end_tv.tv_sec-begin_tv.tv_sec)*1000    
  6.         +((float)(end_tv.tv_usec-begin_tv.tv_usec))/(float)1000;    
  7.   
  8.     iDisplayRst.ShowMiddle(iQuery.m_sQuery,used_msec,    
  9.             setRelevantRst.size(), iQuery.m_iStart);   
  10.   
  11.     iDisplayRst.ShowBelow(vecTerm,setRelevantRst,vecDocIdx,iQuery.m_iStart); 

这篇关于北大天网搜索引擎TSE分析及完全注释[3]来到关键字分词及相关性分析程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/670220

相关文章

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

c# checked和unchecked关键字的使用

《c#checked和unchecked关键字的使用》C#中的checked关键字用于启用整数运算的溢出检查,可以捕获并抛出System.OverflowException异常,而unchecked... 目录在 C# 中,checked 关键字用于启用整数运算的溢出检查。默认情况下,C# 的整数运算不会自

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

Spring中Bean有关NullPointerException异常的原因分析

《Spring中Bean有关NullPointerException异常的原因分析》在Spring中使用@Autowired注解注入的bean不能在静态上下文中访问,否则会导致NullPointerE... 目录Spring中Bean有关NullPointerException异常的原因问题描述解决方案总结

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

python-nmap实现python利用nmap进行扫描分析

《python-nmap实现python利用nmap进行扫描分析》Nmap是一个非常用的网络/端口扫描工具,如果想将nmap集成进你的工具里,可以使用python-nmap这个python库,它提供了... 目录前言python-nmap的基本使用PortScanner扫描PortScannerAsync异