天天看点

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

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系列(一)

算法复杂度分析

最新内容请见作者的github页:http://qaseven.github.io/