Как получить исходный источник innerHTML без содержимого, сгенерированного Javascript? - PullRequest
23 голосов
/ 09 декабря 2010

Можно ли каким-то образом получить исходный 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 (результат обработанного скрипта).

Ответы [ 9 ]

6 голосов
/ 10 декабря 2010

Я не думаю, что есть простое решение, чтобы просто "захватить исходный код", поскольку оно должно быть чем-то, что предоставляется браузером. Но, , если вы заинтересованы в этом только для части страницы , тогда у меня есть обходной путь для вас.

Вы можете заключить интересующий раздел в «замороженный» скрипт:

<script id="frozen" type="text/x-frozen-html">

Атрибут type, который я только что создал, но он заставит браузер игнорировать все внутри него. Затем вы сразу после этого добавляете еще один тег сценария (правильный javascript) - сценарий «оттаивания». Этот размораживающий скрипт получит замороженный скрипт по идентификатору, захватит текст внутри него и сделает document.write, чтобы добавить фактическое содержимое на страницу. Всякий раз, когда вам нужен исходный код, он все равно записывается в виде текста внутри замороженного скрипта.

И вот оно у вас есть. Недостатком является то, что я не буду использовать это для всей страницы ... (SEO, подсветка синтаксиса, производительность ...), но это вполне приемлемо, если у вас есть особые требования к части страницы.


Редактировать: вот пример кода. Кроме того, как правильно указал @FlashXSFX, любые теги сценария в замороженном сценарии необходимо экранировать. Поэтому в этом простом примере я создам для этой цели тег <x-script>.

<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

3 голосов
/ 08 августа 2014

Простой способ - получить его снова с сервера. Это будет в кеше скорее всего. Вот мое решение с использованием jQuery.get () . Он берет исходный URI страницы и загружает данные с помощью вызова ajax:

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

При этом будет напечатан оригинальный код без JavaScript. Не обрабатывает ошибки!

Если вы не хотите использовать jQuery для извлечения источника, обратитесь к ответу на этот вопрос: Как сделать вызов ajax без jquery?

2 голосов
/ 16 декабря 2010

Не могли бы вы отправить запрос Ajax на ту же страницу, на которой вы сейчас находитесь, и использовать результат в качестве исходного HTML?Это надежно при соблюдении надлежащих условий, поскольку вы буквально получаете оригинальный HTML-документ.Однако это не будет работать, если страница изменяется при каждом запросе (с динамическим содержимым) или если по какой-либо причине вы не можете сделать запрос на эту конкретную страницу.

1 голос
/ 10 декабря 2010

Метод грубой силы

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>"));
0 голосов
/ 02 января 2018

Сложно использовать тег <style> для шаблона.Чтобы вам больше не нужно переименовывать x-script.

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

Но мне не нравится это безобразное решение.

0 голосов
/ 11 декабря 2010

Я не могу придумать решение, которое бы работало так, как вы просите.Единственный код, к которому у Javascript есть доступ, - через DOM, который содержит результат только после обработки страницы.

Самое близкое, что я могу придумать для достижения того, чего вы хотите - это использовать Ajax для загрузки свежегоскопируйте необработанный HTML-код для вашей страницы в строку Javascript, после чего, поскольку это строка, вы можете делать с ней все что угодно, в том числе отображать ее в окне предупреждения.

0 голосов
/ 11 декабря 2010

Если вы хотите нетронутый документ, вам нужно будет получить его снова. Там нет никакого способа обойти это. Если бы не document.write () (или аналогичный код, который выполнялся бы во время процесса загрузки), вы можете загрузить innerHTML исходного документа в память при загрузке / загрузке, прежде чем изменять его.

0 голосов
/ 11 декабря 2010

Если вы переопределите 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, ''));
0 голосов
/ 09 декабря 2010

Я думаю, что вы хотите пересечь узлы 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('');
...