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/