zoukankan      html  css  js  c++  java
  • Python selenium的js扩展实现

    python写的数据采集,对一般有规律的页面用 urllib2 + BeautifulSoup + 正则就可以搞定。 但是有些页面的内容是通过js生成,或者通过js跳转的,甚至js中还加入几道混淆机制;对这种涉及页面脚本解析的内容,前面的方式便很无力。

    这时我们需要能解析、运行js的引擎——浏览器,而python selenium能提供程序与浏览器的交互接口,再加上phantomjs这个可以后台运行的浏览器,即使用 selenium + phantomjs 便可以解决以上的问题。

    selenium可以操作页面的元素,并且提供执行js脚本的接口。但其调用js脚本后并不能直接返回执行的结果,这样再采集内容的过程中就会受到一些限制。 比如我们想使用页面中的函数进行数据转换,或者获取iframe里的内容,这些js产生数据要传回比较麻烦。

    所以我便写一个简化js数据回传的扩展 exescript.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #
    # created by heqingpan
    
    _init_js="""
    (function (){
    if (window.__e)
    { return;
    }
    var e=document.createElement('div');
    e.setAttribute("id","__s_msg");
    e.style.display="none";
    document.body.appendChild(e);
    window.__e=e;
    })();
    window.__s_set_msg=function(a){
        window.__e.setAttribute("msg",a.toString()||"");
    }
    """
    _loadJsFmt="""
    var script = document.createElement('script');
    script.src = "{0}";
    document.body.appendChild(script);
    """
    _jquery_cdn="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js"
    _warpjsfmt="__s_set_msg({0})"
    
    class ExeJs(object):
        def __init__(self,driver,trytimes=10):
            from time import sleep
            self.driver=driver
            driver.execute_script(_init_js)
            while trytimes >0:
                try:
                    self.msgNode=driver.find_element_by_id('__s_msg')
                    break
                except Exception:
                    sleep(1)
                    trytimes -= 1
            if self.msgNode is None:
                raise Exception()
        def exeWrap(self,jsstr):
            """ jsstr 执行后有返回值,返回值通过self.getMsg()获取 """
            self.driver.execute_script(_warpjsfmt.format(jsstr))
        def loadJs(self,path):
            self.execute(_loadJsFmt.format(path))
        def loadJquery(self,path=_jquery_cdn):
            self.loadJs(path)
        def execute(self,jsstr):
            self.driver.execute_script(jsstr)
        def getMsg(self):
            return self.msgNode.get_attribute('msg')
    
    

    打开ipython上一个例子,获取博客园首页文章title列表

    from selenium import webdriver
    import exescript
    
    d=webdriver.PhantomJS("phantomjs")
    d.get("http://www.cnblogs.com/")
    exejs=exescript.ExeJs(d)
    exejs.exeWrap('$(".post_item").length')
    print exejs.getMsg()
    #out: 
    """
    20
    """
    
    jsstr="""(function(){
    var r=[];
    $(".post_item").each(function(){
      var $this=$(this);
      var $h3=$this.find("h3");
      r.push($h3.text());
    });
    return r.join(',');})()"""
    exejs.exeWrap(jsstr)
    l=exejs.getMsg()
    for title in l.split(','):
        print title
    
    #out:
    """
    mac TeamTalk开发点点滴滴之一——DDLogic框架分解上
    The directfb backend was supported together with linux-fb backend in GTK+2.10
    Science上发表的超赞聚类算法
    功能齐全、效率一流的免费开源数据库导入导出工具(c#开发,支持SQL server、SQLite、ACCESS三种数据  库),每月借此处理数据5G以上
    企业级应用框架(三)三层架构之数据访问层的改进以及测试DOM的发布
    Unity3D 第一季 00 深入理解U3D开发平台
    Welcome to Swift (苹果官方Swift文档初译与注解二十一)---140~147页(第三章--集合类型)
    appium简明教程(11)——使用resource id定位
    SQL语句汇总(终篇)—— 表联接与联接查询
    fopen警告处理方式
    AndroidWear开发之HelloWorld篇
    AMD and CMD are dead之KMD.js版本0.0.2发布
    SQL语句汇总(三)——聚合函数、分组、子查询及组合查询
    DevExpress GridControl功能总结
    ASP.NET之Jquery入门级别
    2014年前端面试经历
    grunt源码解析:整体运行机制&grunt-cli源码解析
    跟用户沟通,问题尽量分析清楚,以及解决问题
    ASP.NET之Ajax系列(一)
    算法复杂度分析
    """
    
  • 相关阅读:
    atomic,nonatomic
    iOS开发-retain/assign/strong/weak/copy/mutablecopy/autorelease区别
    MagicalRecord的使用(第三方库实现的数据库)
    深浅拷贝
    C中的预编译宏定义
    省电的iPhone定位
    ASP连接读写ACCESS数据库实例(转)
    【摘要】JavaScript 的性能优化:加载和执行
    PC端网站跳转手机端网站
    多行未知文本垂直居中
  • 原文地址:https://www.cnblogs.com/shizioo/p/3813929.html
Copyright © 2011-2022 走看看