从Python执行Javascript

时间:2012-04-13 06:39:41

标签: javascript python screen-scraping

我有使用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()的输出。我可以写一个正则表达式来弄清楚整个事情,但我希望我的代码保持整洁。什么是最好的选择?

我正在浏览以下库,但我没有看到确切的解决方案。他们中的大多数都试图模仿浏览器,使事情变得缓慢。

编辑:一个例子很棒..(准系统会做)

6 个答案:

答案 0 :(得分:39)

你也可以使用用纯python编写的Js2Py,并且能够执行和转换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

答案 1 :(得分:32)

使用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

答案 2 :(得分:13)

另一个解决方案,因为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

答案 3 :(得分:2)

在quickjs出现之后,

quickjs应该是最好的选择。只需pip install quickjs,您就可以出发了。

根据自述文件中的示例进行修改。

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

答案 4 :(得分:1)

您可以使用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 :(得分:1)

您可以使用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