Ik heb HTML-webpagina’s die ik crawl met xpath. De etree.tostring
van een bepaald knooppunt geeft me deze string:
<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>
Ik heb alleen de uitvoer van escramble_758()
nodig. Ik kan een regex schrijven om het hele ding te achterhalen, maar ik wil dat mijn code netjes blijft. Wat is het beste alternatief?
Ik blader door de volgende bibliotheken, maar ik heb geen exacte oplossing gezien. De meesten van hen proberen de browser na te bootsen, waardoor de boel traag wordt.
- http://code.google.com/p/python-spidermonkey/(zegt duidelijk
it's not yet possible to call a function defined in Javascript
) - http://code.google.com/p/webscraping/(zie niets voor Javascript , ik kan het mis hebben)
- http://pypi.python.org/pypi/selenium(Emulerende browser)
Bewerken: Een voorbeeld is geweldig.. (barebones zijn voldoende)
Antwoord 1, autoriteit 100%
Je kunt ook Js2Py gebruiken, dat is geschreven in pure python en in staat is om zowel javascript uit te voeren als te vertalen naar python. Ondersteunt vrijwel hele JavaScript, zelfs labels, getters, setters en andere zelden gebruikte functies.
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
Voordelen van Js2Py zijn onder meer draagbaarheid en extreem gemakkelijke integratie met python (aangezien JavaScript in feite wordt vertaald naar python).
Installeren:
pip install js2py
Antwoord 2, autoriteit 86%
Met PyV8kan ik dit doen. Ik moet echter document.write
vervangen door return
omdat er geen DOM is en dus ook geen 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 "))
Of u kunt een nepdocumentobject maken
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
Antwoord 3, autoriteit 40%
Nog een oplossing aangezien PyV8 niet onderhouden lijkt te zijn en afhankelijk is van de oude versie van libv8.
PyMiniRacerHet is een wrapper rond de v8-engine en het werkt met de nieuwe versie en wordt actief onderhouden.
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")
En ja, je moet document.write
vervangen door return
zoals anderen suggereerden
Antwoord 4, autoriteit 7%
Je kunt js2py-context gebruiken om je js-code uit te voeren en uitvoer te krijgen van document.write met een nepdocumentobject:
import js2py
js = """
var output;
document = {
write: function(value){
output = value;
}
}
""" + your_script
context = js2py.EvalJs()
context.execute(js)
print(context.output)
Antwoord 5, autoriteit 7%
Je kunt requests-htmlgebruiken die chroom eronder zal downloaden en gebruiken.
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
Meer hierover lees hier
Antwoord 6, autoriteit 3%
quickjs zou de beste optie moeten zijn nadat quickjs uit is gekomen. Gewoon pip install quickjs
en je bent klaar om te gaan.
wijzig op basis van het voorbeeld op 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())