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系列(一)
    算法复杂度分析
    """
    
  • 相关阅读:
    强化学习的基本迭代方法
    基于文本描述的事务聚类
    学习强化学习之前需要掌握的3种技能
    其它 华硕 ASAU S4100U 系统安装 win10安装 重装系统 Invalid Partition Table 解决
    数据分析 一些基本的知识
    Python 取样式的内容 合并多个文件的样式 自定义样式
    电商 Python 生成补单公司需要的评论格式3
    SpringBlade 本地图片上传 生成缩略图
    SQL Server 字符串截取
    SpringBlade 本地图片上传
  • 原文地址:https://www.cnblogs.com/shizioo/p/3813929.html
Copyright © 2011-2022 走看看