从 Python 执行 Javascript
Posted
技术标签:
【中文标题】从 Python 执行 Javascript【英文标题】:Executing Javascript from Python 【发布时间】:2012-04-25 13:13:55 【问题描述】:我有使用 xpath 抓取的 html 网页。某个节点的etree.tostring
给了我这个字符串:
<script>
<!--
function escramble_758()
var a,b,c
a='+1 '
b='84-'
a+='425-'
b+='7450'
c='9'
document.write(a+c+b)
escramble_758()
//-->
</script>
我只需要escramble_758()
的输出。我可以编写一个正则表达式来弄清楚整个事情,但我希望我的代码保持整洁。最好的选择是什么?
我正在浏览以下库,但没有看到确切的解决方案。他们中的大多数人都在尝试模拟浏览器,这让事情变得非常缓慢。
http://code.google.com/p/python-spidermonkey/(明明是it's not yet possible to call a function defined in javascript
)
http://code.google.com/p/webscraping/(看不到任何关于 Javascript 的内容,我可能错了)
http://pypi.python.org/pypi/selenium(模拟浏览器)
编辑:一个例子会很棒..(准系统就可以了)
【问题讨论】:
等等。这是骗子吗?还是睡衣错了,以至于有人删除了他们的答案? 可能是PhantomJS 可以帮忙或pyv8。 @ErikReppen 我检查了睡衣,没有例子。 @RanRag 要求您尽可能展示一个示例。 我删除了它,因为我意识到它非常错误。 【参考方案1】:您还可以使用 Js2Py,它是用纯 python 编写的,能够执行并将 javascript 转换为 python。几乎支持整个 JavaScript 甚至标签、getter、setter 和其他很少使用的功能。
import js2py
js = """
function escramble_758()
var a,b,c
a='+1 '
b='84-'
a+='425-'
b+='7450'
c='9'
document.write(a+c+b)
escramble_758()
""".replace("document.write", "return ")
result = js2py.eval_js(js) # executing JavaScript and converting the result to python string
Js2Py 的优点包括可移植性和与 python 的极易集成(因为基本上 JavaScript 正在被翻译成 python)。
安装:
pip install js2py
【讨论】:
如果你正在运行不受信任的代码(一个抓取的 HTML 页面),请不要使用它,js2py 有一个pyimport
语句可以让你运行任意代码。【参考方案2】:
使用PyV8,我可以做到这一点。但是,我必须将document.write
替换为return
,因为没有DOM,因此也没有document
。
import PyV8
ctx = PyV8.JSContext()
ctx.enter()
js = """
function escramble_758()
var a,b,c
a='+1 '
b='84-'
a+='425-'
b+='7450'
c='9'
document.write(a+c+b)
escramble_758()
"""
print ctx.eval(js.replace("document.write", "return "))
或者你可以创建一个模拟文档对象
class MockDocument(object):
def __init__(self):
self.value = ''
def write(self, *args):
self.value += ''.join(str(i) for i in args)
class Global(PyV8.JSClass):
def __init__(self):
self.document = MockDocument()
scope = Global()
ctx = PyV8.JSContext(scope)
ctx.enter()
ctx.eval(js)
print scope.document.value
【讨论】:
如何安装 PyV8?当我执行python setup.py install
时,我得到 ERROR: you should set V8_HOME to the Google v8 folder,或者先下载并构建它。 code.google.com/p/v8> 在访问这个项目时,我只看到了 2 个下载,benchmarks-v2.zip benchmarks-v1.zip。他们都没有任何py文件。
我只使用exe安装程序,因为我使用的是Window。我不确定如何在其他平台上安装它。
我遇到了同样的问题,哇,这太棒了。它完美地工作。现在我想知道如何管理功能提示?!请帮忙。
PyV8 真的是真的坏了!首先,它需要一个非常特定版本的 Python 和 V8。其次,你需要自己猜测。
你知道任何其他用于 Python 的 JS 解释器允许创建可以作为作用域实现的模拟对象吗?我一直在研究 PyMiniRacer,但没有遇到任何将 python 类添加到作用域中的东西?谢谢【参考方案3】:
另一个解决方案是 PyV8 似乎没有维护并且依赖于旧版本的 libv8。
PyMiniRacer 它是 v8 引擎的包装器,它适用于新版本,并得到积极维护。
pip install py-mini-racer
from py_mini_racer import py_mini_racer
ctx = py_mini_racer.MiniRacer()
ctx.eval("""
function escramble_758()
var a,b,c
a='+1 '
b='84-'
a+='425-'
b+='7450'
c='9'
return a+c+b;
""")
ctx.call("escramble_758")
是的,您必须按照其他人的建议将 document.write
替换为 return
【讨论】:
您好,您知道是否可以扩展 PyMiniRacer 的范围以使用 python 类,例如上面的 PyV8 示例?基本上能够使用 JS 访问某些 Python 类/对象?谢谢。 @SamG101 不,除了简单的 js sn-ps 外,从来没有用过它【参考方案4】:您可以使用 js2py 上下文来执行您的 js 代码并使用模拟文档对象从 document.write 获取输出:
import js2py
js = """
var output;
document =
write: function(value)
output = value;
""" + your_script
context = js2py.EvalJs()
context.execute(js)
print(context.output)
【讨论】:
【参考方案5】:您可以使用requests-html,它将在下面下载并使用铬。
from requests_html import HTML
html = HTML(html="<a href='http://www.example.com/'>")
script = """
function escramble_758()
var a,b,c
a='+1 '
b='84-'
a+='425-'
b+='7450'
c='9'
return a+c+b;
"""
val = html.render(script=script, reload=False)
print(val)
# +1 425-984-7450
更多内容请阅读here
【讨论】:
【参考方案6】:quickjs 应该是 quickjs 出来后的最佳选择。只需pip install quickjs
,您就可以开始了。
根据 README 中的示例进行修改。
from quickjs import Function
js = """
function escramble_758()
var a,b,c
a='+1 '
b='84-'
a+='425-'
b+='7450'
c='9'
document.write(a+c+b)
escramble_758()
"""
escramble_758 = Function('escramble_758', js.replace("document.write", "return "))
print(escramble_758())
https://github.com/PetterS/quickjs
【讨论】:
以上是关于从 Python 执行 Javascript的主要内容,如果未能解决你的问题,请参考以下文章
从Laravel 4 Controller执行Python脚本