IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Expression rationnelle pour détecter du HTML


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti Avatar de chatofor
    Profil pro
    Inscrit en
    Août 2009
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 59
    Par défaut Expression rationnelle pour détecter du HTML
    Bonjour,

    Je veux faire un script qui récupère le contenu de balises HTML paragraphes. Récupérer ce qu'il y a dans <p></p>

    Voici mon sript tout simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $file_contents = "<p>Involontairement au d&eacute;part, plus ou moins volontairement maintenant</p><p>Je l'ai pris involontairement (je dirais m&ecirc;me que c'est les anciens &quot;amis&quot; qui m'y on emmen&eacute;).<br />
    Mais finalement la solitude me pla&icirc;t. J'ai l'impression que c'est fait pour moi.</p>";
    preg_match_all("#<p>(.*)</p>#", $file_contents, $out);
    echo 'affichage';
    Problème, tout n'est pas inclu. La première phrase oui, la deuxième pas du tout.

    Avez-vous une idée de pourquoi ?

    Merci d'avance

    edit : dans mon code les caractères spéciaux sont encodés en HTML genre é = & eacute ;

  2. #2
    Membre expérimenté Avatar de zancrows
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2016
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 159
    Par défaut
    Bonjour, déjà tu devrais échapper le slash dans ton regex
    en suite la 2ème phrase ne match pas parce qu'il le caractère 'entrer' ( \r\n ) après le
    <br />
    tu peux faire des test avec ce site https://regex101.com/r/MW8YOQ/3/

  3. #3
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 018
    Par défaut
    Citation Envoyé par zancrows Voir le message
    Bonjour, déjà tu devrais échapper le slash dans ton regex
    Absolument pas, le slash n'est pas un caractère spécial. Il ne dois être échappé que lorsque le slash est utilisé comme délimiteur de pattern.

    la 2ème phrase ne match pas parce qu'il le caractère 'entrer' ( \r\n )
    'entrée' est plus une touche du clavier qu'un caractère, ensuite suivant le système utilisé, cette touche peux produire dans un éditeur l'une des séquences de caractères suivantes: \n ou \r\n ou \r. Mais effectivement le . ne matche pas le \n par défaut, pour qu'il le fasse, il faut utiliser le modificateur s.

    Mais ce n'est pas le seul problème de cette pattern.

  4. #4
    Membre expérimenté Avatar de zancrows
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2016
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 159
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    Absolument pas, le slash n'est pas un caractère spécial. Il ne dois être échappé que lorsque le slash est utilisé comme délimiteur de pattern.
    autant pour moi

  5. #5
    Membre averti Avatar de chatofor
    Profil pro
    Inscrit en
    Août 2009
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 59
    Par défaut
    Ca paraît effectivement plus simple. Le code une fois adapté à mes besoins donne ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php
    $ch = curl_init();
    $timeout = 0; // set to zero for no timeout
    curl_setopt ($ch, CURLOPT_URL, 'http://m.jeuxvideo.com/forums/42-51-55256100-1-0-1-0-le-chemin-de-la-solitude.htm');
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    $file_contents = curl_exec($ch);
    curl_close($ch);
     
     
    $dom = new DOMDocument;
    $dom->loadHTML($file_contents);
     
    $result = [];
     
    foreach ($dom->getElementsByTagName('p') as $pNode) {
        $content = '';
        foreach ($pNode->childNodes as $childNode) {
            $content .= $dom->saveHTML($childNode);
        }
        $result[] = $content;
    }
    ?>
    <pre><?php var_dump($result); ?></pre>
    Seulement la ligne 12 renvoie une erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Warning: DOMDocument::loadHTML(): Tag header invalid in Entity, line: 19 in /opt/lampp/htdocs/tests/yams/alsa3.php on line 12
     
    Warning: DOMDocument::loadHTML(): Tag section invalid in Entity, line: 25 in /opt/lampp/htdocs/tests/yams/alsa3.php on line 12
     
    Warning: DOMDocument::loadHTML(): Tag footer invalid in Entity, line: 421 in /opt/lampp/htdocs/tests/yams/alsa3.php on line 12
    J'ai cherché du côté de google et j'ai trouvé qu'il fallait entrer ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     libxml_use_internal_errors(true);
    Je n'ai pas cherché donc compris pourquoi mais je te remercie pour ton aide

    Je n'ai pas vraiment compris l'histoire du deuxième foreach avec le childNodes mais je vais y réfléchir

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 018
    Par défaut
    Par défaut, lorsque libxml (la librairie qui se cache derrière les classes de manipulation du DOM en PHP) détecte une erreur dans le code html, un warning est affiché, ce qui est plutôt gênant.
    Ce que fait libxml_use_internal_errors(true), c'est de rediriger ces erreurs vers le gestionnaire d'erreurs de libxml. Ainsi, les erreurs ne sont plus affichées mais tu peux par contre les consulter via libxml_get_errors() qui renvoie un tableau de ces erreurs.
    Autre chose à savoir sur le fonctionnement de libxml_use_internal_errors(), cette fonction renvoie son réglage précédent, ce qui fait qu'on écrit couramment:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $dom = new DOMDocument;
    $state = libxml_use_internal_errors(true); // on stocke l'état précédent
    $dom->loadHTML($html); // c'est ici que la chaîne est parsée et que les erreurs sont détectés.
    libxml_use_internal_errors($state); // on restitue l'état précédent, ainsi on impacte pas les scripts éventuels qui peuvent suivre

  7. #7
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 018
    Par défaut
    Citation Envoyé par chatofor Voir le message
    Je n'ai pas vraiment compris l'histoire du deuxième foreach avec le childNodes mais je vais y réfléchir
    Pourquoi ce deuxième foreach?
    La méthode DOMDocument::saveHTML() renvoie la chaîne du nœud passé en argument mais avec les tags du nœud en question. Donc si $pNode correspond à <p>toto</p>, tu obtiendras <p>toto</p> et non toto.

    D'autre part, si chacun de tes paragraphes ne contenaient qu'un seul nœud texte, on pourrait très bien s'en passer et obtenir leur contenu en faisant:$content = $pNode->nodeValue; qui renvoie tout les éléments texte d'un nœud (y compris celui de ces nœuds enfant). Mais ce n'est pas le cas ici.
    Si on prend le contenu du deuxième paragraphe:
    Je l'ai pris involontairement (je dirais m&ecirc;me que c'est les anciens "amis" qui m'y on emmen&eacute;).<br />
    Mais finalement la solitude me pla&icirc;t. J'ai l'impression que c'est fait pour moi.
    On a:
    • un nœud texte:
      Je l'ai pris involontairement (je dirais m
    • une entité
      &ecirc;
    • un nœud texte:
      me que c'est les anciens "amis" qui m'y on emmen
    • une entité
      &eacute;
    • un nœud texte:
      ).
    • un élément <br />
    • un nœud texte:
      Mais finalement la solitude me pla
    • etc.


    Ces éléments sont de nature différente, donc la seule manière de récupérer le contenu d'une balise consiste à boucler sur ses nœuds enfant et à concaténer leur contenu. La propriété DOMNode::childNodes renvoie une instance de DOMNodeList qui contient les enfants directs d'un élément.

  8. #8
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 018
    Par défaut
    Pour parser du html on utilise DOMDocument, pas les regex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $dom = new DOMDocument;
    $dom->loadHTMLFile($yourfile);
     
    $result = [];
     
    foreach ($dom->getElementsByTagName('p') as $pNode) {
        $content = '';
        // on concatène les nœuds enfants du paragraphe
        foreach ($pNode->childNodes as $childNode) {
            $content .= $dom->saveHTML($childNode);
        }
        $result[] = $content;
    }
    démo

Discussions similaires

  1. [XL-2010] Expressions rationnelles pour des dates (point de point)
    Par Alba1981 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 24/02/2017, 15h53
  2. Expression rationnelle pour éliminer symbole
    Par Invité dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 01/08/2015, 20h13
  3. [RegEx] expression régulière pour détecter apostrophe
    Par flilou dans le forum Langage
    Réponses: 4
    Dernier message: 27/06/2013, 15h01
  4. [RegEx] Expression régulière pour les balises HTML
    Par meloo dans le forum Langage
    Réponses: 3
    Dernier message: 09/07/2009, 15h23
  5. Cherche Expression rationnelle pour isoler une chaîne
    Par ritual dans le forum Shell et commandes GNU
    Réponses: 10
    Dernier message: 18/08/2008, 14h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo