分类 前端 下的文章

如果你使用百度搜索“使用 python 运行 js 程序”之类的关键字,得到的结果无非是"pyv8","pyexecjs,","js2py","直接操作node"。
那么很遗憾,以上四种方案都很不ok。

我花费很长时间,查阅了大量资料,总结出一个道理:如果在百度里很长时间都找不到的答案,不妨去 Google 一下,使用英文关键字。

这里介绍的是 PyMiniRacer ,它是一个很棒的库,可以完美替代谷歌的 pyv8 ,让你在任何版本的Python里都能通过 pip 很轻松的安装。

PyMiniRacer 仓库

特点:轻,安装方便,使用v8引擎(快),可以记录上下文环境,项目在积极维护中

安装:pip install py_mini_racer
使用:(更多用法见github)

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

分别介绍一下其他库的缺点:

pyv8

2013 年开始就不维护了,支持python2 和早期python3 ,对python版本有要求,安装难,安装了不一定能用。

pyexecjs

这个也不维护了,作者的话:“pyexecjs性能差,推荐大家去用性能更好的pyv8”
pyexecjs 本身依赖js运行环境.首先在python中调用pyexecjs,然后pyexecjs再去启动nodejs。性能差

js2py

这个库的核心是“将js 代码翻译成 py”,自然会缺失很多js的系统函数,最后出现很多奇怪的bug

dukpy

这个库是基于 duktape 引擎的,不支持 es6。可能会出现很多奇怪的bug


最后,可以在 https://stackoverflow.com/questions/10136319/executing-javascript-from-python 发现更多的 “在 python 中运行js”的答案

网页自动刷新小助手

设计初心

  1. 为什么要写这个小助手?

为了刷帖子的访问量

  1. 有替代方案案吗?

有,而且有许多。如“流量精灵”, 有些浏览器自带有刷新网页的插件。

但是,作为一个程序猿。明明知道其实现原理很简单,为什么不尝试自己做一个呢?

  1. 使用了哪些技术

最初写的时候很粗糙,这次优化了一下下。

  1. 使用 bootstrap4 实现了响应式布局
  2. 使用 vue 框架。没办法,这框架太好用了,用一次就爱上了。

实现原理

使用 iframe 标签加载目标网页。通过多次修改 iframe 标签的 src 属性来实现多次访问目标网页。

代码

Demo

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>网页自动刷新小助手</title>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script>
</head>
<body>
<div class="navbar navbar-expand-md bg-dark text-light w-100 border-top border-warning">
    <a href="" class="nav-item text-light nav-link navbar-brand">
        网页自动刷新小助手
    </a>
</div>

<div id="app" class="container">
    <div class="row">
        <div class="card aside col-md-4 my-3">
            <div class="card-body">
                <div class="form-group">
                    <label for="">
                        链接
                        <small>(必须以 http:// 或 https:// 开头)</small>
                    </label>
                    <input type="text" v-model="src" class="form-control" placeholder="请输入链接">
                </div>
                <div class="form-group">
                    <label for="">刷新次数</label>
                    <input type="number" v-model="times" class="form-control">
                </div>
                <div class="form-group">
                    <label for="">刷新间隔时间(毫秒)</label>
                    <input type="number" v-model="interval" class="form-control">
                </div>
                <div class="btn-group-sm">
                    <button class="btn btn-primary" @click="start">开始刷</button>
                    <button class="btn btn-danger" @click="stop">停止</button>
                </div>
            </div>
        </div>
        <div class="col-md-8 my-3">
            <div class="alert alert-info">
                {{ message }}
            </div>
            <iframe class="mt-2 w-100 h-100" ref="iframe_box" frameborder="0"></iframe>
        </div>
    </div>
</div>

<script>
    let App = new Vue({
            el: '#app',
            data: {
                src: "https://api.xygeng.cn/dailywd/api/get.php",
                times: 10,
                interval: 2000,
                job_id: "",
                count: 1,
                message: '网页预览小窗口'
            },
            methods: {
                start() {
                    this.message = '任务将会在' + this.interval / 1000 + 's 后开始';

                    this.job_id = setInterval(() => {
                        this.message = '任务正在进行中 , 第' + this.count + '次'
                        if (++this.count > this.times) this.stop()
                        this.$refs.iframe_box.src = this.src
                    }, this.interval)
                },
                stop() {
                    this.message = '任务已结束'
                    clearInterval(this.job_id)
                    this.count = 1;
                }
            }
        }
    )
</script>
</body>
</html>