【问题标题】:Applying DOM Manipulations to HTML and saving the result?将 DOM 操作应用于 HTML 并保存结果?
【发布时间】:2011-10-15 11:16:37
【问题描述】:

我有大约 100 个静态 HTML 页面,我想对其应用一些 DOM 操作。它们都遵循相同的 HTML 结构。我想对这些文件中的每一个应用一些 DOM 操作,然后保存生成的 HTML。

这些是我想要应用的操作:

# [start]
$("h1.title, h2.description", this).wrap("<hgroup>");
if ( $("h1.title").height() < 200 ) {
  $("div.content").addClass('tall');
}
# [end]
# SAVE NEW HTML

第一行 (.wrap()) 我可以轻松地使用查找和替换来完成,但是当我必须确定元素的计算高度时,它变得很棘手,这在没有 JavaScript 的情况下无法轻易确定。

有谁知道我如何做到这一点?谢谢!

【问题讨论】:

  • 您想通过 Javascript 保存数据吗?我不认为你可以

标签: javascript html dom static bulk


【解决方案1】:

您可以通过 $('html').html() (或者如果您不想要诸如头标签之类的东西,则可以使用更具体的选择器)获取修改后的内容,然后将其作为大字符串提交到您的服务器并写入文件服务器端。

【讨论】:

    【解决方案2】:

    虽然第一部分确实可以在“文本模式”下使用正则表达式或更完整的 JavaScript DOM 实现来解决,但对于第二部分(高度计算),您需要一个真正的完整浏览器或无头浏览器PhantomJS 之类的引擎。

    来自PhantomJS homepage

    PhantomJS 是一个命令行工具,用于打包和嵌入 WebKit。 从字面上看,它就像任何其他基于 WebKit 的网络浏览器一样,除了 没有任何东西显示在屏幕上(因此,术语无头)。在 除此之外,PhantomJS 可以使用它的 JavaScript API。


    下面是一个示意图说明(我承认它没有经过测试)。

    在你的修改脚本中(比如modify-html-file.js)打开一个HTML页面,修改它的DOM树和console.log根元素的HTML:

    var page = new WebPage();
    
    page.open(encodeURI('file://' + phantom.args[0]), function (status) {
        if (status === 'success') {
            var html = page.evaluate(function () {
                // your DOM manipulation here
                return document.documentElement.outerHTML;
            });
            console.log(html);
        }
        phantom.exit();
    });
    

    接下来,通过将脚本的输出重定向到文件来保存新的 HTML:

    #!/bin/bash
    
    mkdir modified
    for i in *.html; do
        phantomjs modify-html-file.js "$1" > modified/"$1"
    done
    

    【讨论】:

    • 这看起来很有希望!我会下载并试一试。不过,我仍然需要弄清楚如何将输出写入文件……
    • 这似乎是通过render() 函数完成的!好的,现在我们正在取得进展!
    • DOM修改后可以调用render方法吗?
    • “通过将脚本的输出重定向到文件来保存新的 HTML”之后的部分在哪里写?
    • @FernandoTiberti,这是一个单独的 shell 脚本。
    【解决方案3】:

    我尝试PhantomJSkatspaugh's answer 一样,但在尝试操作页面时遇到了几个问题。我的用例是修改 Doxygen 的静态 html 输出,而不修改 Doxygen 本身。目标是通过从页面中删除不必要的元素来减少交付的文件大小,并将其转换为 HTML5。此外,我还想使用 jQuery 更轻松地访问和修改元素。

    在 PhantomJS 中加载页面

    自接受答案以来,API 似乎发生了巨大变化。此外,我使用了一种不同的方法(源自this answer),这对于缓解我遇到的一个主要问题非常重要。

    var system = require('system');
    var fs = require('fs');
    var page = require('webpage').create();
    
    // Reading the page's content into your "webpage"
    // This automatically refreshes the page
    page.content = fs.read(system.args[1]);
    
    // Make all your changes here
    
    fs.write(system.args[2], page.content, 'w');
    phantom.exit();
    

    阻止 JavaScript 运行

    我的页面在页脚中使用了 Google Analytics,现在页面的修改超出了我的意图,可能是因为运行了 javascript。如果我们禁用 javascript,我们实际上不能使用 jQuery 来修改页面,所以这不是一个选项。我尝试过临时更改标签,但是当我这样做时,每个特殊字符都会被替换为 html 转义的等效字符,从而破坏页面上的所有 javascript 代码。然后,我遇到了this answer,这让我有了以下想法。

    var rawPageString = fs.read(system.args[1]);
    rawPageString = rawPageString.replace(/<script type="text\/javascript"/g, "<script type='foo/bar'");
    rawPageString = rawPageString.replace(/<script>/g, "<script type='foo/bar'>");
    
    page.content = rawPageString;
    
    // Make all your changes here
    
    rawPageString = page.content;
    rawPageString = rawPageString.replace(/<script type='foo\/bar'/g, "<script");
    

    添加 jQuery

    actually an example 介绍了如何使用 jQuery。但是,我认为离线副本会更合适。最初我尝试使用 page.includeJs 作为示例,但发现page.injectJs 更适合用例。与 includeJs 不同的是,页面上下文中没有添加 &lt;script&gt; 标记,并且调用会阻止执行,从而简化了代码。 jQuery 被放置在我执行脚本的同一目录中。

    page.injectJs("jquery-2.1.4.min.js");
    page.evaluate(function () {
    
      // Make all changes here
    
      // Remove the foo/bar type more easily here
      $("script[type^=foo]").removeAttr("type");
    });
    
    fs.write(system.args[2], page.content, 'w');
    phantom.exit();
    

    把它们放在一起

    var system = require('system');
    var fs = require('fs');
    var page = require('webpage').create();
    
    var rawPageString = fs.read(system.args[1]);
    // Prevent in-page javascript execution
    rawPageString = rawPageString.replace(/<script type="text\/javascript"/g, "<script type='foo/bar'");
    rawPageString = rawPageString.replace(/<script>/g, "<script type='foo/bar'>");
    
    page.content = rawPageString;
    
    page.injectJs("jquery-2.1.4.min.js");
    page.evaluate(function () {
    
      // Make all changes here
    
      // Remove the foo/bar type
      $("script[type^=foo]").removeAttr("type");
    });
    
    fs.write(system.args[2], page.content, 'w');
    phantom.exit();
    

    从命令行使用它:

    phantomjs modify-html-file.js "input_file.html" "output_file.html"
    

    注意:这是在 Windows 8.1 上测试并与 PhantomJS 2.0.0 一起使用的。

    专业提示:如果速度很重要,您应该考虑从 PhantomJS 脚本而不是 shell 脚本中迭代文件。这将避免 PhantomJS 在启动时的延迟。

    【讨论】:

      猜你喜欢
      • 2011-01-12
      • 2020-07-11
      • 1970-01-01
      • 1970-01-01
      • 2017-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多