Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

regex pour isoler le contenu d'un body

21 réponses
Avatar
SuperG2
Bonjour

Alors la, je marche sur la corde raid ... Admirez l'équilibriste ... :)

Une regex ... oui oui, ce mot barbare que j'ai lu il y a deux ans ... Ce mot
qui me faisiat pensé que ... le jour ou je le comprendrais je pourais peut
être dire que je connais un piti peu le PHP ... :p

Et bien voilà, je suis en plein dedant :)

J'utilise un logiciel CMS pour rédiger un contenu à mettre en ligne, et la
seule solution pour rendre le travail propre serait que j'arrive a récupérer
le contenu alors généré ... (Un sacré bordel lol)

Comment alors pourais je récupérer le body, son contenu et le /body pour
laisser se mourir notre pauvre doctype préconfiguré ainsi que les données du
head :p

Merci de vos avis éclairés, en attendant je vais allumer la lumière ;-)

Super G2 en mode aille ma nuque, c'est pas possible !

10 réponses

1 2 3
Avatar
Olivier Miakinen

Une regex ... oui oui, ce mot barbare que j'ai lu il y a deux ans ... [...]

Comment alors pourais je récupérer le body, son contenu et le /body pour
laisser se mourir notre pauvre doctype préconfiguré ainsi que les données du
head :p


En toute généralité, pour parser du (X)HTML, il faut plus que des
regexp. Mais si c'est juste pour récupérer ce qui va de <body> à
</body> tu peux faire par exemple :

$body = preg_replace('|.*(<body>.*</body>).*|s', '$1', $document);

À adapter si jamais tu risques de rencontrer des <BODY> ou des < body >
et que tu veuilles les accepter.

Avatar
SuperG2
Merci de ta réponse, si tu as le temps, tu peu essayer de me la traduire en
français ? Décidément, c'est bizzard à assimiler.
Un tuto vidéo serait du meilleur effet ;-)

Voilà ce que moi j'ai mis en place :

<?php

$texte = "<html><head></head><body><h1>Un titreH1 </h1><br/>du contenu<h2>Un
titre H2</h2>du contenu<br/><h3>Un titre H3</h3><div align="center">Hello
REGEX</div></body></html>";

echo("Le code d'origine à traiter<br/>");
$origine = htmlentities($texte);
echo ("$origine<br/>");


if (preg_match('@<body>(.+)</body>@U', $texte, $reg1))
{
/* print"$reg1[1]"; */
echo ("LE REGEX FONCTIONNE : LE CONTENU DE BODY EST RECUPERE !<br/>");
}
else
{
echo "<br>Ne Marche pas";
}

echo("Le code de sortie<br/>");
$sortie = htmlentities($reg1[1]);
echo ("$sortie<br/>");

?>
Avatar
Olivier Miakinen
Merci de ta réponse, si tu as le temps, tu peux essayer de me la traduire en
français ?


:-D

Je n'avais pas l'impression de causer en swahili.

Décidément, c'est bizarre à assimiler.
Un tuto vidéo serait du meilleur effet ;-)


Volontiers, si tu me payes la caméra, l'ordinateur assez puissant, et
bien sûr le logiciel de capture et de montage.

Voilà ce que moi j'ai mis en place :


Bon, eh bien je vais essayer de traduire en français ce que tu as fait.

<?php

$texte = "<html><head></head><body><h1>Un titreH1 </h1><br/>du contenu<h2>Un
titre H2</h2>du contenu<br/><h3>Un titre H3</h3><div align="center">Hello
REGEX</div></body></html>";


Ok. Ça manque un peu d'espaces et de sauts de ligne, mais c'est une
jolie soupe de balises. Et la plupart des navigateurs devraient savoir
en faire quelque chose.

echo("Le code d'origine à traiter<br/>");
$origine = htmlentities($texte);
echo ("$origine<br/>");


Ok.

if (preg_match('@<body>(.+)</body>@U', $texte, $reg1))


1) Tu préfères utiliser preg_match() au lieu de preg_replace(). C'est
ton droit le plus strict.

2) Tu as utilisé "@" là où j'avais utilisé "|". Là encore, c'est comme
tu veux. Il faut juste éviter (entre autres) le caractère "/" qui est
déjà utilisé dans la regexp.

3) Dans ta question, tu avais dit que tu voulais récupérer le <body> et
le </body> en plus du contenu, mais la position des parenthèses fait que
tu ne récupèreras que le contenu dans $reg1[1]. Cela dit, $reg1[0] doit
contenir l'ensemble.

4) L'option U n'est pas utile puisque, jusqu'à preuve du contraire, il y
a un seul body dans un code html.

5) En revanche, l'option s sera indispensable le jour où le code HTML ne
sera pas tout entier sur une seule ligne (ce qui est quand même un cas
assez fréquent).

Donc :
if (preg_match('@<body>(.+)</body>@s', $texte, $reg1))

{
/* print"$reg1[1]"; */
echo ("LE REGEX FONCTIONNE : LE CONTENU DE BODY EST RECUPERE !<br/>");


Oui. D'après la doc tu dois avoir le contenu de BODY dans $reg1[1], et
le contenu plus les deux balises dans $reg1[0].

}
else
{
echo "<br>Ne Marche pas";
}

echo("Le code de sortie<br/>");
$sortie = htmlentities($reg1[1]);
echo ("$sortie<br/>");

?>


Euh... quelle est la question, au fait ? Il ne te plaît pas, ton code ?

À tout hasard voici quelques liens utiles :
http://fr2.php.net/manual/fr/reference.pcre.pattern.modifiers.php
http://fr2.php.net/manual/fr/reference.pcre.pattern.syntax.php
http://fr2.php.net/manual/fr/function.preg-match.php
http://fr2.php.net/manual/fr/function.preg-replace.php

Avatar
Bruno Desthuilliers
(snip)
En toute généralité, pour parser du (X)HTML, il faut plus que des
regexp. Mais si c'est juste pour récupérer ce qui va de <body> à
</body> tu peux faire par exemple :

$body = preg_replace('|.*(<body>.*</body>).*|s', '$1', $document);

À adapter si jamais tu risques de rencontrer des <BODY> ou des < body >


Ou encore:
<body truc="bidule" machin="chouette">

Avatar
SAM

Salutatous,

Je m'immisce pour parler de ma marotte du moment :
les fonctions DOM de PHP

<?php

$texte = "<html><head></head><body><h1>Un titreH1 </h1><br/>du contenu<h2>Un
titre H2</h2>du contenu<br/><h3>Un titre H3</h3><div align="center">Hello
REGEX</div></body></html>";


Ok. Ça manque un peu d'espaces et de sauts de ligne, mais c'est une
jolie soupe de balises. Et la plupart des navigateurs devraient savoir
en faire quelque chose.


Pour une soupe c'est une soupe !
J'ai tenté tant bien que mal d'essayer d'extraire le contenu du body du
$texte via ce que je comprends des fonctions DOM.

Je soumets donc à votre tès grande sagacité le code suivant
(qui n'a sans doute guère d'intérêt dans ce petit contexte mais qui
pourrait être extrêmement simplifié si la finalité est de construire une
nouvelle page "rappropriée")


Voilà (insertion dans un div du contenu du body de $texte) :

<?php
$texte = "<html><head></head><body><h1 ID='TRUC'
STYLE='text-align:center'>Un titre H1</h1><br/>du contenu<h2>Un titre
H2</h2>du contenu<br/><h3>Un titre H3</h3><div align="center">Hello
REGEX</div></body></html>";
$sortie = "Le code d'origine à traiter" ;

function printElement( $elemt ) {
$tag = $elemt->nodeName;
$attr = '';
$attr = $elemt->hasAttribute('id')?
" id='".$elemt->getAttribute('id')."'" : "";
$attr .= $elemt->hasAttribute('name')?
" name='".$elemt->getAttribute('name')."'" : "";
$attr .= $elemt->hasAttribute('class')?
" class='".$elemt->getAttribute('class')."'" : "";
$attr .= $elemt->hasAttribute('style')?
" style='".$elemt->getAttribute('style')."'" : "";
$txt = '';
if ($elemt->hasChildNodes()) {
foreach ($elemt->childNodes as $nodling) {
$txt .= $nodling->nodeValue;
}
}
$tag2 =(strtolower($tag) != 'br' && strtolower($tag) != 'hr')?
" </$tag>" : "";
return "<$tag$attr>n$txtn$tag2n";
}

$doc = new DOMDocument();
$doc->loadHTML($texte);
$origine = $doc->getElementsByTagName("body")->item(0);
$origine = $origine->getElementsByTagName("*");

print"<h1 style='color:red'>$sortie</h1>n";
print "<div style='border:1px solid;paddind:10px;background:#ffc'>n";

if( $lg = $origine->length )
for ( $i = 0; $i < $lg; $i++ ) {
$item = $origine->item($i);
echo printElement( $item);
}

print "</div><!-- fin d'insertion -->";
?>


Et où l'on voit bien ce que donne une soupe de balises quand on tente de
l'analyser :
le bout de texte 'du contenu'
qui est en dehors de tout conteneur (tag ?) est oublié au passage ...

Maintenant, il est possible que je me sois gourationné et que plus
simple se pourrait ?

--
sm


Avatar
SuperG2
Arf oui, c'est vrai !! Est ce que ma solution prend en compte les body
'trafiqués' :p

Bienvu Bruno ;-)

Hmmm donc je dois trouver le caractère ou le jeu de caracteres qui va me
permettre de dire '<body' .(TOUT). '>'

Ok :p

<?php

$texte = "<html><head></head><body><h1>Un titreH1 </h1><br/>du contenu<h2>Un
titre H2</h2>du contenu<br/><h3>Un titre H3</h3><div align="center">Hello
REGEX</div></body></html>";

echo("Le code d'origine à traiter<br/>");
$origine = htmlentities($texte);
echo ("$origine<br/>");


if (preg_match('@<body>(.+)</body>@U', $texte, $reg1))
{
/* print"$reg1[1]"; */
echo ("LE REGEX FONCTIONNE : LE CONTENU DE BODY EST RECUPERE !<br/>");
}
else
{
echo "<br>Ne Marche pas";
}

echo("Le code de sortie<br/>");
$sortie = htmlentities($reg1[1]);
echo ("$sortie<br/>");

?>

(snip)
En toute généralité, pour parser du (X)HTML, il faut plus que des
regexp. Mais si c'est juste pour récupérer ce qui va de <body> à
</body> tu peux faire par exemple :

$body = preg_replace('|.*(<body>.*</body>).*|s', '$1', $document);

À adapter si jamais tu risques de rencontrer des <BODY> ou des < body >


Ou encore:
<body truc="bidule" machin="chouette">



Avatar
Mickael Wolff

Et où l'on voit bien ce que donne une soupe de balises quand on tente de
l'analyser :
le bout de texte 'du contenu'
qui est en dehors de tout conteneur (tag ?) est oublié au passage ...


Ben non , c'est toi qui l'oublie :

$origine = $origine->getElementsByTagName("*");


Les textnodes de body ne sont pas récupérés lors de cette man½uvre,
puisque tu ne prend que ces éléments fils.

Maintenant, il est possible que je me sois gourationné et que plus
simple se pourrait ?


Plus simple pourrait... Mais que veux tu faire ? Hormis faire mumuse :)

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Avatar
Paul
Bonjour
...

Comment alors pourais je récupérer le body, son contenu et le /body pour
laisser se mourir notre pauvre doctype préconfiguré ainsi que les
données du head
Une idée comme ça : comme les occurences du mot 'body' ne peuvent être

plus de 2, pourquoi ne pas commencer par un explode('body',$texte,-1) et
ainsi récupérer l'en tête et le corps ?

Avatar
Bruno Desthuilliers
Arf oui, c'est vrai !! Est ce que ma solution prend en compte les body
'trafiqués' :p

Bienvu Bruno ;-)

Hmmm donc je dois trouver le caractère ou le jeu de caracteres qui va me
permettre de dire '<body' .(TOUT). '>'


Ce que tu veux, c'est '<body' suivi de "tout sauf >" 0 à N fois suivi de
'>'

"tout sauf >" s'écrit avec une classe complémentée: [^>]

Donc ça devrait être quelque chose comme:

'<body[^>]*>(.*)</body>'

Avec les flags qui vont bien pour la (non) prise en compte de la casse etc.

(NB : non testé)

Avatar
SAM

Et où l'on voit bien ce que donne une soupe de balises quand on tente de
l'analyser :
le bout de texte 'du contenu'
qui est en dehors de tout conteneur (tag ?) est oublié au passage ...


Ben non , c'est toi qui l'oublie :

$origine = $origine->getElementsByTagName("*");


Les textnodes de body ne sont pas récupérés lors de cette man½uvre,
puisque tu ne prend que ces éléments fils.


Bon, et comment faire ?
Depuis, j'avais vu ce manque, et cette fois je récupère *tout* le texte
mais vraiment *tout* et y compris celui des autres balises et en un seul
jet.
:-(

Maintenant, il est possible que je me sois gourationné et que plus
simple se pourrait ?


Plus simple pourrait... Mais que veux tu faire ? Hormis faire mumuse :)


Comme +/- dit en intro de mon intervention,
je découvre les fonctions DOM de php.
(c'est d'ailleurs ma seule motivation à venir sur ce ng et j'ouvre un
nouveau fil à ce sujet)

Disons qu'ici je tentais d'attaquer la question par un autre angle que
les expressions régulières.

A ce que je comprends, l'idée est de réceptionner une page (sans doute
construite par une espèce de formulaire) d'en extraire que le contenu
("contenu du body") pour l'intégrer dans une partie d'une autre et à mon
idée c'est vraiment un travail à faire traiter via le DOM.

Avec un peu de chance le résultat pourra être un peu + standard ?

L'exemple donné ne passant pas au validateur :
" You have used character data somewhere it is not permitted to appear.
* putting text directly in the body of the document without wrapping
it in a container element (such as a <p>aragraph</p>)"

--
sm


1 2 3