博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TSE网页存储、中文分词、倒排索引生成
阅读量:2490 次
发布时间:2019-05-11

本文共 2264 字,大约阅读时间需要 7 分钟。

  • TSE网页存储

 

根据驻留在内存里的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中文分词

 

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)

最大正向减字法,每次查字典的时候都是从最左边开始找,这是中文特有的分词,英文的话就按照空格可以

直接提取单词来匹配了.

 

  • TSE倒排索引生成

 

分词的代码在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/

你可能感兴趣的文章
spring boot jpa 实现拦截器
查看>>
jenkins + maven+ gitlab 自动化部署
查看>>
Pull Request流程
查看>>
Lambda 表达式
查看>>
函数式数据处理(一)--流
查看>>
java 流使用
查看>>
java 用流收集数据
查看>>
java并行流
查看>>
CompletableFuture 组合式异步编程
查看>>
mysql查询某一个字段是否包含中文字符
查看>>
Java中equals和==的区别
查看>>
JVM内存管理及GC机制
查看>>
Java:按值传递还是按引用传递详细解说
查看>>
Java中Synchronized的用法
查看>>
阻塞队列
查看>>
linux的基础知识
查看>>
接口技术原理
查看>>
五大串口的基本原理
查看>>
PCB设计技巧与注意事项
查看>>
linux进程之间通讯常用信号
查看>>