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 :

récupérer données page html (publique)


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 617
    Par défaut récupérer données page html (publique)
    Bonjour,
    Je suis toujours en train de me familiariser avec le parsing html.
    J'ai deux soucis avec le programme suivant :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    # -*- coding: utf-8 -*-
     
    import requests, bs4#, csv, sys, os
    #from datetime import date as datebis
    #import chardet
     
    url = 'http://www.meteociel.fr/climatologie/climato.php?'
     
    payload = {"mois":5, "annee":2017, "submit":"OK"}
    donnees_tot = "donnees_tot.txt"
    try:
        sess = requests.session()
        r1 = sess.post(url, data=payload)
        soup1 = bs4.BeautifulSoup(r1.text, 'html.parser')
        with open(donnees_tot,"w") as f:
            f.write(r1.text)    
    except:
        pass
     
    elem_tot=[]
    tab1 = soup1.find_all('center')
    for el1 in tab1:
        el2= el1.find_all('center')
        for d in el2:
            date = d.find("h1")
        for el3 in el2:
            el4 = el3.find_all("td")
            for el5 in el4:
                elem_tot.append((el5.text))#.encode("utf-8"))
    tot_villes = len(elem_tot)//6
    elem_group = []
    for i in range(0,tot_villes*6-6,6):
        el = (elem_tot[i:i+6])
        try:
            el = el.replace(" °c","")
        except:
            pass
        elem_group.append(el)
    print(elem_group)
    print(date)
    moy_et_tot=elem_tot[tot_villes*6-6:]
    print(moy_et_tot)
    Le premier problème, c'est que je n'arrive pas à changer le mois et l'année. Il y a un <input value="OK" type="submit"> qui est peut-être en cause ?
    J'ai tenté de mettre des guillemets autour des numéros de mois et d'année, sans succès (car j'ai toujours du mal à savoir si la réponse attendue est un str ou un int).
    Le deuxième problème que je rencontre est que je voudrais récupérer les valeurs numériques et pour cela, je pensais à remplacer le " °c" par "" de façon à passer en float ensuite.
    Mon "replace" reste sans effet.
    J'imagine que tout cela est très basique encore mais bon.
    A bientôt vous lire.

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Dans l'une de tes boucles il suffit de mettre des print pour voir que ça ne fait jamais ce que tu veux !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        for i in range(0,tot_villes*6-6,6):
            el = (elem_tot[i:i+6])
            try:
                el = el.replace(" °c","")
                print("OK")
            except:
                print("ECHEC")
                pass
            elem_group.append(el)
    Et pour cause, pourquoi avoir mis ces try/except ? Ca te masque toutes les erreurs ... Qui plus est l'enchainement
    n'est JAMAIS une bonne idée. A proscrire.

    Au lieu de faire une liste 1D, tu devrais faire des listes de listes. Chaque sous-liste ayant 6 éléments. Et dans ces 6 éléments tu sais précisément lesquels tu dois traiter et comment. Là tu te plantes car elem_tot[i:i+6] est une liste, et que la fonction replace s'applique à une chaine de caractère, donc nécéssairement cet appel crash.


    Pour l'autre problème, suffit de mieux regarder l'URL lorsque tu changes le mois et l'année sur le site ciblé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    http://www.meteociel.fr/climatologie/climato.php?mois=3&annee=2018
    Donc il faut que tu construise l'URL pour qu'elle ait cette forme.

  3. #3
    Membre Expert
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 617
    Par défaut
    Merci beaucoup.
    Cela me paraît tellement évident à te lire.
    Je suis au boulot et je ne peux pas tester mes changements mais cela semble en effet assez simple.
    Juste une remarque : quand tu écris :
    Au lieu de faire une liste 1D, tu devrais faire des listes de listes. Chaque sous-liste ayant 6 éléments.
    c'est bien ce que je fais en principe (sauf erreur de ma part).
    Encore merci, je m'y remets ce soir.

  4. #4
    Membre Expert
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 617
    Par défaut
    J'ai trouvé un ordi pour m'amuser à nouveau.
    Je rencontre un autre problème : j'ai des données qui s'écrivent par exemple "28 mm (30.5j) ".
    Je voudrais accéder aux données numériques. Pas de souci pour enlever "mm" (avec replace).
    Par contre, ce qu'il y a entre parenthèses me pose problème.
    J'ai plusieurs idées :
    - avec startwith
    - avec un test (if "mm" in chaine: ...)
    - avec les regex (que je ne maîtrise pas du tout).
    Une idée de ce qui est le mieux - le plus simple ?

  5. #5
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Non tu fais une liste 1D.

    Car tu aurais une liste 2D (i.e une liste de liste) tu écrirais
    et non
    De même en faisant
    , si tu as une liste 1D, il va apparaitre juste une chaine de caractère. Si tu as une liste de liste, alors ici sera imprimé une liste de 6 éléments.

    Pour traiter la chaine "28 mm (30.5j)", tu peux utiliser la méthode split (pourvu que les espaces soient bien comme tu le présente ici), qui te renverra ["28","mm","(30.5j)"], puis tu prends le 1er élément de cette liste et le tour est joué. Tu peux également le transformé en int à ce moment là selon tes besoins.

  6. #6
    Membre Expert
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 617
    Par défaut
    Merci pour ces réponses.
    Je ne vois pas où j'ai mis des elem[0].
    Pour la liste de liste, c'est ce que je fais. Certes un peu plus tard mais je ne me vois pas le faire avant.
    Pour la méthode split, cela ne me convient pas car cela ne fonctionnera pas pour le premier terme. Si je ne trouve rien de plus simple, je pourrai l'utiliser en excluant ce premier terme.
    Voici où j'en suis, pour fixer les choses.
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    # -*- coding: utf-8 -*-
     
    import requests, bs4#, csv, sys, os
    #from datetime import date as datebis
     
    url0 = 'http://www.meteociel.fr/climatologie/climato.php?mois=mois_reel&annee=annee_reelle'
     
    url=[]
    for an in range(2003,2019,1):
        for m in range(1,13,1):
            url.append(url0.replace("mois_reel",str(m)).replace("annee_reelle",str(an)))
    print(url) 
     
    donnees_tot = "donnees_tot.txt"
    try:
        sess = requests.session()
        r1 = sess.post(url[-8])
        soup1 = bs4.BeautifulSoup(r1.text, 'html.parser')
        with open(donnees_tot,"w") as f:
            f.write(r1.text)    
    except:
        print("pas de connexion")
     
    elem_tot=[]
    tab1 = soup1.find_all('center')
    for el1 in tab1:
        el2= el1.find_all('center')
        for d in el2:
            date = d.find("h1")
        for el3 in el2:
            el4 = el3.find_all("td")
            for el5 in el4:
                el6 = (el5.text).replace(" °c","").replace(" mm","")
                try:
                    elem_tot.append(float(el6))
                except:
                    elem_tot.append(el6)
    tot_villes = len(elem_tot)//6
    elem_group = []
    for i in range(0,tot_villes*6-6,6):
        el = elem_tot[i:i+6]
        elem_group.append(el)
    print(elem_group)
    print(date)
    moy_et_tot=elem_tot[tot_villes*6-6:]
    print(moy_et_tot)
    print(tot_villes)

  7. #7
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Oulala, vous faites une fixette sur la méthode .replace ?

    Une chaine de caractère ca se construit ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    a,b=1,2
    s1='toto%d_tata%d'%(a,b) ### Facon 1
    print(s1)
    s2='toto'+str(a)+'_tata'+str(b)  ### Facon 2
    print(s2)

    Ensuite vous ne parvenez pas à faire une liste 2D dès le début car vous n'utiliser pas la structure du document que vous exploité. Pourquoi ne pas utiliser par exemple ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tab= soup1.find_all('table')[6]
    Il y a 8 tableaux dans la page et c'est le n°6 (les n° allant de 0 à 7) dans lequel est l'information qui vous intéresse. Et là on voit clairement en lisant le code que vous chercher un tableau, et que vous vous intéresser uniquement au n°6. Pas besoin d'itérer sur tous ! Et qui plus est sur des 'center' dont on ne sait pas trop ce que ca renferme ...
    Ensuite les balise <tr>...<\tr> sépare les lignes de votre tableau. Donc rechercher plutot cela !
    Et dans les <tr>, vous pourrez faire un find_all("td"), et là vous aurez précisément la liste des 6 éléments qui vous intéresse.
    Et une fois que vous savez que vous avez 6 éléments et quels sont ils, vous pouvez très bien appliquer un traitement différent à chacun d'eux.

  8. #8
    Membre Expert
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 617
    Par défaut
    Merci.
    Pour la première remarque, c'est ce que j'avais fait au début mais cela plantait car je souhaitais mettre ma variable url0 en dehors de la boucle. Je m'y suis peut-être mal pris.
    Pour la deuxième remarque, j'ai modifié mon programme : c'est plus propre mais j'obtiens le même résultat en gros avec la même méthode. Merci encore.
    Pour la liste 2D, je dois être étanche : je ne vois pas. Cependant, le résultat actuel me convient à peu près.
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    import requests, bs4#, csv, sys, os
    #from datetime import date as datebis
     
    url=[]
    for an in range(2003,2019,1):
        for m in range(1,13,1):
            url0 = 'http://www.meteociel.fr/climatologie/climato.php?mois=%i&annee=%i'%(m,an)
            url.append(url0)
    print(url) 
     
    donnees_tot = "donnees_tot.txt"
    try:
        sess = requests.session()
        r1 = sess.post(url[-8])
        soup1 = bs4.BeautifulSoup(r1.text, 'html.parser')
        with open(donnees_tot,"w") as f:
            f.write(r1.text)    
    except:
        print("pas de connexion")
     
    tab= soup1.find_all('table')[6]
     
    elem_tot=[]
    tab1 = tab.find_all('tr')
    for el1 in tab1:
        el2= el1.find_all('td')
        for el3 in el2:
            elem_tot.append(el3.text)
    #    print(el3)
    print(elem_tot)
    tot_villes = len(elem_tot)//6
    elem_group = []
    for i in range(0,tot_villes*6-6,6):
        el = elem_tot[i:i+6]
        elem_group.append(el)
    print(elem_group)
    #print(date)
    moy_et_tot=elem_tot[tot_villes*6-6:]
    print(moy_et_tot)
    print(tot_villes)

Discussions similaires

  1. [MySQL] Récupérer données page HTML et stocker dans BDD
    Par brizy dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 19/04/2014, 11h25
  2. Réponses: 12
    Dernier message: 13/01/2010, 12h11
  3. Récupérer contenu page HTML
    Par viking1404 dans le forum Réseau
    Réponses: 2
    Dernier message: 16/11/2009, 19h07
  4. [w10]récupérer données page web
    Par minoltis dans le forum WinDev
    Réponses: 2
    Dernier message: 08/02/2007, 13h53
  5. Récupérer infos page html pour les insérer dans Outlook
    Par andromede88 dans le forum Windows
    Réponses: 4
    Dernier message: 21/09/2006, 14h21

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