网络爬虫的Web Kit移植研究

2020-10-26 02:23席文强
科学与信息化 2020年29期
关键词:网络爬虫

席文强

摘 要 当今开源浏览器引擎中,Web Kit与gecko平分秋色,但对于代码结构框架,Web Kit似乎要清晰很多,因此,对于网络爬虫研究来说,Web Kit的移植研究显得尤为重要。本文通过对Web Kit浏览器内核移植目的的阐述,分析了移植过程中的各个步骤以及问题改进方法,对获取网页链接节点和实现步骤做了分析和研究。

关键词 Web Kit;JS;Web Core;网络爬虫

引言

1移植的目的

引擎的爬虫需要从给定的url中抽出尽可能多的正确链接,这不仅需要获取到页面源码中显式的url,还需要解析js,模拟一些事件来得到那些“隐藏”的链接。Web Kit可以满足这个需要。并且,为了更方便地为引擎所用,减少引擎的体积,采用了自己移植的方式。

Web Kit的移植可以分为:组建工程,实现接口,封装接口。对于不基于任何一个移植(如qt,gtk等)的移植,要做的工作非常多。但对于现在的需求,很多功能都是不需要的,这就简化了很多的工作量。对于必须要实现的接口,也都做的尽量简单[1]。

2移植工程

在移植的很多时候要参考别的平台的移植,要把每个平台的都看一下,每一个地方可能要参考不同的平台。这个地方可以参考efl的。

在各个相应的目录下建立PlatformXXX.cmake或OptionXXX.cmake。OptionXXX.cmake里包含了编译之前需要的一些信息,如编译选项的打开关闭等。在移植中,可以先把所有的关闭,通过字面意思看出需要打开的先打开,在运行时遇到问题时,要记住这边的选择,排查问题时不要忘记这边的影响。

PlatformXXX.cmake里包含要编译的源文件,依赖的库等。依赖的库先选最小集,需要时添加。源文件参考其他移植,对于平台相关的源文件,先不要加入。

这个步骤并不是一步完成的,实际上各个步骤都是穿插的,后面编译或运行时遇到的问题,都可能要回到这里修改配置文件。

2.1 实现平台相关的接口

在编译时,根据错误建立相应的目录和文件,并在PlatformXXX.cmake中添加新建的源文件。这里必须要注意的一点是,接口先定义成空实现,并在里面打印相应的信息。这样可以先通过编译,但在后面运行时可能会报错。而报错时就可以根据打印的信息确定是什么原因导致,从而实现相应的接口以使运行正常。

这些接口Web Kit之所以空出,目的就是方便各个平台的移植。对于一些平台相关的接口,Web Kit采用的方式是建立一个托管类,这个托管类中都是一些纯虚函数。这样,各个平台在做自己的移植时,就可以建立子类继承这个托管类,并实现其中的纯虚函数。还有另外一种方式,就是空出未实现的接口,由移植时实现。

FrameLoaderClientXXX.cpp中有很多函数会在加载的过程中被调用,在其中完成一些与外界的交互后,再返过去调回到Web Core内部。如果在程序执行时某个函数内中断,可以参考其他移植如qt,明确接口的含义,以及需要回调的函数,再具体实现[2]。

2.2 调用并封装接口

调用内部的接口使Web Kit运行起来。如初始化、加载页面、执行动作等。首先要定义Web View和Web Frame,Web View对应Web Core内的Page,在其中完成构造,初始化等,以及与外界的交互(提供供python调用的类和接口)。Web Frame对应Web Core内的Frame类,在这里开始页面的加载,数据,配置的传入等。

另外,对于传给Web Kit的数据和配置,以及Web Kit报出的信息,由于需要在Web Core内使用,则要在WTF内定义。

3各模块移植时的改动

Web Kit移植时需要对各个浏览器内核模块进行修改,以便于节省计算资源,对无用模块进行裁剪,同时添加回调空函数以保证有效性和可用性。

3.1 WTF模块

WTF模块这里放的都是Web Kit内部定义的一些库供其他模块使用,算是最下层的,编译的时候当然也是最先编译。里面有智能指针,各种容器,hashmap,内存分配,线程等管理的接口。其中有Platform.h文件,里面是一些宏的定义,移植的时候需要稍作修改。

一些需要传给Web Kit的配置信息,以及与外部与Web Kit交互的数据,其类的定义也要在这个模块下。因为WTF是最先编译的,而Web Core和Web Kit都有可能会用到那些结构。

3.2 Javascript Core模块

JS引擎在移植的时候几乎不需要动。但有部分内存是分配在Heap中的,jscore中的垃圾回收,如果想实时回收,则需要在这里实现那些基于定时器的接口。如果要求不高,可以在外部通过调用Web Core内提供的接口回收,GCController中的garbage CollectNow()等,但这个起的作用非常有限[3]。

3.3 Web Core模块

这部分最需要说的是定时器Timer。Web Kit中Timer实现的基本思想是:每个线程维护一个虚拟Timer的优先级队列,每次启动或停止一个虚拟Timer时,都会设置该Timer的下次触发时间(“next fire time”)。当虚拟Timer的触发时间变化时,需要调整其在优先级队列的位置,以保证队列的有效性。当虚拟Timer启动或者先前的系统Timer触发的时候,会调用由具体平台实现的set Shared Timer Fire Time函数,去设置系统Timer的等待时间,开始新一轮的超时等待。

其中,Timer是个模板类,继承于Timer Base,它就是所谓的虚拟定时器,提供了具体平台的系统Timer触发时的回调接口,以及启动和停止定时器的相关接口。另一方面,Timer Base提供了优先级队列(由堆结构实现)的访问接口,例如:heap Decrease Key用于调整堆,以保证当前定时器的下次触发时间缩短后优先级仍然有效;heap Delete从优先级队列中删除当前定时器;heap Insert向优先级队列插入定时器。Timer Base中提供的优先级访问接口直接操纵的是Thread Timers的m_timerheap成员。

因此定时器Timer一定要实现一个符合要求的。简单的定时器,比如基于时钟的信号,表面上能正常工作,但是会隐藏很多问题。比如多线程,一些段错误,还有内存泄漏。

3.4 Web Kit接口层

在这里,要构造两个重要的对象,Page和Frame,以及相关的一些对象。要进行一些必要的初始化,可以根据错误提示进行,也可以参考其他的移植[4]。

3.5 段错误问题

基于源码移植的Web Kit,跑起来肯定会有很多段错误。可以用gdb调试。例如ASSERT FAILED:这类段错误比较常见。Web Kit为了方便排查问题,尽量在错误犯下之后最早的时候通过这种方式给出提示。也就是说,这个段错误是Web Kit故意造成的,但造成的原因是Web Kit发现了异常的东西。未初始化:如果提示cannot access memory at 0x….,那有可能是这个原因。这时要考虑是不是在Web Kit移植层,该创建的对象没有创建。

参考文献

[1] 詹恒飞,杨岳湘,方宏.Nutch分布式网络爬虫研究与优化[J].计算机科学与探索,2011,5(1):68-74.

[2] 胡戎,馮仲科,蒋君志伟.基于CheerIO的MEAN Stack气象数据网络爬虫研究[J].农业机械学报,2016(6):275-282.

[3] 刘高军,夏景隆.基于Heritrix的网络爬虫研究与应用[J].软件导刊,2013,12(5):123-125.

[4] 贾海军.基于URL及上下文的主题网络爬虫研究[D].上海:上海师范大学,2014.

猜你喜欢
网络爬虫
基于分布式的农业信息检索系统的设计与实现
微信平台下的教务信息获取和隐私保护方法研究
基于网络爬虫的电子易购软件设计与实现
搜索引擎技术的发展现状与前景
炼铁厂铁量网页数据获取系统的设计与实现
基于社会网络分析的权威网页挖掘研究
主题搜索引擎中网络爬虫的实现研究
浅析如何应对网络爬虫流量
基于淘宝某商品销售量监控系统
网络爬虫针对“反爬”网站的爬取策略研究