• 在 Selenium 中让 PhantomJS 执行它的 API


    from selenium import webdriver
    driver = webdriver.PhantomJS()
    script = "var page = this; page.onResourceError = function(res) {page.browserLog.push({'url': res.url, 'status': res.status});};"
    driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
    driver.execute('executePhantomScript', {'script': script, 'args': []})
    driver.get('http://www.baidu.com')
    print(driver.get_log('browser'))
    
    
    

      

    需要注意的是,1) PhantomJS 脚本中必须执行语句var page = this,然后通过 page 变量来调用 API,否则会失败。
    2) driver.get_log('browser')同样也会得到页面的 console.log 的输出,需要进行过滤。它的输出格式是{"level": level, "message": message, "timestamp": timestamp},可以通过filter(lambda x: 'url' in x, driver.get_log('browser'))语句过滤掉。
    3) 这个方法仅限于 PhantomJS,

    摘自:http://www.jianshu.com/p/23a6f6fd6268

    Selenium获取PhantomJS输出

    0 背景

    最近在做对网站的自动化测试,最开始使用 Python Requests 进行测试,测试通过,然而页面还是会出现这样那样问题。一方面是因为测试用例还不够详细,另一方面,Requests 是 url 层面或者说 api 层面的测试,并没有完全模拟用户在浏览器中的操作。比如,页面有些元素是 JS 动态生成的,Requests 是无法得到的;或者页面中的 img 或者 script 链接坏了,用 Requests 的话就需要去解析 html 了,这样如果网站对排版做一点点改动就要重写测试用例,非常费时费力。
    经过一番搜索,了解到两个神器 Selenium 和 PhantomJS。关于这两个软件,就简单说一下,Selenium 是一个Web浏览器自动化测试框架,而 PhantomJS 是一个基于 Webkit 的无 UI 的浏览器,详细介绍请自行搜索。

    1 目的

    测试页面中哪些链接是坏的。

    2 遇到的问题

    Selenium 可以通过 PhantomJS 获取实际显示的页面(JS 动态生成的元素也可以得到),并且可以模拟用户对页面操作,但是上面提到的页面中的链接坏了或者页面的跳转,它也是无法感知的,这些动作其实在 PhantomJS 中都可以得到,但是如果没有做处理,在 Selenium 中是无法直接得到的。

    3 解决

    在 PhantomJS 中,可以通过许多的句柄来获取页面的动作。比如下面这个脚本可以记录整个页面访问的过程(netlog.js):

    "use strict";
    var page = require('webpage').create(),
        system = require('system'),
        address;
    
    if (system.args.length === 1) {
      console.log('Usage: netlog.js <some URL>');
      phantom.exit(1);
    } else {
      address = system.args[1];
    
      page.onResourceRequested = function (req) {
        console.log('requested: ' + JSON.stringify(req, undefined, 4));
      };
    
      page.onResourceReceived = function (res) {
        console.log('received: ' + JSON.stringify(res, undefined, 4));
      };
    
      page.open(address, function (status) {
        if (status !== 'success') {
          console.log('FAIL to load the address');
        }
        phantom.exit();
      });
    }

    执行phantomjs netlog.js http://www.baidu.com,可以得到如下类似的输出:

    requested: {
        "headers": [
            {
                "name": "Accept",
                "value": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
            },
            {
                "name": "User-Agent",
                "value": "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1"
            }
        ],
        "id": 1,
        "method": "GET",
        "time": "2017-01-05T03:42:14.125Z",
        "url": "http://www.baidu.com/"
    }
    received: {
        "body": "",
        "bodySize": 215,
        "contentType": "text/html",
        "headers": [
            {
                "name": "Date",
                "value": "Thu, 05 Jan 2017 03:42:14 GMT"
            },
            {
                "name": "Content-Type",
                "value": "text/html"
            },
            {
                "name": "Content-Length",
                "value": "215"
            },
    
    ...

    Selenium 正常调用 PhantomJS 的方法如下(Python 语言,下同):

    from selenium import webdriver
    driver = webdriver.PhantomJS()
    driver.get('http://www.baidu.com')
    print(driver.get_log('browser'))

    其中最后一条语句可以得到页面的 console.log 的输出,同时会生成一个 ghostdriver.log 的文件,其中是 PhantomJS 的日志。
    接下来就是如何在 Selenium 中获取 PhantomJS 的输出了。

    首先是在 Selenium 中让 PhantomJS 执行它的 API 的 Hack(参考):

    driver = webdriver.PhantomJS()
    script = "this.onResourceError = function(res) {console.log(JSON.stringify({'url': res.url, 'status': res.status}));};"
    driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
    driver.execute('executePhantomScript', {'script': script, 'args': []})

    但是这样通过driver.get_log('browser')是得不到想要的内容的,因为虽然和页面 JS 的 console.log 是同样的名字,然而 PhantomJS API 的 console.log 的输出是在刚才提到的 ghostdriver.log 文件中,当然你也可以每次就读取该文件来获取内容(可以通过 webdriver 的 service_log_path 参数来设置文件名)。笔者觉得这样不够优雅,于是继续……
    通过阅读 PhantomJS 的源码,终于在 session.js 找到了一个隐藏的变量 browserLog 来实现这个功能,这个变量其实就是driver.get_log('browser')读取的变量,把你想要的内容藏在这个变量里就好了。

    from selenium import webdriver
    driver = webdriver.PhantomJS()
    script = "var page = this; page.onResourceError = function(res) {page.browserLog.push({'url': res.url, 'status': res.status});};"
    driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
    driver.execute('executePhantomScript', {'script': script, 'args': []})
    driver.get('http://www.baidu.com')
    print(driver.get_log('browser'))

    需要注意的是,1) PhantomJS 脚本中必须执行语句var page = this,然后通过 page 变量来调用 API,否则会失败。
    2) driver.get_log('browser')同样也会得到页面的 console.log 的输出,需要进行过滤。它的输出格式是{"level": level, "message": message, "timestamp": timestamp},可以通过filter(lambda x: 'url' in x, driver.get_log('browser'))语句过滤掉。
    3) 这个方法仅限于 PhantomJS,其他的 WebDriver 还没有测试过。



    作者:JerryKFC
    链接:http://www.jianshu.com/p/23a6f6fd6268
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    QtDBus编程详解
    QProcess详解
    python 爬虫 亚航 指定日期间的航线
    python 模块
    centos postgres 安装、远程连接
    python 爬虫 anyproxy
    python_scrapy_filespipe重写
    python_xpath
    常见问题汇总
    python_scrapy_log日志
  • 原文地址:https://www.cnblogs.com/saryli/p/7727731.html
Copyright © 2020-2023  润新知