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 :

parser une page HTML avec re.search()


Sujet :

Python

Vue hybride

Mydriaze parser une page HTML avec... 04/10/2008, 15h47
GnuVince Utilise BeautifulSoup 04/10/2008, 17h18
Mydriaze Bonjour, Merci pour ton... 04/10/2008, 17h32
oiffrig Si tu tiens vraiment à... 05/10/2008, 12h45
Mydriaze D'accord!! MERCI... 05/10/2008, 14h24
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de Mydriaze
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 192
    Par défaut parser une page HTML avec re.search()
    Bonjour à tous,

    Avec urllib, j'arrive à obtenir une page HTML en string.
    Je veux en extraire un passage dont je sais qu'il est compris entre
    </Title> et <tr><td align="right">toto_end</td>


    J'ai fait une fonction qui me ramene la page en string,
    et une autre que voici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    def cherche_passage(page):
        print page
        print type(page)
        passage = re.search('</title>(.*)<tr><td align="right">toto_end</td>', page)
        print passage
        print type(passage)
        passage = passage.group(1)
        print passage
    et là ça ne passe pas.
    ça me print bien la page
    le type c'est bien une string

    Mais le résultat de re.search est "none" alors que mes bornes y figurent bien.
    J'obtiens 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
     
    <html>
      <head>
    ... toute le page
    </html>
    <type 'str'>
    None
    <type 'NoneType'>
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 10, in cherche_synonyme
      File "<stdin>", line 8, in cherche_passage
    AttributeError: 'NoneType' object has no attribute 'group'
    >>>
    Alors que si je teste avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print (re.search('</title>(.*)<tr><td align="right">toto_end</td>', '</title>blabla<tr><td align="right">toto_end</td>').group(1)
    j'ai bien

    Est-ce qu'il y a une solution simple pour palier à ce problème?
    Je pense que c'est un problème de retour à la ligne... Mais comment faire?

    J'ai essayé d'ajouter :

    de chaque côté de la variable page mais ça donne le même résultat...

    J'ai bien trouvé ce que vous avez mis en ligne :

    from HTMLParser import HTMLParser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class MyHTMLParser(HTMLParser):
     
        def handle_starttag(self, tag, attrs):
            print "Encountered the beginning of a %s tag" % tag
     
        def handle_endtag(self, tag):
            print "Encountered the end of a %s tag" % tag
    Mais je n'y comprends rien...
    Je ne sais pas utiliser les classes...


    Je vous remercie d'avance, si vous pouvez me dépanner.

  2. #2
    Membre émérite
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Par défaut
    Utilise BeautifulSoup

  3. #3
    Membre confirmé Avatar de Mydriaze
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 192
    Par défaut
    Bonjour,

    Merci pour ton aide.

    Je ne connais pas Beautifulsoup mais je regarderai! Merci beaucoup!

    Sinon, je viens de trouver une solution differente que voici si ça interesse qqn...

    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
    def cherche_passage(page):
        beginTag = "<h2>"
        endTag   = '<tr><td align="right">toto_end</td>'
        startPos = str(page).find(beginTag)
        while startPos > -1:
            endPos = page.find(endTag,startPos+1)
            if endTag == -1:
                break
            else:
                passage = page[startPos+len(beginTag):endPos]
                passage = re.sub("<br>","\n",passage)
                passage = re.sub ("<[^<>]+>" ,'', passage)
                print "\nTrouvé:",passage
                startPos = page.find(beginTag,endPos+1)
        return passage
    Merci à Sebsauvage.

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Par défaut
    Si tu tiens vraiment à utiliser les expressions régulières (coûteux pour une recherche aussi simple), le problème c'est que le (.*) ne prend pas les caractères de retour à la ligne. Pour contourner ça, il faut que tu compiles ton expression avec le "drapeau" re.DOTALL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    expr = re.compile('</title>(.*)<tr><td align="right">toto_end</td>', re.DOTALL)
    def cherche_passage(page):
        print page
        print type(page)
        passage = expr.search(page)
        print passage
        print type(passage)
        passage = passage.group(1)
        print passage

  5. #5
    Membre confirmé Avatar de Mydriaze
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 192
    Par défaut
    D'accord!!

    MERCI BEAUCOUP!!

    Je vais garder le premier script alors. Mais je note précieusement toutes les infos que vous m'avez données car je ne connaissais pas du tout.

    merci à tous.

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut Faut faire plus simple
    1)
    Dabord le diagnostic.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    search( pattern, string[, flags]) 
    ....Return None if no position in the string matches the pattern;....
    http://www.python.org/doc/2.5.2/lib/node46.html#l2h-400



    passage = re.search('</title>(.*)<tr><td align="right">toto_end</td>', page)
    PAS BON

    passage = re.search('</Title>(.*)<tr><td align="right">toto_end</td>', page)
    MARCHERA, je pense


    Python considère liste_b et Liste_b comme deux choses différentes
    tu te rappelles ?


    Ce n'est pas un problème de retour à la ligne. Avant de chercher des explications exotiques, il faut bien lire le compte rendu d'erreur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <type 'str'>
    None
    <type 'NoneType'>
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 10, in cherche_synonyme
      File "<stdin>", line 8, in cherche_passage
    AttributeError: 'NoneType' object has no attribute 'group'
    <type 'str'> c'est print type(page)
    None à la ligne suivante , c'est print passage
    alors que ce qui est attendu c'est quelque chose comme <_sre.SRE_Match object at 0x0147C2F8> quand il y a le patern, or tu SAIS qu'il y a le patern, donc il faut rester sur cette indication inatendue jusqu'à comprendre le twist.





    2) Tu dis que ta page est dans un string. Je suppose que tu l'obtiens par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    sockhtml = urllib.urlopen(url)
    page = sockhtml.read()
    AMA ce n'est pas une bonne idée d'utiliser read() et de mettre ta page dans un string.
    Je te conseille de lire le message #15 dans la file
    http://www.developpez.net/forums/d59...ine-caractere/

    Je te conseille aussi le message 4 de la file
    http://www.developpez.net/forums/d54...quante-python/

    Je me cite pour ne pas avoir à répéter.






    3) Pour ce qui est de ton problème précisément, je te conseille aussi de lire la file suivante
    http://www.developpez.net/forums/d62...robleme-regex/
    dans laquelle j'ai commis un autre message concernant la problématique regex/or not regex ?

    Comme tu risques de n'y pas aller, je te file le tuyau: regarde la fonction partition() qui agit sur des strings, elle va plus vite que l'utilisation de regex.






    4) En complément de la précédente référence que je te donne, je te signale que j'ai complété le test de vitesse dont il est question dans les messages #6 et #7 de cette file par la comparaison suivante:

    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
    25
    26
    27
    28
    29
    30
    31
    x = "Le vicomte François-René de Chateaubriand est issu d'une très vieille famille aristocratique"
     
    from time import clock
     
    ct = 100000
    t0 = clock()
    print x[x.find('vicomte ')+8:x.find(" est issu d'une")],"    FIND"
    while ct:
        y = x[x.find('vicomte ')+4:x.find(" est issu d'une")]
        ct-=1
    print clock() - t0
     
    print
     
    ct = 100000
    t0 = clock()
    print x.partition('vicomte ')[2].partition(" est issu d'une")[0],"     PARTITION()"
    while ct:
        y = x.partition('vicomte ')[2].partition(" est issu d'une")[0]
        ct-=1
    print clock() - t0
     
    print
     
    ct = 100000
    t0 = clock()
    print x[11:41],"     x[11:41]"
    while ct:
        y = x[11:41]
        ct-=1
    print clock() - t0

    qui montre que l'utilisation de find() est plus longue elle aussi que partition().






    5) Il y a une erreur dans ton code
    Écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            if endPos == -1:
                break
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            if endTag == -1:
                break


    6) Voir aussi message #4 de la file suivante
    http://www.developpez.net/forums/d54...quante-python/





    En résumé, AMA:
    mets ta page en liste par read().splitlines(), utilise les méthodes de string au lieu des regex, utilise partition().

    Avec tout ça, je pense modestement que ton problème devrait devenir très simple.

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

Discussions similaires

  1. Parser une page HTML avec Simple html dom parser
    Par thelover2fr dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 3
    Dernier message: 24/05/2012, 13h26
  2. parser une page html avec perl
    Par fedodido dans le forum Langage
    Réponses: 1
    Dernier message: 16/03/2009, 13h36
  3. Parser une page HTML avec du PHP
    Par Richard_Rahl dans le forum Langage
    Réponses: 9
    Dernier message: 19/08/2008, 15h36
  4. Réponses: 7
    Dernier message: 14/09/2005, 10h50

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