本文共 2264 字,大约阅读时间需要 7 分钟。
根据驻留在内存里的set集合,取出没有爬取的网页连接,然后就去把它下载下来.
比如,下载了1000个网页,然后把这1000个HTML都放到一个文件里去,这个文件可能叫TianWang.raw.8415
意思就是线程号为8415的取的原始网页集合文件
对于每个在TianWang.raw.8415中的记录,都有一个对应的类叫CDocument(有点类似CPage.)
需要建立一个表,对每个记录(CDocument)在原始网页文件中的偏移,然后顺便提取他的网页内容摘要进行记录.
之后建立一个url摘要对应记录号的表.
好,这个过程的作用是什么呢?
比如某个时候,我想要提取url为的网页内容. 首先我去打开这个TianWang.raw.8415文件,然后
对求MD5 摘要,通过这个摘要,找出这个url在TianWang.raw.8415中是第5个记录,那么知道了
他是第5个记录,再去查看他在TianWang.raw.8415中的偏移是1024,然后去读取接下来的网页,读多长,取决
于记录头中的长度字段信息.
以下是建立 记录<-->偏移量过程的关键代码,位于DocIndex.cpp中
while (getline(ifs, strLine)) {
if (strLine[0]=='/0' || strLine[0]=='#' || strLine[0]=='/n'){ nOffset = ifs.tellg(); continue; }ofsDoc << iDocument.m_nDocId ;
ofsDoc << "/t" << iDocument.m_nPos ;}
TSE的字典用的是STL 中的MAP.关于英文字母的trie字典树,是一个26 叉树,查找效率0(logn).
现在,要把一篇网页内容分割成一个一个的关键词.TSE用的是最大正向减字法分词.
先用一个很大的数组接受html里,除了<>这些标签外的文字.
分成一个一个的句子来处理.
对一个句子,每次按照长度为ComLen来提取关键字,先用一个指针char* start指示开头,用char* end来指示
待匹配字符串尾. 如果start到end在字典里有匹配的词,就后移一个ComLen,继续匹配;如果没有这个词,就把
end往前移动一个位置继续匹配,直到又找到一个词,然后把start移动这个位置的后一个,end移动到
start+ComLen的位置,继续匹配.
关键步骤是无法匹配后,减少一个字符继续查字典,比如按照步长m来处理平均长度为d的句子,有k个句子
最坏情况是每次步长处理的时候,都没有找到匹配的单词,那么每次步长都要比较m次,查字典假设是红黑树
o(logn)的复杂度,那么最坏情况下 匹配成功一次后(只成功匹配了一个字符),start往后移动一个位置,所以总
共是mkdO(logn)
最大正向减字法,每次查字典的时候都是从最左边开始找,这是中文特有的分词,英文的话就按照空格可以
直接提取单词来匹配了.
分词的代码在HzSeg.cpp中。
对raw格式的网页内容 进行分割的代码在DocSegment.cpp中
前面已经建立好2个表,一个是url对应着记录号,一个是记录号对应的偏移。
现在开始对网页进行处理,实际上只用到第2张表。
遍历这张表,把一个一个的记录取出来,存到CDocument对象里,将来要用时就知道
这个记录在原始文件raw里的偏移是多少,可以跳到那个位置去读
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);}然后从vector里面取出每个记录号,读取一个记录的所有内容(包括头)
然后移动致实际内容开始的地方
// skip Head
int bytesRead = 0,newlines = 0; while (newlines != 2 && bytesRead != HEADER_BUF_SIZE-1) { if (*s == ' ') newlines++; else newlines = 0; s++; bytesRead++; } 把接下来的html正文内容传给iDocument.m_sBodyNoTags = s;最后执行分词
string strLine = iDocument.m_sBodyNoTags;
CHzSeg iHzSeg;
strLine = iHzSeg.SegmentSentenceMM(iDict,strLine); 分词的结果是记录ID号对应以"/"分割的关键字重定向到正向索引文件中:
fout << docId << endl << strLine;
fout << endl; 根据这些记录,生成一个文件
转载地址:http://vjmrb.baihongyu.com/