web-dev-qa-db-fra.com

Exécuter Javascript depuis Python

J'ai des pages Web HTML que j'explore à l'aide de xpath. Le etree.tostring D'un certain nœud me donne cette chaîne:

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

J'ai juste besoin de la sortie de escramble_758(). Je peux écrire une expression régulière pour comprendre le tout, mais je veux que mon code reste en ordre. Quelle est la meilleure alternative?

Je passe en revue les bibliothèques suivantes, mais je n'ai pas vu de solution exacte. La plupart d'entre eux essaient d'émuler le navigateur, ce qui ralentit les choses.

Edit: Un exemple sera génial .. (barebones fera l'affaire)

43
jerrymouse

En utilisant PyV8 , je peux le faire. Cependant, je dois remplacer document.write avec return car il n'y a pas de DOM et donc pas de 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 "))

Ou vous pouvez créer un faux objet document

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
34
Kien Truong

Vous pouvez également utiliser Js2Py qui est écrit en pur python et est capable d'exécuter et de traduire javascript en python. Prend en charge pratiquement tous les libellés JavaScript, getters, setters et autres fonctionnalités rarement utilisées).

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 

Les avantages de Js2Py incluent la portabilité et une intégration extrêmement facile avec python (car essentiellement JavaScript est en cours de traduction en python).

À installer:

pip install js2py
40
Piotr Dabkowski

Une autre solution car PyV8 ne semble pas être maintenue et dépend de l'ancienne version de libv8.

PyMiniRacer C'est un wrapper autour du moteur v8 et il fonctionne avec la nouvelle version et est activement maintenu.

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")

Et oui, vous devez remplacer document.write avec return comme d'autres l'ont suggéré

14
Dienow

Vous pouvez utiliser le contexte js2py pour exécuter votre code js et obtenir la sortie de document.write avec un faux objet document:

import js2py

js = """
var output;
document = {
    write: function(value){
        output = value;
    }
}
""" + your_script

context = js2py.EvalJs()
context.execute(js)
print(context.output)
1
Mirko