TSE中提取HTML中链接的方法
来源:互联网 发布:粉笔直播课mac客户端 编辑:程序博客网 时间:2024/05/21 15:44
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))
{
yy_switch_to_buffer(buf);
__base_uri = (struct uri *)pg_uri;
__is_our_base = 0;
__onfind = onfind;
__arg = arg;
BEGIN INITIAL;
n = yylex();
}
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. */
for (yyleng = 0; __elems[yyleng].name; yyleng++)
{
if (strcasecmp(yytext + 1, __elems[yyleng].name) == 0)
{
__cur_elem = __elems + yyleng;
break;
}
}
其中数组的定义为
static struct __elem __elems[] = {
{"A", __elem_a_attr},
{"AREA", __elem_area_attr},
{"BASE", __elem_base_attr},
{"FRAME", __elem_frame_attr},
{"IFRAME", __elem_iframe_attr},
{"IMG", __elem_img_attr},
{"LINK", __elem_link_attr},
{"META", __elem_meta_attr},
{NULL, }
};
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;
while (!HLINK_ISBLANK(yytext[yyleng]) && yytext[yyleng] != '=')
yyleng++;
yytext[yyleng] = '/0';
然后把属性值 就是"href"串 存到 char *__cur_attr中,并用__curpos来标记存放uri的数组_buffer的位置
for (yyleng = 0; __cur_elem->attrs[yyleng]; yyleng++)
{
if (strcasecmp(yytext, __cur_elem->attrs[yyleng]) == 0)
{
__curpos = __buffer;
__cur_attr = __cur_elem->attrs[yyleng];
break;
}
}
进入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}/" |
<SINGLE_QUOTED>{blank}{0,512}"'" |
<UNQUOTED>{blank}|">" {
读取完毕后的操作是,首先在读取到的字符串后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中链接的方法
- 从HTML文档中提取链接
- 从HTML中提取正文的简单方法
- Qt处理html 提取链接的最快速方法
- HTML中提取图片的SRC路径
- 提取html中table的正则表达式
- 提取网页中所有链接
- 从HTML代码中提取文字,去掉HTML的标记
- php提取HTML中字符
- 提取网页中链接和标题的正则表达式
- 提取网页中链接和标题的正则表达式
- 提取图片中文字的方法
- 字符窜中提取中文的方法
- 另类提取Word中图片的方法
- 提取字符串中url的方法
- ogre中提取阴影锥的方法
- 身份证号码中,年龄、性别的提取方法
- ogre中提取阴影锥的方法
- CSS 代码格式化工具
- 手机报纸略探
- 印度对IT人才开发的计划和措施
- JAVA中jar文件的编写和应用
- mvnForum管理文档
- TSE中提取HTML中链接的方法
- 印度国家教育上的政策
- Ajax技术:构建动态的Java应用程序
- JavaScript真相报告(来自mozilla,兼推荐一个好用的web幻灯片系统)
- TSE代码爬取流程分析
- Java性能优化技巧集锦
- 银行资产流失统计
- 面向Java开发人员的Ajax:Java对象序列化
- 深入浅出Java设计模式之迭代器模式