从 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 代码并使用模拟文档对象从 do​​cument.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的主要内容,如果未能解决你的问题,请参考以下文章

从 Python 项目创建单个可执行文件

从Laravel 4 Controller执行Python脚本

Python - 从文件执行多个 SQL 查询

为啥我不能从我的 python 脚本创建可执行文件?

我如何从 php 执行 python 函数(它需要一个参数)?

从具有依赖项的python程序创建可执行文件