天天看點

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/