浙江省高等学校教师教育理论培训

微信搜索“毛凌志岗前心得”小程序

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  12653 随笔 :: 2 文章 :: 617 评论 :: 609万 阅读

在Python中执行javascript - 熊猫凶猛 - 博客园

在Python中执行javascript

在使用python抓取网页的过程中,有的时候需要执行某些简单的javascript,以获得自己需要的内容,例如执行js里面的document.write或者document.getElementById等。自己解析js代码显然有点吃力不讨好,因此最好能找到一些可以解析执行js的python库。

google之可以找到三个候选者,分别是微软的ScriptControl,v8的python移植PyV8,还有SpiderMonkey的Python移植Python-Spidermonkey。其中ScriptControl只能在windows上运行,需要win32com库;PyV8能在windows和*nix上运行,但是需要装PyV8库;而SpiderMonkey是mozilla的js引擎在python上的移植,感觉已经不太活跃,因此没用。

微软的ScriptControl中对执行js最重要的方法就是addObject与eval,通过addObject,我们可以向js执行环境注入一个我们自定义的document对象,通过eval方法,我们可以执行一段js代码。注入自定义对象需要使用win32com.server.util.wrap方法,将一个python对象包装为COM对象,例如假设我们想注入一个只实现了write方法的document对象,代码是这样的:

复制代码
复制代码
import win32com.server.util, win32com.client

class win32Doc:
     _public_methods_ = ['write']
     def write(self, s):
             print s

doc = win32Doc()
jsengine = win32com.client.Dispatch('MSScriptControl.ScriptControl')
jsengine.language = 'JavaScript'
jsengine.allowUI = False
jsengine.addObject('document', win32com.server.util.wrap(doc))
jsengine.eval('document.write("hello, world")')
复制代码
复制代码

在windows里运行这段python代码,最终就会打印出hello, world来。如果我们希望从python里读取js通过document.write写入的字符串并进行解析,只要给上面的win32Doc类添加对应的方法(例如read),就可以读取并解析HTML代码,并进行进一步处理了。

对PyV8来说,原理也是类似的,不过在具体机制上有所不同而已。在PyV8中需要在初始化的时候加入一个全局对象,其他的对象都是挂在全局对象之下的,例如document只是全局对象的一个属性而已(实际上,document对象就是window对象的一个属性么),当然,这个属性对应的实际上是一个对象。需要注意的是,PyV8在处理字符串编码的时候让人很迷惑,在windows下它需要js的编码为UTF8,而在Linux下只要求宽字符串,即python里的unicode,而在内部的字符串都是UTF8编码的。至于为何如此,熊猫也骚扰过开发PyV8的flier,貌似是V8自己的feature。示例代码是这样的:

复制代码
复制代码
import PyV8

class v8Doc(PyV8.JSClass):
     def write(self, s):
             print s.decode('utf-8')

class Global(PyV8.JSClass):
     def __init__(self):
             self.document = v8Doc()

glob = Global()
ctxt = PyV8.JSContext(glob)
ctxt.enter()
#or ctxt.eval(u'document.write("你好,中国")') for Linux
ctxt.eval(u'document.write("你好,中国")'.encode('utf-8'))
复制代码
复制代码

上面只是在python里模拟执行js的document.write的大体思路,如果还需要执行其他的js代码对DOM树进行操纵,那就一个个添加对应的方法好了。当然,这个添加也要保持一个限度,不然添加的方法太多,代码会非常复杂,相当于自己已经开始实现一个DOM树处理和解析的完全封装了,如果是这样,还不如使用自动化接口操纵浏览器,例如通过js/vbs操纵IE,或者在后台进行自动化批处理的话,使用一些headless browser软件,例如phantomjs,这就留待以后再说了。

posted on   lexus  阅读(16403)  评论(1编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2010-04-27 erick recommendation:慕容晓晓《爱情买卖》MV欣赏
2010-04-27 get random number in python
点击右上角即可分享
微信分享提示