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

Python Discussion :

Optimisation regexp sur contenu html


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de arnaudk
    Inscrit en
    Février 2009
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 38
    Par défaut Optimisation regexp sur contenu html
    Bonsoir,

    Les regexp c'est beau, sauf quand on s'arrache les cheveux dessus.
    Mon problème est assez simple : dans un contenu html, j'aimerais "neutraliser" tous les symboles dollars présents entre des balises pre, mais pas les autres.

    La raison est que tous les autres dollars servent à générer des formules compilées en latex, et les $ présents entre les balise pre sont des bouts de code php ou jquery dans mes différents tutos.

    Voici un exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <p>des dollars ici $33$ et ici $$45$$ et dans un pre <pre> voila $ bla bla $ bla $ et $$ </pre> et encore dehors $86$</p>
    Le filtre latex va remplacer par exemple $33$ par une image <img .../>

    Le seul moyen que j'ai trouvé de "neutraliser" ces dollars entre balises pre, c'est de les remplacer par une autre chaine, le temps de compiler les formules latex, puis revenir en arrière.
    Donc cela donnerait un truc du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <p>des dollars ici $33$ et ici $$45$$ et dans un pre <pre> voila YOUPI bla bla YOUPI bla YOUPI et YOUPIYOUPI </pre> et encore dehors $86$</p>
    puis compilation latex des images :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <p>des dollars ici <img.../> et ici <img.../> et dans un pre <pre> voila YOUPI bla bla YOUPI bla YOUPI et YOUPIYOUPI </pre> et encore dehors <img.../></p>
    et on revient en arrière, on vire les YOUPI pour des dollars :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <p>des dollars ici <img.../> et ici <img.../> et dans un pre <pre> voila $ bla bla $ bla $ et $$</pre> et encore dehors <img.../></p>
    Sauf que, non seulement cela fait beaucoup de scan complets, mais en plus je n'arrive pas à trouver une unique regexp pour remplacer simplement tous les $ entre pre d'un coup ( je m'en tire avec plusieurs recherches successives ).

    C'est loin d'être joli et optimal.
    Auriez-vous une idée pour simplifier cela ?

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Voilà une solution simple qui a l'air de fonctionner:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    def sub(g):
        return g.group(0).replace('$', 'YOUPI')
     
    ch = "<p>des dollars ici $33$ et ici $$45$$ et dans un pre <pre> voila $ bla bla $ bla $ et $$ </pre> et encore dehors $86$</p>"
     
    print re.sub(r'(<pre>)([^<]*)(</pre>)', sub, ch)
     
    <p>des dollars ici $33$ et ici $$45$$ et dans un pre <pre> voila YOUPI bla bla YOUPI bla YOUPI et YOUPIYOUPI </pre> et encore dehors $86$</p>
    Le principe est simple: le motif isole chaque séquence "<pre>.....</pre>", et la fonction sub remplace tous les '$' par 'YOUPI'. On peut, bien sûr, faire le remplacement inverse plus tard.

    Il pourrait y avoir plusieurs séquences "<pre>.....</pre>", et ces séquences peuvent être coupées par une fin de ligne. Par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ch = """xx$xx$$xx<pre>xx$xx$$xx</pre>xx$xx$$xx<pre>xx$x
    x$$xx</pre>xx$xx$$xx<pre>xx$xx$$xx</pre>xx$xx$$xx"""
     
    print re.sub(r'(<pre>)([^<]*)(</pre>)', sub, ch)
     
    xx$xx$$xx<pre>xxYOUPIxxYOUPIYOUPIxx</pre>xx$xx$$xx<pre>xxYOUPIx
    xYOUPIYOUPIxx</pre>xx$xx$$xx<pre>xxYOUPIxxYOUPIYOUPIxx</pre>xx$xx$$xx
    Pour accepter qu'il y ait plusieurs séquences possibles "<pre>.....</pre>", il ne doit pas y avoir de '<' entre "<pre>" et "</pre>". S'il n'y a qu'une seule séquence, on peut faire sauter cette contrainte en remplaçant dans le motif "([^<]*)" par "(.*)".

  3. #3
    Membre Expert

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Par défaut
    Il y a moyen d’être plus restrictif sur le test, en ne s’arrêtant que sur une balise </pre>, avec un petit look ahead négatif*:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    r'(<pre>)(?:()(</pre>)|((?:.(?!</pre>))*.)(</pre>))'
    Ce qui se “traduit” par*: «*On capture la chaîne “<pre>” suivie de soit*:
    ×rien et la balise fermante </pre>, ou…
    ×zéro, un ou plusieurs caractères tant qu’ils ne sont pas suivis par la chaîne “</pre>” (sans oublier de capturer le dit dernier caractère, le petit . final…), suivis de la chaîne “</pre>”.

    À noter que la première partie de la condition est indispensable, sinon la chaîne “<pre></pre>” ne sera pas détectée…

    Le seul truc que cette regex ne sait pas gérer, ce sont les imbrications de balises <pre> –*mais ça, il n’y a que les moteurs de regex supportant la récursivité qui peuvent le faire.

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Merci, mont29, ça manquait effectivement pour faire sauter la contrainte!

    Mais ta 1ère solution (avant correction), plus simple, fonctionnait très bien pour détecter aussi les "<pre></pre>":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ch = """xx$xx$$xx<pre>xx$xx$$xx</pre>xx$xx$$xx<pre></pre>xx$xx$$xx"""
     
    print re.sub(r'(<pre>)((?:.(?!</pre>))*.?)(</pre>)', sub, ch)
     
    xx$xx$$xx<pre>xxYOUPIxxYOUPIYOUPIxx</pre>xx$xx$$xx<pre></pre>xx$xx$$xx
    Sont effectivement trouvées les 2 séquences:
    1ère séquence: <pre>xx$xx$$xx</pre>
    2ème séquence: <pre></pre>

  5. #5
    Membre Expert

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Par défaut
    Oui, mais non*!

    En fait, là ça fonctionne parce que le groupe <pre></pre> est le dernier… Sinon, * et consort étant gloutons, ils “boufferont” tout jusqu’au </pre> suivant (dans “foo <pre></pre> bar <pre> blabla</pre>”, il y aura qu’un seul groupe de trouvé, “</pre> bar <pre> blabla”).

    Du coup, je me dis qu’il y a peut-être plus simple que le look ahead*: les opérateurs non-gloutons*:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    r'(<pre>)(.*?)(</pre>)'
    Pas le temps de tester, par contre…

  6. #6
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    @mont29:

    Effectivement, le motif précédent que je citais ne marchait pas dans tous les cas.

    Ton dernier motif a l'air de fonctionner:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def sub(g):
        print u"séquence trouvée: ", g.group(0)
        return g.group(0).replace('$', 'YOUPI')
     
    ch = """<pre></pre>xx$xx$$xx<pre>xx$xx$$xx</pre>xx$xx$$xx<pre></pre>xx$xx$$xx<pre>xx$xx$$xx</pre>xx$xx$$xx<pre></pre>"""
     
    print re.sub(r'(<pre>)(.*?)(</pre>)', sub, ch)
    Ce qui affiche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    séquence trouvée:  <pre></pre>
    séquence trouvée:  <pre>xx$xx$$xx</pre>
    séquence trouvée:  <pre></pre>
    séquence trouvée:  <pre>xx$xx$$xx</pre>
    séquence trouvée:  <pre></pre>
    <pre></pre>xx$xx$$xx<pre>xxYOUPIxxYOUPIYOUPIxx</pre>xx$xx$$xx<pre></pre>xx$xx$$xx<pre>xxYOUPIxxYOUPIYOUPIxx</pre>xx$xx$$xx<pre></pre>
    Manifestement, toutes les séquences "<pre>...</pre>" sont trouvées, mais je ne comprends pas comment chaque recherche s'arrête à </pre> avec simplement ".*?": tu peux expliquer?


    [Edit] j'ai compris: '.*' (=glouton) s'arrête au dernier "</pre>", et '.*?' (=non glouton) s'arrête au premier "</pre>" qu'il rencontre. Je ne me rappelais plus que '*?' était un élément de motif en soit. Merci!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 20/07/2012, 11h51
  2. Créer Diaporama contenu html sur web pour TV
    Par ant0inep dans le forum Général Conception Web
    Réponses: 0
    Dernier message: 26/10/2011, 11h39
  3. Expression régulière sur un contenu HTML
    Par major68 dans le forum Langage
    Réponses: 2
    Dernier message: 09/07/2009, 23h27
  4. [débutant]travailler sur contenu string
    Par Serge76 dans le forum SL & STL
    Réponses: 13
    Dernier message: 06/11/2004, 16h43
  5. Optimisations mysql sur les requêtes SELECT: index
    Par leo'z dans le forum Débuter
    Réponses: 2
    Dernier message: 29/11/2003, 13h23

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