【问题标题】:How do I get the original innerHTML source without the Javascript generated contents?如何在没有 Javascript 生成的内容的情况下获取原始的 innerHTML 源?
【发布时间】:2011-05-22 19:20:51
【问题描述】:

是否有可能以某种方式获得原始 HTML 源代码,而无需经过处理的 Javascript 进行更改?例如,如果我这样做:

<div id="test">
    <script type="text/javascript">document.write("hello");</script>
</div>

如果我这样做:

alert(document.getElementById('test').innerHTML);

它显示:

<script type="text/javascript">document.write("hello");</script>hello

简单来说,我希望alert 只显示:

<script type="text/javascript">document.write("hello");</script>

没有最终的hello(处理脚本的结果)。

【问题讨论】:

  • 你在哪个浏览器中测试过这个?在 FF4b7 和 Chrome 8 中,我得到 &lt;script type="text/javascript"&gt;document.write("hello");&lt;/script&gt;hello
  • @Marcel:IE7 和 IE8(还有 IE6)
  • @Marcel:我更新了问题,我忘了一块。很抱歉。
  • 我担心你事先不知道添加了什么文本,是吗?
  • 是的,这就是我所担心的。但是当元素被添加到 DOM 时,没有办法区分原始标记和动态添加的元素/节点(除非您将它们标记为这样),至少据我所知。

标签: javascript html innerhtml


【解决方案1】:

我认为“获取原始源”没有简单的解决方案,因为它必须是由浏览器提供的东西。但是,如果您只对页面的某个部分执行此操作,那么我可以为您提供解决方法。

您可以将感兴趣的部分包装在“冻结”脚本中:

&lt;script id="frozen" type="text/x-frozen-html"&gt;

我刚刚编的type属性,但它会强制浏览器忽略其中的所有内容。然后,您在此之后立即添加另一个脚本标记(这次是正确的 javascript) - “解冻”脚本。这个解冻脚本将通过 ID 获取冻结脚本,抓取其中的文本,然后执行 document.write 将实际内容添加到页面。每当您需要原始源代码时,它仍会被捕获为冻结脚本中的文本。

你有它。缺点是我不会将它用于整个页面......(SEO、语法突出显示、性能......)但如果您对页面的一部分有特殊要求,这是完全可以接受的。


编辑:这是一些示例代码。此外,正如@FlashXSFX 正确指出的那样,冻结脚本中的任何脚本标签都需要转义。所以在这个简单的例子中,我将为此创建一个&lt;x-script&gt; 标签。

<script id="frozen" type="text/x-frozen-html">
   <div id="test">
      <x-script type="text/javascript">document.write("hello");</x-script>
   </div>
</script>
<script type="text/javascript">
   // Grab contents of frozen script and replace `x-script` with `script`
   function getSource() {
      return document.getElementById("frozen")
         .innerHTML.replace(/x-script/gi, "script");
   }
   // Write it to the document so it actually executes
   document.write(getSource());
</script>

现在只要您需要源代码:

alert(getSource());

查看演示:http://jsbin.com/uyica3/edit

【讨论】:

  • 能否请您显示一小段代码。我不明白。
  • 我认为这可能真的有效,所以我试了一下。我看到的主要问题是当您尝试将脚本标签放入冻结标签时。 (我使用了原始海报的 sn-ps)您需要进行一些转义和一些字符串替换才能使其正常工作。
【解决方案2】:

一个简单的方法是再次从服务器获取它。它很可能会在缓存中。这是我使用jQuery.get() 的解决方案。它获取页面的原始 uri 并通过 ajax 调用加载数据:

$.get(document.location.href, function(data,status,jq) {console.log(data);})

这将打印没有任何 javascript 的原始代码。它不做任何错误处理!

如果不想使用 jQuery 来获取源码,请参考这个问题的答案:How to make an ajax call without jquery?

【讨论】:

  • 好主意!我遇到了一个问题,即无法在没有网络浏览器的情况下抓取网站,但同时该网站在加载后会破坏一些数据(我需要这些数据)。使用这种方法,缓慢且低效的加载一次完成,而站点 html 的实际读取是在同一个浏览器会话中完成的,因此它一次解决了两个问题。
【解决方案3】:

您能否向您当前所在的同一页面发送 Ajax 请求并将结果用作您的原始 HTML?如果条件合适,这是万无一失的,因为您实际上是在获取原始 HTML 文档。但是,如果页面在每个请求(具有动态内容)时发生更改,或者由于某种原因您无法向该特定页面发出请求,则此方法将不起作用。

【讨论】:

    【解决方案4】:

    暴力破解

    var orig = document.getElementById("test").innerHTML;
    alert(orig.replace(/<\/script>[.\n\r]*.*/i,"</script>"));
    

    编辑:

    这样会更好

    var orig = document.getElementById("test").innerHTML + "<<>>";
    alert(orig.replace( /<\/script>[^(<<>>)]+<<>>/i, "<\/script>"));
    

    【讨论】:

    • 除了您忘记了斜线replace(/&lt;\/script&gt;[.\n\r]*.*/i,"&lt;\/script&gt;") 并且我不明白您为什么在[.\n\r] 内放置一个点这一事实之外,这无论如何可能是一个很好的尝试和可能的方法,所以+1。无论如何,它仍然非常具体,即如果添加一个简单的新行document.write("hello\nchina");,您的正则表达式将仅替换hello,并在它所在的位置使用china
    • @Marco,感谢您更正正则表达式。正如我所说,这是一种蛮力方法(不是优雅/通用的方法)。
    【解决方案5】:

    如果您覆盖 document.write 以在脚本写入文档的所有内容的开头和结尾添加一些标识符,您将能够使用正则表达式删除这些写入。

    这是我想出的:

        <script type="text/javascript" language="javascript">
            var docWrite = document.write;
            document.write = myDocWrite;
    
            function myDocWrite(wrt) {
                docWrite.apply(document, ['<!--docwrite-->' + wrt + '<!--/docwrite-->']);
            }
        </script>
    

    在初始脚本之后的页面某处添加了您的示例:

        <div id="test">
            <script type="text/javascript">     document.write("hello");</script>
        </div>
    

    然后我用它来提醒里面有什么:

        var regEx = /<!--docwrite-->(.*?)<!--\/docwrite-->/gm;
        alert(document.getElementById('test').innerHTML.replace(regEx, ''));
    

    【讨论】:

    • 请更具体。原帖是问怎么用document.write,还是得到原出处。
    【解决方案6】:

    如果您想要原始文档,则需要再次获取它。没有办法解决这个问题。如果不是 document.write()(或在加载过程中运行的类似代码),您可以在加载/domready 时将原始文档的 innerHTML 加载到内存中,然后再修改它。

    【讨论】:

      【解决方案7】:

      我想不出一个可以按照您要求的方式工作的解决方案。 Javascript 唯一可以访问的代码是通过 DOM,它只包含页面处理后的结果。

      我能想到的最接近您想要的方法是使用 Ajax 将您页面的原始 HTML 的新副本下载到 Javascript 字符串中,此时由于它是一个字符串,您可以用它做任何您想做的事情,包括在警告框中显示它。

      【讨论】:

        【解决方案8】:

        一个棘手的方法是使用&lt;style&gt; 标记作为模板。这样你就不需要重命名x-script了。

        console.log(document.getElementById('test').innerHTML);
        <style id="test" type="text/html+template">
            <script type="text/javascript">document.write("hello");</script>
        </style>

        但我不喜欢这种丑陋的解决方案。

        【讨论】:

          【解决方案9】:

          我想你想遍历 DOM 节点:

          var childNodes = document.getElementById('test').childNodes, i, output = [];
          
          for (i = 0; i < childNodes.length; i++)
              if (childNodes[i].nodeName == "SCRIPT")
                  output.push(childNodes[i].innerHTML);
          
          return output.join('');
          

          【讨论】:

            猜你喜欢
            • 2011-06-30
            • 2017-11-25
            • 2011-02-26
            • 2020-06-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-04-17
            • 2017-12-26
            相关资源
            最近更新 更多