TSE中提取html中链接 uri 采用的是Lex分析 TSE中和lex相关的是hlink.l和uri.l
其中 uri.l是用来处理一个提取出的uri ,hlink.l是用来提取html中链接的。 代码流程:
在Crawl类的DownloadFile()方法中,当取得一个网页(HTML)的内容,并存到一个CPage类里。 开始对CPage类进行分析处理。先是处理这个网页的uri uri_parse_string(iPage.m_sUrl.c_str(), &page_uri); 结果存到page_uri里去。 之后调用hlink_detect_string(iPage.m_sContent.c_str(), &page_uri, onfind, &p); 这个hlink_detect_string函数是关键函数,这个函数的意思就是,把网页内容作为参数(iPage.m_sContent.c_str())传进去,当找到有链接信息后就调用onfind函数,onfind函数的参数是&p. hlink_detect_string函数是在hlink.l中定义的。
int hlink_detect_string(const char *string, const struct uri *pg_uri,onfind_t onfind, void *arg) 参数string就是传入的网页内容,pg_uri是这篇网页的地址,onfind是找到链接后要执行的函数,arg是参数,会一直带着走的。
if (buf = yy_scan_string(string)) BEGIN INITIAL; }
buf = yy_scan_string(string)和 yy_switch_to_buffer告诉程序,需要分析的字符串是参数string 并把传入的参数存为全局变量。 之后进入INITIAL状态,yylex()函数启动分析流程。
在INITIAL状态下 遇到以下表达式的话 "<"{cdata}/{blank}|">" 就是说,遇到类似 "<A>"或者" <A "的话,就把"A" 那一行对应的数组 赋给__cur_elem全局结构。比如,搜索到"<A "就把{"A", __elem_a_attr}赋给__cur_elem.相关代码为: /* Element names are case-insensitive. */ 其中数组的定义为 static struct __elem __elems[] = { static const struct __elem *__cur_elem;
之后进入ATTRIBUTE状态 yy_push_state(ATTRIBUTE);
在ATTRIBUTE状态下 想要找出ATTRIBUTE的值 比如 A href= 首先取得href (没有"=") 此时匹配的字符串yytext为"href" 就是把空格和等号去掉后的字符串 相关代码为
匹配的正则表达式:{cdata}{blank}{0,512}"="{blank}{0,512} 去掉空格和等号: yyleng = 0;
然后把属性值 就是"href"串 存到 char *__cur_attr中,并用__curpos来标记存放uri的数组_buffer的位置 for (yyleng = 0; __cur_elem->attrs[yyleng]; yyleng++) 进入URI状态,准备提取URI BEGIN URI;
在URI状态下,如果遇到双引号,就进入双引号状态,反之单引号也一样 <URI>/"{blank}{0,512} BEGIN DOUBLE_QUOTED; <URI>"'"{blank}{0,512} BEGIN SINGLE_QUOTED; 就是说 现在已经读了<A href=" 准备读取实际的uri了 也就是一般会进入这个动作: <UNQUOTED,DOUBLE_QUOTED,SINGLE_QUOTED,ENTITY>.|/n .|/n 就是除了读取到 引号之前的字符 (因为引号代表href="xxx" xxx读取完毕) 当然也不包括"<"这些很特殊的HTML代码。
读到字符时,最关键的语句是 *__curpos++ = *yytext; 就是把字符读到_curpos指向的内存数组中去,并把_curpos指针加1,就这样一直读,直到把uri读取完毕,也就是读取到引号之类的
<DOUBLE_QUOTED>{blank}{0,512}/" |
读取完毕后的操作是,首先在读取到的字符串后2位,全部加上结束字符"/0", *(__curpos + 1) = *__curpos = '/0';
用一个指针指向uri数组的起始位置 ptr = __buffer; 之后把string类型的字符数组,存到uri结构体去 yyleng = uri_parse_buffer(ptr, __curpos - ptr + 2, &uri); 然后把找到的uri和该uri所在的uri merge成一个最终uri result uri_merge(&uri, __base_uri, result);
最终调用onfind函数 __onfind(__cur_elem->name, __cur_attr,result, __arg)
关于_onfind函数的调用 是一旦找到一个合法的uri 就会调用 所以在扫描一篇HTML时会多次调用onfind函数
onfind函数的功能 在获得的uri 如果是img类型 就存到m_ofsLink4HistoryFile文件里去 如果是其他类型 就交给AddUrl函数处理
这个是TSE中Lex 分析HTML过程的大致流程 以后再写TSE的主代码如何爬取网页的流程 |
TSE中提取HTML中链接的方法
最新推荐文章于 2024-07-12 20:49:16 发布