如何将javascript应用于模拟浏览器的html

时间:2017-02-19 21:53:51

标签: javascript html node.js scala headless-browser

我已经在互联网上搜索了如何创建"一个简单的无头浏览器,因为我有兴趣知道浏览器如何在内部工作。我想实现一个简单的无头浏览器。

我的意思是:假设你有一个html字符串和一个javascript字符串,这两者都是对服务器的HttpRequest的结果;如何将javascript应用到html字符串?

例如: 我向X服务器请求了html源文件,我在响应中获得了这个:

<html>
    <head>
         <script type="text/javascript" src="javascript.js">
    </head>
    <body>
        <p id="content"></p>
    <body>
</html>

然后,我请求javascript.js文件,我得到了这个:

document.getElementById("content").text = "Hello";

如何将javascript.js文件的内容应用到html文件中?我应该遵循的步骤与此类似?:

  1. 将html源解析为Javascript DOM元素
  2. 将javascript应用于DOM
  3. 我想用Java,Scala或Node.js来做。 如果你理解主要想法,我很高兴...我是拉丁美洲人,而我的英语并不是那么好。对不起。如果不明白,请在评论中告诉我,我将编辑我的帖子。

    编辑:换句话说,我想做的是像这样的伪方法/函数(在伪代码中):

    function applu(html, js){
        // Apply js into html
    }
    

1 个答案:

答案 0 :(得分:2)

如果您正在寻找无头浏览器,我确定您已了解phantomsJS。 PhantomJS是一款基于苹果webkit浏览器引擎的无头浏览器。

你在这里要求很多。你需要:

  1. 运行javascript的javascript运行时(例如v8)。
  2. 一个Web引擎,用于将html和它定义的文档对象模型带入生活。
  3. 这两件事都要花费数百万行代码才能执行。

    我的建议是将您的程序与PhantomJS集成。 PhantomJS是一个无头的webbrowser和一个javascript环境。如果您正在使用scala,请启动phantomjs的子进程并通过std i / o向其发送消息。 PhantomJS的 JS 部分意味着你通过它的javascript API使用它,所以另外你必须编写一个js脚本来处理来自std i / o的消息。它没有记录,但是phantomjs有system.std.insystem.std.out api来处理消息。

    JVM之外的大量工作和大量额外资源可以让它工作。我看到您正在使用scala,因此您可以使用jsoup来解析和修改HTML文档,但是您可以使用scala(或java)进行转换。

    实际上,现在我考虑一下,你应该使用jsdom与nodejs配对。 JSDom实现了dom API而没有实际呈现它,这可能是你需要的。 jsdom是为无头的nodejs而制作的。如果你想同时使用scala和node,你也可以使用node的std i / o并让它向JVM发送消息和从JVM发送消息。

    以下是使用jsdom评估javascript和修改html的概念证明。它是一个非常简单的解决方案,对于给定的任务来说它是最有效的资源(这是一项艰巨的任务)。

    我用一个非常简单的概念证明为你做了gist。要运行要点:

    git clone https://gist.github.com/c8aef41ee27e5304e94f6a255b048f87.git apply-js-to-html
    cd apply-js-to-html
    npm install
    node example.js
    

    这是榜样的主要内容:

    const jsdom = require('jsdom');
    
    module.exports = function (html, js) {
        return new Promise((resolve, reject) => {
            jsdom.env(html, (error, window) => {
                if (error) {
                    reject(error);
                }
                try {
                (function evalInContext () {
                    'use strict';
                    const document = this.document;
                    const window = this.window;
                    eval(js);
                    resolve(window.document.documentElement.innerHTML);
                }).call(window);
                } catch (e) {
                    reject(e);
                }
            });
        });
    }
    

    这是正在使用的模块

    const applu = require('./index');
    
    const html = `
        <html>
            <head></head>
            <body>
                <p id="content"></p>
            <body>
        </html>
    `;
    
    const js = `document.getElementById("content").innerHTML = "Hello";`
    
    applu(html, js).then(result => {
        console.log('input html: ', html);
        console.log('output html: ', result);
    }).catch(err => console.error(error));
    

    以下是代码的输出:

    input html:  
        <html>
            <head></head>
            <body>
                <p id="content"></p>
            <body>
        </html>
    
    output html:  <head></head>
            <body>
                <p id="content">Hello</p>
    
    
    </body>
    

    jsdom创建了无头windowdocument环境,无法渲染任何内容。您可以使用evalwindow作为this值使用documentcall it in context。我还要再次声明window$(function(){ $('img').draggable({ containment: '.container' }); }); 将被撤销的js将在范围内包含这些变量。

    这只是一个基本的POC,你可以自己解决这些问题。