Как получить весь документ HTML в виде строки?

237

Есть ли способ в JS, чтобы получить весь HTML- код в тегах HTML , в виде строки?

document.documentElement.??
Вспышка
источник
10
Единственный правильный ответ: stackoverflow.com/questions/817218/… ( прекратите голосование по внутренним / externalHTML-ответам, они НЕ предоставляют весь источник! )
Джон
2
document.body.parentElement.innerHTML
Программы
@ Джон, что они не предоставляют?
блюджайке

Ответы:

320

MS добавила outerHTMLи innerHTMLсвойства некоторое время назад.

Согласно MDN , outerHTMLподдерживается в Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile и Safari Mobile. outerHTMLнаходится в спецификации разбора и сериализации DOM .

Посмотрите quirksmode для совместимости браузера для того, что будет работать для вас. Вся поддержка innerHTML.

var markup = document.documentElement.innerHTML;
alert(markup);
Колин Бернетт
источник
28
externalHTML не получает тип документа.
CMCDragonkai
2
работал как шарм! Спасибо! есть ли способ получить размер любых / всех файлов, связанных с документом, включая файлы js и css?
www139
@CMCDragonkai: Вы можете получить тип документа отдельно и добавить его к строке разметки. Не знаю, я знаю, но возможно.
Майк Брански
76

Ты можешь сделать

new XMLSerializer().serializeToString(document)

в браузерах новее чем IE 9

Смотрите https://caniuse.com/#feat=xml-serializer.

Эрик Айгнер
источник
5
Это был первый правильный ответ по дате / времени. Части страницы, такие как декларация XML, не будут включены, и браузеры будут манипулировать кодом при использовании других «ответов». Это единственное сообщение, за которое нужно проголосовать (дос опубликован через три дня). Люди должны обратить внимание!
Джон
2
Это не совсем правильно, так как он serializeToString выполняет кодирование HTML. Например, если ваш код содержит стили, определяющие шрифты, такие как «Times New Roman», «Times», с засечками, кавычки будут кодироваться в формате html. Возможно, это не важно для некоторых из вас, но для меня это ...
Марко
3
@ Джон хорошо, что ОП на самом деле запрашивает «весь HTML в тегах html». И выбранный лучший ответ Колина Бернетта действительно достигает этого. Этот конкретный ответ (ответ Эрика) будет включать теги html и тип документа. Тем не менее, это был абсолютно алмаз для меня и именно то, что я искал! Ваш комментарий тоже помог, потому что он заставил меня потратить больше времени на этот ответ, так что спасибо :)
evanrmurphy
2
Я думаю, что люди должны быть осторожны с этим, особенно потому, что он возвращает значение, которое не является фактическим HTML, который получает ваш браузер. В моем случае это добавило атрибуты к htmlтегу, которые сервер фактически никогда не отправлял :(
onassar
1
Это поддерживается в каждом браузере. Как эта плохая поддержка браузера?
Эрик
44

Я считаю, что document.documentElement.outerHTMLдолжен вернуть это для вас.

Согласно MDN , outerHTMLподдерживается в Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile и Safari Mobile. outerHTMLнаходится в спецификации разбора и сериализации DOM .

На странице MSDN outerHTMLсвойства указано, что она поддерживается в IE 5+. Ответ Колина ссылается на страницу причудливого режима W3C, которая предлагает хорошее сравнение кросс-браузерной совместимости (также для других функций DOM).

нолдорин
источник
Не все браузеры поддерживают это.
Колин Бернетт
@ Колин: Да, хорошая мысль. Судя по опыту, я помню, что и IE 6+, и Firefox поддерживают его, хотя страница, на которую вы ссылаетесь, указывает на иное ...
Noldorin
Firefox не поддерживает OuterHTML. Это является собственностью IE. developer.mozilla.org/En/...
Джесси Dearing
4
Есть ли способ получить все, включая doctype и html тэги?
trusktr
1
Мой был первым, на самом деле. : P
Нолдорин
40

Я попробовал различные ответы, чтобы увидеть, что возвращается. Я использую последнюю версию Chrome.

Предложение document.documentElement.innerHTML;вернулось<head> ... </body>

Предложение Габи document.getElementsByTagName('html')[0].innerHTML;вернуло то же самое.

Предложение document.documentElement.outerHTML;вернулось, и <html><head> ... </body></html> это все, кроме «doctype».

Вы можете получить объект doctype с помощью команды. document.doctype; Это возвращает объект, а не строку, поэтому, если вам нужно извлечь подробности в виде строк для всех типов документов вплоть до HTML5 включительно, это описано здесь: Получить DocType для HTML в виде строки с помощью Javascript

Я хотел только HTML5, поэтому для создания всего документа мне было достаточно следующего:

alert('<!DOCTYPE HTML>' + '\n' + document.documentElement.outerHTML);

paulo62
источник
6
Это самый полный ответ и должен быть принят. Начиная с 2016 года, совместимость браузера завершена, и упоминать ее подробно (как в принятом в настоящее время ответе) больше не нужно.
Дан Даскалеску
10

Вы также можете сделать:

document.getElementsByTagName('html')[0].innerHTML

Вы не получите тег Doctype или html, но все остальное ...

Hakan
источник
5
document.documentElement.outerHTML
Брайан Кэмпбелл
источник
1
Не все браузеры поддерживают это.
Колин Бернетт
2
Поддерживается в Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile и Safari Mobile ( MDN ). outerHTMLнаходится в спецификации разбора и сериализации DOM .
XP1
Ответ Колина более подробный.
Дан Даскалеску
4

ВЕРОЯТНО ТОЛЬКО IE:

>     webBrowser1.DocumentText

для FF с 1.0:

//serialize current DOM-Tree incl. changes/edits to ss-variable
var ns = new XMLSerializer();
var ss= ns.serializeToString(document);
alert(ss.substr(0,300));

может работать в ФФ. (Показывает ОЧЕНЬ ПЕРВЫЕ 300 символов из ОЧЕНЬ начала исходного текста, в основном doctype-defs.)

НО имейте в виду, что обычный диалог «Сохранить как» FF НЕ МОЖЕТ сохранять текущее состояние страницы, скорее, оригинально загруженный X / h / tml-source-text !! (POST-up ss к некоторому временному файлу и перенаправление на него может доставить сохраняемый исходный текст С изменениями / правками, внесенными в него ранее.)

Хотя FF удивляет хорошим восстановлением "back" и включением NICE состояний / значений в "Save (as) ..." для полей ввода, подобных вводу, textarea и т. Д., А не для элементов в contenteditable / designMode ...

Если НЕ XHTML-соотв. xml-файл (mime-type, НЕ просто расширение файла!), можно использовать document.open/write/close, чтобы УСТАНОВИТЬ appr. содержимое исходного слоя, которое будет сохранено в диалоговом окне сохранения пользователя из меню «Файл / Сохранить» в FF. см .: http://www.w3.org/MarkUp/2004/xhtml-faq#docwrite соотв.

https://developer.mozilla.org/en-US/docs/Web/API/document.write

Нейтрально к вопросам X (ht) ML, попробуйте "view-source: http: // ..." в качестве значения src-attrib для iframe (созданного сценарием !?), - чтобы получить доступ к iframes- документ в ФФ:

<iframe-elementnode>.contentDocumentсм. Google "MDN ContentDocument" для ок. члены, такие как 'textContent', например. «Получил это много лет назад и не хотел ползти к нему. Если все еще острая необходимость, упомяните это, что я должен погрузиться в ...

DOS
источник
2
document.documentElement.innerHTML
cherouvim
источник
Это не возвращает <html ...>тег.
Дан Даскалеску
1

Использование document.documentElement.

На этот же вопрос ответили здесь: https://stackoverflow.com/a/7289396/2164160

Veer En
источник
Этот вопрос должен быть закрыт как почти дубликат этого вопроса, который намного старше. Во всяком случае, интересная часть заключается в том, что вам нужно .outerHTMLи получить document.doctype, и самый полный ответ Паоло .
Дан Даскалеску
1

Чтобы также получить информацию, выходящую за пределы <html>...</html>, самое главное, <!DOCTYPE ...>объявления, вы можете пройти по document.childNodes, превратив каждый из них в строку:

const html = [...document.childNodes]
    .map(node => nodeToString(node))
    .join('\n') // could use '' instead, but whitespace should not matter.

function nodeToString(node) {
    switch (node.nodeType) {
        case node.ELEMENT_NODE:
            return node.outerHTML
        case node.TEXT_NODE:
            // Text nodes should probably never be encountered, but handling them anyway.
            return node.textContent
        case node.COMMENT_NODE:
            return `<!--${node.textContent}-->`
        case node.DOCUMENT_TYPE_NODE:
            return doctypeToString(node)
        default:
            throw new TypeError(`Unexpected node type: ${node.nodeType}`)
    }
}

Я опубликовал этот код как document-outerhtml на npm.


edit Обратите внимание, что приведенный выше код зависит от функции doctypeToString; его реализация может быть следующей (приведенный ниже код публикуется на npm как doctype-to-string ):

function doctypeToString(doctype) {
    if (doctype === null) {
        return ''
    }
    // Checking with instanceof DocumentType might be neater, but how to get a
    // reference to DocumentType without assuming it to be available globally?
    // To play nice with custom DOM implementations, we resort to duck-typing.
    if (!doctype
        || doctype.nodeType !== doctype.DOCUMENT_TYPE_NODE
        || typeof doctype.name !== 'string'
        || typeof doctype.publicId !== 'string'
        || typeof doctype.systemId !== 'string'
    ) {
        throw new TypeError('Expected a DocumentType')
    }
    const doctypeString = `<!DOCTYPE ${doctype.name}`
        + (doctype.publicId ? ` PUBLIC "${doctype.publicId}"` : '')
        + (doctype.systemId
            ? (doctype.publicId ? `` : ` SYSTEM`) + ` "${doctype.systemId}"`
            : ``)
        + `>`
    return doctypeString
}

Gerben
источник
0

Я всегда использую

document.getElementsByTagName('html')[0].innerHTML

Возможно, это не правильный путь, но я могу понять это, когда увижу это.

Габи де Вильде
источник
Это неверно, потому что он не вернет <html...>тег.
Дан Даскалеску
0

Мне просто нужен html типа документа и он должен нормально работать в IE11, Edge и Chrome. Я использовал код ниже, он работает нормально.

function downloadPage(element, event) {
    var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);

    if ((navigator.userAgent.indexOf("MSIE") != -1) || (!!document.documentMode == true)) {
        document.execCommand('SaveAs', '1', 'page.html');
        event.preventDefault();
    } else {
        if(isChrome) {
            element.setAttribute('href','data:text/html;charset=UTF-8,'+encodeURIComponent('<!doctype html>' + document.documentElement.outerHTML));
        }
        element.setAttribute('download', 'page.html');
    }
}

и в вашем теге привязки используйте это.

<a href="#" onclick="downloadPage(this,event);" download>Download entire page.</a>

пример

    function downloadPage(element, event) {
    	var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
    
    	if ((navigator.userAgent.indexOf("MSIE") != -1) || (!!document.documentMode == true)) {
    		document.execCommand('SaveAs', '1', 'page.html');
    		event.preventDefault();
    	} else {
    		if(isChrome) {
                element.setAttribute('href','data:text/html;charset=UTF-8,'+encodeURIComponent('<!doctype html>' + document.documentElement.outerHTML));
    		}
    		element.setAttribute('download', 'page.html');
    	}
    }
I just need doctype html and should work fine in IE11, Edge and Chrome. 

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

<p>
<a href="#" onclick="downloadPage(this,event);"  download><h2>Download entire page.</h2></a></p>

<p>Some image here</p>

<p><img src="https://placeimg.com/250/150/animals"/></p>

kiranvj
источник
0

Я использую outerHTMLдля элементов (основной <html>контейнер) и XMLSerializerдля всего остального, включая <!DOCTYPE>случайные комментарии вне <html>контейнера, или что-то еще может быть там. Кажется, что пробелы не сохраняются вне <html>элемента, поэтому по умолчанию я добавляю новые строки с помощью sep="\n".

function get_document_html(sep="\n") {
    let html = "";
    let xml = new XMLSerializer();
    for (let n of document.childNodes) {
        if (n.nodeType == Node.ELEMENT_NODE)
            html += n.outerHTML + sep;
        else
            html += xml.serializeToString(n) + sep;
    }
    return html;
}

console.log(get_document_html().slice(0, 200));

Сэм Уоткинс
источник
-2

Вы должны пройтись по документу childNodes и получить содержимое externalHTML.

в VBA это выглядит так

For Each e In document.ChildNodes
    Put ff, , e.outerHTML & vbCrLf
Next e

используя это, позволяет получить все элементы веб-страницы, включая узел <! DOCTYPE>, если он существует

milevyo
источник
-9

Правильный путь на самом деле:

webBrowser1.DocumentText

Дамиано
источник