参考 论文: 一种可扩展的高效链接提取模型的实现与验证
作为一个爬虫,最基本的便是能够从各个页面中提取URL,这里介绍我实现的提取器。基于可扩展性,我首先实现了一个不针对任何元素的HTML元素提取,即可以提取所有的元素,并通过HOOK的模型,再根据具体需要实现不同的HOOK来获得针对性的信息。当然爬虫的HOOK便是获取URL。
HOOK的接口大致如下:
// [消息通知接口]
void begin_parser()
void begin_element()
void end_parser()
void end_element()
// [具体处理接口]
void get_element_name(...)
void get_attr_name(...)
void get_attr_value(...)
基础提取器的过程大致如下:
获得元素名 hook.get_element_name(...)
获得属性名 hook.get_attr_name(...)
获得属性值 hook.get_attr_value(...)
获得属性名 hook.get_attr_name(...)
获得属性值 hook.get_attr_value(...)
……
如此循环直到分析完页面。
由于考虑了可扩展性,或多火或少的会对性能有些影响,比如我们要实现一个完全针对性的URL分析,则可以减少多次的元素,属性等的提取,此过程还有多次无意义的字符判断。因此我改变了 hook 的接口,把 get_element_name() 的返回值设置为 bool 值,这样提取器便可以通过hook的接口得到不同的hook程序对不同的元素信息的关心情况,做出适当的处理,在我的实现中,该函数返回true,表示关心该元素的情况,false反之,如果是不关心的话,提取器直接跳到下一个元素进行分析,这样无疑提高了分析器的性能,使得它同针对性的提取器性能差距缩小。还有上面的begin_parser() begin_element()等通知函数是为了让不同的hook能知道当前提取器的工作情况,以方便处理获得的数据信息。
不过在页面分析前,有必要对页面数据进行一次预处理,比如爬虫时对脚本,注释的过滤,因此我在提取器中加入一个HTML过滤器,可根据不同需要来设置不同的过滤器,在本爬虫中,我派生一个过滤器 html_filter 用于把脚本和注释进行过滤。
我的爬虫中的URL提取器大致就是这样,下面是部分代码 :
加入这两个宏纯粹是为了代码紧凑些。一个用于判断是否分析到数据流的结尾,另一个加入多少有点SB,如果flag为真,返回ret_code。HOHO
#define return_if_end(rs) do{ if(rs == rs_end_of_file) return rs_end_of_file;}while(0)
#define return_if(flag,ret_code) do{ if(flag) return ret_code;}while(0)
const string cauc_html_parser::m_brank = " ";
void cauc_html_parser::set_stream(istream& is)
{
this->istream_it = istream::_Iter(is);
}
bool cauc_html_parser::handle_by_hook(Command cmd)