Comment obtenir l'intégralité du document HTML sous forme de chaîne?

237

Existe-t-il un moyen dans JS pour obtenir l'intégralité du HTML dans les balises html , sous forme de chaîne?

document.documentElement.??
Le flash
la source
10
La seule bonne réponse: stackoverflow.com/questions/817218/… ( arrêtez de voter pour les réponses HTML internes / externes, elles ne fournissent PAS la source entière! )
John
2
document.body.parentElement.innerHTML
Programmes Redwolf
@John qu'est-ce qu'ils ne fournissent pas?
bluejayke

Réponses:

320

MS a ajouté les propriétés outerHTMLet il y a innerHTMLquelque temps.

Selon MDN , outerHTMLest pris en charge dans Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile et Safari Mobile. outerHTMLest dans la spécification d' analyse et de sérialisation DOM .

Voir quirksmode pour la compatibilité du navigateur pour ce qui fonctionnera pour vous. Tout soutien innerHTML.

var markup = document.documentElement.innerHTML;
alert(markup);
Colin Burnett
la source
28
externeHTML n'obtient pas le doctype.
CMCDragonkai
2
travaillé comme un charme! Merci! existe-t-il un moyen d'obtenir la taille de tout / tous les fichiers liés au document, y compris les fichiers js et css?
www139
@CMCDragonkai: Vous pouvez obtenir le doctype séparément et l'ajouter à la chaîne de balisage. Pas idéal, je sais, mais possible.
Mike Branski
76

Tu peux faire

new XMLSerializer().serializeToString(document)

dans les navigateurs plus récents que IE 9

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

Erik Aigner
la source
5
Ce fut la première bonne réponse selon les horodatages. Des parties de la page telles que la déclaration XML ne seront pas incluses et les navigateurs manipuleront le code lors de l'utilisation des autres "réponses". C'est le seul message qui devrait être voté (dos est publié trois jours plus tard). Les gens doivent faire attention!
John
2
Ce n'est pas tout à fait correct car il serializeToString effectue un encodage HTML. Par exemple, si votre code contient des styles définissant des polices telles que "Times New Roman", Times, serif, les guillemets seront encodés en HTML. Peut-être que ce n'est pas important pour certains d'entre vous mais pour moi c'est ...
Marko
3
@John et l'OP demande en fait "tout le code HTML dans les balises html". Et la meilleure réponse choisie par Colin Burnett y parvient. Cette réponse particulière (celle d'Erik) inclura les balises html et le doctype. Cela dit, c'était totalement un diamant brut pour moi et exactement ce que je cherchais! Votre commentaire a également aidé car cela m'a fait passer plus de temps avec cette réponse, alors merci :)
evanrmurphy
2
Je pense que les gens devraient être prudents avec celui-ci, en particulier parce qu'il renvoie une valeur qui n'est pas le code HTML réel que votre navigateur reçoit. Dans mon cas, il a ajouté des attributs au htmltag que le serveur n'a jamais réellement envoyés :(
onassar
1
Il est pris en charge dans tous les navigateurs. Comment est cette mauvaise prise en charge du navigateur?
Erik Aigner
44

Je pense que je document.documentElement.outerHTMLdevrais vous le rendre.

Selon MDN , outerHTMLest pris en charge dans Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile et Safari Mobile. outerHTMLest dans la spécification d' analyse et de sérialisation DOM .

La page MSDN sur la outerHTMLpropriété indique qu'elle est prise en charge dans IE 5+. La réponse de Colin renvoie à la page du mode excentrique du W3C, qui offre une bonne comparaison de la compatibilité entre navigateurs (pour d'autres fonctionnalités DOM également).

Noldorin
la source
Tous les navigateurs ne le prennent pas en charge.
Colin Burnett
@Colin: Ouais, bon point. Par expérience, il me semble que IE 6+ et Firefox le supportent tous les deux, bien que la page quirksmode que vous avez liée suggère le contraire ...
Noldorin
Firefox ne prend pas en charge OuterHTML. Il est propriétaire d'IE. developer.mozilla.org/En/…
Jesse Dearing
4
Existe-t-il un moyen d'obtenir tout, y compris le doctype et les balises html?
trusktr
1
Le mien était le premier, en fait. : P
Noldorin
40

J'ai essayé les différentes réponses pour voir ce qui est retourné. J'utilise la dernière version de Chrome.

La suggestion document.documentElement.innerHTML;est revenue<head> ... </body>

La suggestion de Gaby est restée document.getElementsByTagName('html')[0].innerHTML;la même.

La suggestion document.documentElement.outerHTML;est revenue <html><head> ... </body></html> qui est tout sauf le «doctype».

Vous pouvez récupérer l'objet doctype avec document.doctype; Cela renvoie un objet, pas une chaîne, donc si vous avez besoin d'extraire les détails sous forme de chaînes pour tous les doctypes jusqu'à HTML5 inclus, il est décrit ici: Obtenir le DocType d'un HTML en tant que chaîne avec Javascript

Je ne voulais que du HTML5, donc les éléments suivants me suffisaient pour créer le document entier:

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

paulo62
la source
6
C'est la réponse la plus complète et doit être acceptée. Depuis 2016, la compatibilité du navigateur est complète et il n'est plus nécessaire de la mentionner en détail (comme dans la réponse actuellement acceptée).
Dan Dascalescu
10

Vous pouvez également faire:

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

Vous n'obtiendrez pas la balise Doctype ou html, mais tout le reste ...

Hakan
la source
5
document.documentElement.outerHTML
Brian Campbell
la source
1
Tous les navigateurs ne le prennent pas en charge.
Colin Burnett
2
Pris en charge dans Firefox 11, Chrome 0.2, Internet Explorer 4.0, Opera 7, Safari 1.3, Android, Firefox Mobile 11, IE Mobile, Opera Mobile et Safari Mobile ( MDN ). outerHTMLest dans la spécification d' analyse et de sérialisation DOM .
XP1
La réponse de Colin est plus détaillée.
Dan Dascalescu
4

PROBABLEMENT UNIQUEMENT IE:

>     webBrowser1.DocumentText

pour FF à partir de 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));

peut fonctionner en FF. (Affiche les TRÈS PREMIERS 300 caractères du TRÈS début du texte source, principalement des doctype-defs.)

MAIS sachez que le dialogue "Enregistrer sous" normal de FF NE PEUT PAS enregistrer l'état actuel de la page, plutôt le texte source X / h / tml-source chargé à l'origine !! (Un POST-up de ss vers un fichier temporaire et une redirection vers celui-ci pourrait fournir un texte source enregistrable AVEC les changements / modifications qui lui ont été apportés.)

Bien que FF surprenne par une bonne récupération sur "back" et une belle inclusion d'états / valeurs sur "Save (as) ..." pour les champs d'entrée, textarea, etc., pas sur les éléments dans contenteditable / designMode ...

Si ce n'est PAS un xhtml - resp. fichier xml (type mime, PAS seulement extension de nom de fichier!), on peut utiliser document.open/write/close pour FIXER l'appr. contenu dans la couche source, qui sera enregistré dans la boîte de dialogue d'enregistrement de l'utilisateur à partir du menu Fichier / Enregistrer de FF. voir: http://www.w3.org/MarkUp/2004/xhtml-faq#docwrite resp.

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

Neutre par rapport aux questions de X (ht) ML, essayez une "vue-source: http: // ..." comme valeur de l'attribut src d'un iframe (fait par le script !?), - pour accéder à un iframes - document en FF:

<iframe-elementnode>.contentDocument, voir google "mdn contentDocument" pour appr. membres, comme 'textContent' par exemple. «Il y a des années et je n'aime pas ramper pour ça. Si vous avez toujours un besoin urgent, mentionnez-le, dans lequel j'ai pu plonger ...

dos
la source
2
document.documentElement.innerHTML
cherouvim
la source
Cela ne renvoie pas la <html ...>balise.
Dan Dascalescu
1

Utilisez document.documentElement.

Même question répondue ici: https://stackoverflow.com/a/7289396/2164160

Veer En
la source
Cette question devrait être fermée comme étant à peu près un double de celle-ci, qui est beaucoup plus ancienne. Quoi qu'il en soit, la partie intéressante est que vous avez besoin .outerHTMLet pour l'obtenir document.doctype, et la réponse la plus complète est celle de Paolo .
Dan Dascalescu
1

Pour obtenir également des éléments en dehors de <html>...</html>, plus important encore, la <!DOCTYPE ...>déclaration, vous pouvez parcourir document.childNodes, en les transformant chacun en une chaîne:

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

J'ai publié ce code en tant que document-externalhtml sur npm.


edit Notez que le code ci-dessus dépend d'une fonction doctypeToString; son implémentation pourrait être la suivante (le code ci-dessous est publié sur npm en tant que 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
la source
0

J'utilise toujours

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

Probablement pas dans le bon sens mais je peux le comprendre quand je le vois.

gaby de wilde
la source
Ceci est incorrect car il ne renverra pas la <html...>balise.
Dan Dascalescu
0

J'ai juste besoin de doctype html et devrait fonctionner correctement dans IE11, Edge et Chrome. J'ai utilisé le code ci-dessous, cela fonctionne 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');
    }
}

et dans votre balise d'ancrage, utilisez comme ceci.

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

Exemple

    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
la source
0

J'utilise outerHTMLpour les éléments (le <html>conteneur principal ), et XMLSerializerpour tout autre élément, y compris <!DOCTYPE>des commentaires aléatoires à l'extérieur du <html>conteneur, ou quoi que ce soit d'autre. Il semble que les espaces ne soient pas conservés en dehors de l' <html>élément, donc j'ajoute des sauts de ligne par défaut avec 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
la source
-2

Vous devez parcourir le document childNodes et obtenir le contenu externalHTML.

en VBA, il ressemble à ceci

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

en l'utilisant, vous permet d'obtenir tous les éléments de la page Web, y compris le nœud <! DOCTYPE> s'il existe

milevyo
la source
-9

La bonne façon est en fait:

webBrowser1.DocumentText

Damiano
la source