从 Python 执行 Javascript

IT技术 javascript python screen-scraping
2021-01-20 06:41:57

我有使用 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个回答

您还可以使用纯 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
如果您正在运行不受信任的代码(一个抓取的 HTML 页面),请不要使用它,js2py 有一个pyimport让您运行任意代码语句。
2021-03-18 06:41:57

使用PyV8,我可以做到这一点。但是,我必须替换为document.writereturn因为没有 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 和 V8 版本。其次,你需要自己猜测。
2021-03-16 06:41:57
我只使用 exe 安装程序,因为我使用的是 Window。我不确定如何在其他平台上安装它。
2021-03-28 06:41:57
如何安装 PyV8?当我执行 a 时python setup.py install,我收到错误:您应该将 V8_HOME 设置为 Google v8 文件夹,或者先下载并构建它。< code.google.com/p/v8 >在访问这个项目时,我只看到 2 个下载, benchmarks-v2.zip benchmarks-v1.zip。他们都没有任何 py 文件。
2021-03-31 06:41:57
您是否知道任何其他适用于 Python 的 JS interpeter 允许创建可实现为作用域的模拟对象?我一直在看 PyMiniRacer,但没有遇到任何将 python 类添加到作用域的问题?谢谢
2021-04-12 06:41:57
我遇到了同样的问题,哇,这太棒了。它完美地工作。现在我想知道如何管理功能提示?!请帮忙。
2021-04-13 06:41:57

另一种解决方案是 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.writereturn为他人建议

嗨,您知道是否可以扩展 PyMiniRacer 的范围以使用 python 类,如上面的 PyV8 示例?基本上能够使用 JS 访问某些 Python 类/对象?谢谢。
2021-03-29 06:41:57
@SamG101 不,除了简单的 js 片段外,从未将其用于任何其他用途
2021-04-11 06:41:57

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

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

更多关于这个阅读这里