¿Cómo obtener todo el documento HTML como una cadena?

237

¿Hay alguna manera en JS de obtener todo el HTML dentro de las etiquetas html , como una cadena?

document.documentElement.??
El flash
fuente
10
La única respuesta correcta: stackoverflow.com/questions/817218/… ( deje de votar las respuestas internas / externas de HTML, ¡NO proporcionan la fuente completa! )
John
2
document.body.parentElement.innerHTML
Programas Redwolf
@John, ¿qué no proporcionan?
bluejayke

Respuestas:

320

MS agregó las propiedades outerHTMLy innerHTMLhace algún tiempo.

Según MDN , outerHTMLes compatible con Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile y Safari Mobile. outerHTMLestá en la especificación de análisis y serialización DOM .

Vea quirksmode para la compatibilidad del navegador para lo que funcionará para usted. Todo el apoyo innerHTML.

var markup = document.documentElement.innerHTML;
alert(markup);
Colin Burnett
fuente
28
outsideHTML no obtiene el doctype.
CMCDragonkai
2
¡trabajado como un encanto! ¡gracias! ¿Hay alguna forma de obtener el tamaño de cualquiera / todos los archivos vinculados al documento, incluidos los archivos js y css?
www139
@CMCDragonkai: puede obtener el doctype por separado y anteponerlo a la cadena de marcado. No es ideal, lo sé, pero es posible.
Mike Branski
76

Tu puedes hacer

new XMLSerializer().serializeToString(document)

en navegadores más nuevos que IE 9

Ver https://caniuse.com/#feat=xml-serializer

Erik Aigner
fuente
55
Esta fue la primera respuesta correcta según los sellos de fecha / hora. No se incluirán partes de la página, como la declaración XML, y los navegadores manipularán el código al usar las otras "respuestas". Esta es la única publicación que debe ser votada (dos se publican tres días después). ¡La gente necesita prestar atención!
John
2
Esto no es del todo correcto ya que serializeToString realiza una codificación HTML. Por ejemplo, si su código contiene estilos que definen fuentes como "Times New Roman", Times, las comillas recibirán codificación html. Quizás eso no sea importante para algunos de ustedes, pero para mí es ...
Marko
3
@John bueno, el OP realmente pide "todo el HTML dentro de las etiquetas html". Y la mejor respuesta seleccionada por Colin Burnett logra esto. Esta respuesta particular (Erik's) incluirá las etiquetas html y el doctype. Dicho esto, ¡esto fue totalmente un diamante en bruto para mí y exactamente lo que estaba buscando! Tu comentario también ayudó porque me hizo pasar más tiempo con esta respuesta, así que gracias :)
evanrmurphy
2
Creo que la gente debería tener cuidado con este, específicamente porque devuelve un valor que no es el html real que recibe su navegador. En mi caso, agregó atributos a la htmletiqueta que el servidor nunca envió :(
onassar
1
Es compatible con todos los navegadores. ¿Cómo es este pobre soporte del navegador?
Erik Aigner
44

Creo que document.documentElement.outerHTMLdebería devolverte eso.

Según MDN , outerHTMLes compatible con Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile y Safari Mobile. outerHTMLestá en la especificación de análisis y serialización DOM .

La página de MSDN en la outerHTMLpropiedad señala que es compatible con IE 5+. La respuesta de Colin enlaza con la página W3C quirksmode, que ofrece una buena comparación de la compatibilidad entre navegadores (para otras funciones DOM también).

Noldorin
fuente
No todos los navegadores admiten esto.
Colin Burnett
@ Colin: Sí, buen punto. Por experiencia, me parece recordar que tanto IE 6+ como Firefox lo admiten, aunque la página del modo peculiar que vinculó sugiere lo contrario ...
Noldorin
Firefox no es compatible con OuterHTML. Es propiedad de IE. developer.mozilla.org/En/…
Jesse Dearing
44
¿Hay alguna manera de obtener todo, incluidas las etiquetas doctype y html?
trusktr
1
El mío fue el primero, en realidad. : P
Noldorin
40

Intenté las diferentes respuestas para ver qué se devuelve. Estoy usando la última versión de Chrome.

La sugerencia document.documentElement.innerHTML;regresó<head> ... </body>

La sugerencia de Gaby document.getElementsByTagName('html')[0].innerHTML;devolvió lo mismo.

La sugerencia document.documentElement.outerHTML;regresó, <html><head> ... </body></html> que es todo, aparte del 'doctype'.

Puede recuperar el objeto doctype con document.doctype; Esto devuelve un objeto, no una cadena, por lo que si necesita extraer los detalles como cadenas para todos los doctypes hasta HTML5 incluido, se describe aquí: Obtenga DocType de un HTML como cadena con Javascript

Solo quería HTML5, por lo que lo siguiente fue suficiente para crear el documento completo:

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

paulo62
fuente
66
Esta es la respuesta más completa y debe ser aceptada. A partir de 2016, la compatibilidad del navegador es completa y ya no es necesario mencionarlo en detalle (como en la respuesta actualmente aceptada).
Dan Dascalescu
10

También puedes hacer:

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

No obtendrá la etiqueta Doctype o html, pero todo lo demás ...

Hakan
fuente
5
document.documentElement.outerHTML
Brian Campbell
fuente
1
No todos los navegadores admiten esto.
Colin Burnett
2
Compatible con Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile y Safari Mobile ( MDN ). outerHTMLestá en la especificación de análisis y serialización DOM .
XP1
La respuesta de Colin es más detallada.
Dan Dascalescu
4

PROBABLEMENTE SOLO IE:

>     webBrowser1.DocumentText

para FF desde 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));

puede funcionar en FF. (Muestra los PRIMEROS 300 caracteres desde el principio del texto fuente, principalmente doctype-defs).

¡PERO tenga en cuenta que el diálogo "Guardar como" normal de FF NO PODRÍA guardar el estado actual de la página, sino el X / h / tml-source-text cargado originalmente! (un POST-up de ss a algún archivo temporal y redirigirlo a ese podría entregar un texto fuente guardable CON los cambios / ediciones previamente realizados).

Aunque FF sorprende por una buena recuperación en "back" y una NICE inclusión de estados / valores en "Save (as) ..." para CAMPOS de entrada, área de texto , etc., no en elementos en contenteditable / designMode ...

Si NO es un xhtml- resp. archivo xml (tipo mime, ¡NO solo extensión de nombre de archivo!), se puede usar document.open/write/close para CONFIGURAR la aplicación. contenido a la capa de origen, que se guardará en el diálogo de guardar del usuario desde el menú Archivo / Guardar de FF. ver: http://www.w3.org/MarkUp/2004/xhtml-faq#docwrite resp.

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

Neutral para las preguntas de X (ht) ML, intente con "view-source: http: // ..." como el valor de src-attrib de un iframe (¡hecho por script !?), - para acceder a un iframes- documento en FF:

<iframe-elementnode>.contentDocument, consulte google "mdn contentDocument" para apr. miembros, como 'textContent' por ejemplo. Lo tengo hace años y no me gusta arrastrarme por él. Si todavía es una necesidad urgente, mencione esto, en el que tengo que sumergirme ...

dos
fuente
2
document.documentElement.innerHTML
cherouvim
fuente
Esto no devuelve la <html ...>etiqueta.
Dan Dascalescu
1

Uso document.documentElement.

Misma pregunta respondida aquí: https://stackoverflow.com/a/7289396/2164160

Veer En
fuente
Esa pregunta debería cerrarse como un duplicado de esta, que es mucho más antigua. De todos modos, la parte interesante es que necesitas .outerHTMLy para obtener el document.doctype, y la respuesta más completa es la de Paolo .
Dan Dascalescu
1

Para que las cosas también salgan de <html>...</html>la <!DOCTYPE ...>declaración, lo más importante , puede recorrer document.childNodes, convirtiendo cada una en una cadena:

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}`)
    }
}

Publiqué este código como document-outsidehtml en npm.


editar Tenga en cuenta que el código anterior depende de una función doctypeToString; su implementación podría ser la siguiente (el código a continuación se publica en npm como 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
fuente
0

Yo siempre uso

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

Probablemente no sea el camino correcto, pero puedo entenderlo cuando lo veo.

gaby de wilde
fuente
Esto es incorrecto porque no devolverá la <html...>etiqueta.
Dan Dascalescu
0

Solo necesito doctype html y debería funcionar bien en IE11, Edge y Chrome. Utilicé el siguiente código, funciona bien.

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');
    }
}

y en su etiqueta de anclaje use así.

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

Ejemplo

    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
fuente
0

Estoy usando outerHTMLpara elementos (el <html>contenedor principal ), y XMLSerializerpara cualquier otra cosa, incluidos <!DOCTYPE>comentarios aleatorios fuera del <html>contenedor, o cualquier otra cosa que pueda estar allí. Parece que el espacio en blanco no se conserva fuera del <html>elemento, por lo que agrego nuevas líneas de forma predeterminada con 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));

Sam Watkins
fuente
-2

Debe recorrer el documento childNodes y obtener el contenido externo HTML.

en VBA se ve así

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

con esto, le permite obtener todos los elementos de la página web, incluido el nodo <! DOCTYPE> si existe

milevyo
fuente
-9

La forma correcta es en realidad:

webBrowser1.DocumentText

Damiano
fuente