WebDriver实现

WebDriver是QT4W定义的用于解析Dom结构的中间层,根据输入的Xpath来定位的HTML控件,并操作其属性。在WebDriver初始化的时候,需要传入一个WebView对象,并且通过该对象来实现eval_script()方法。其他获取或者设置元素属性的方法实现依赖于eval_script()方法。WebDriver的具体实现会继承IWebDriver,并实现其中定义的方法。IWebDriver定义见*API文档*。

在QT4W中实现了WebDriverBase类,实现了IWebDriver的接口。正如上面所言,接口中的很多方法都是通过JS方法实现的。在WebDriverBase中,我们顶一个成员变量driver_script,该成员变量中存放的是已经写好的JS方法。通过注入执行这些JS方法,来获取Dom操作能力。具体的WebDriverBase实现可以查看*接口文档*。

在实现自己的WebDriver时可以直接继承WebDriverBase类。这里需要指出的是,由于这里涉及的JS代码以及Xpath的解析工作,在不同的浏览器上此处的实现可能会有所差异,很多时候需要重写一下eval_script方法,这里就说明一下如何来实现Driver中的eval_script方法,实现如下所示:

    def eval_script(self, frame_xpaths, script):
        '''在指定frame中执行JavaScript,并返回执行结果(该实现需要处理js基础库未注入情况的处理)
        :param frame_xpaths: frame元素的XPATH路径,如果是顶层页面,怎传入“[]”
        :type frame_xpaths:  list
        :param script:       要执行的JavaScript语句
        :type script:        string
        '''
        from qt4w.util import JavaScriptError, ControlNotFoundError, ControlAmbiguousError
        try:
            return self._webview.eval_script(frame_xpaths, script)
        except JavaScriptError, e:
            err_msg = e.message
            err_msg = err_msg.split('\n')[0]  # 错误堆栈信息可能会有影响
            
            if isinstance(err_msg, unicode): err_msg = err_msg.encode('utf8')
            if ('ReferenceError' in err_msg or 'TypeError' in err_msg) and 'qt4w_driver_lib' in err_msg:
                # ie8 TypeError ie9 ReferenceError
                # 注入js基础库
                self.eval_script(e.frame, self.driver_script)
                # 再次执行待指定的JS代码
                return self.eval_script(frame_xpaths, script)
            elif 'Find element' in err_msg and 'failed' in err_msg:
                # 未找到元素
                raise ControlNotFoundError(err_msg)
            elif 'Find' in err_msg and 'elements match' in err_msg:
                #找到多个元素
                err_msg += self._get_dom_tree(frame_xpaths)
                raise ControlAmbiguousError(err_msg)
            else:
                raise e

在此处eval_script实现中采用后置结构,首先治理直接调用WebView.eval_script()执行传入的JS代码,如果执行失败后,通过获取的Error信息,来判断错误原因。如果是因为引入qt4w_driver_lib错误,就先注入JS代码库,然后在执行需要执行的JS脚本。在重写该方法时,推荐采用类似的方法。