PARTAGE prévisions nombres d'heures de soleil sur 7 jours Script Python3

Salut,
Je continue sur ma lancée.
Je voudrais récupérer des valeurs sur le site de mon fournisseur d’électricité et le script que j’ai créé me retourne ‹ 0 › comme valeur.

#! /usr/bin/env python3
import requests
from sys import argv
from bs4 import BeautifulSoup
from requests.auth import HTTPBasicAuth
res = requests.get('https://exemple.fr/', auth=HTTPBasicAuth('utilisateur', 'MotDePasse'))
soupe=BeautifulSoup(res.content, "html.parser")
print(soupe.find_all(class_="rouge1")[2].text.strip())

Je cherche à faire remonter les valeurs ci-dessous, une petite aide serait la bienvenue.

Merci

pour de-bug le mieux est que tu ouvre une fenêtre en ssh
puis tu tape python3
>>>
sur le prompt tu rentre les lignes de ton script une a une
pour la dernière tu tape juste

soupe.find_all(class_="rouge1")

comme ça tu vois ce qu’il répond
puis tu adapte

soupe.find_all(class_=« rouge1 »)[0]
soupe.find_all(class_=« rouge1 »)[1]
… etc jusqu’ à tomber sur la bonne info
aprés tu recadre la partie text fonction du résultat.

J’ai suivi scrupuleusement la méthode. J’y suis bien arrivé pour un autre site (ex. météoblue) avec un résultat, mais avec l’exemple ci-dessus je n’y arrive pas.

La valeur retournée = [ ] si je tape la la commande suivante:

>>> soup.find_all(class_ = "rouge1")
[]

Ceci dit la valeur que je recherche à isoler provient d’un tableau sur le site:

J’ai tenté de remonter une autre valeur type texte: « inline-h3 »

mais la commande me renvoie également une valeur nulle

>>> soup.find_all(class_ = "inline-h3")
[]

je sèche…

C’est peut être moi qui t’est mis sur la mauvaise piste en recopiant …
il y a pas de souligner bas …

soup.find_all(class_ = « inline-h3 »)

soup.find_all(class = "inline-h3")

Pas sûr car sans le souligner bas j’ai une erreur et avec ça répond mais la valeur est nulle

image

Bonsoir,

Merci @olive pour ce partage.

Merci également @Bben pour le code de ton scenario. Je m’en suis inspiré.

Je suis en train de faire des tests pour récupérer le suivi de colis sur le site de Mondial Relais (Leur API semblant être réservée aux pros, je tente donc le scraping. Je leur ai posé la question mais je n’ai pas eu de réponse pour le moment).

J’arrive bien à récupérer la date, l’heure et le dernier statut

image

avec le code suivant :

Résumé

Voici le détail du script Python :

#! /usr/bin/env python3
import requests
import urllib.parse
import posixpath
import json
import re
from sys import argv
from bs4 import BeautifulSoup
url_path = posixpath.join("suivi-de-colis/?NumeroExpedition=" + argv[1] + "&CodePostal=" + argv[2])
url = urllib.parse.urljoin("https://www.mondialrelay.fr", url_path)
res = requests.get(url)
soupe=BeautifulSoup(res.content, "html.parser")

data={}
data['date']=soupe.find(class_ = "col-xs-5").text[1:11]
data['heure']=soupe.find(class_ = "step-suivi").text.split()[0]
data['commentaire']=re.search('\n\n\n(.*)\n\n\n',str(soupe.find(class_ = "step-suivi").text.strip())).group(1)

print(json.dumps(data))

Et cela su scenario :

$scenario->setLog('---------------------------------- démarrage Test Python');
$fileURL = "/var/www/html/plugins/script/core/ressources/mondialRelay";

$numeroColis = "52846790";
$codePostal = "16200";

$command = escapeshellcmd($fileURL." ".$numeroColis." ".$codePostal);
$output = shell_exec($command);

$dataJson=json_decode($output,true);

$scenario->setLog('Date : ' . $dataJson['date']);
$scenario->setLog('Date : ' . $dataJson['heure']);
$scenario->setLog('Date : ' . $dataJson['commentaire']);

cmd::byString('#[Colis][Mondial Relay][Date]#')->event($dataJson['date']);
cmd::byString('#[Colis][Mondial Relay][Heure]#')->event($dataJson['heure']);
cmd::byString('#[Colis][Mondial Relay][Commentaire]#')->event($dataJson['commentaire']);

mais je n’arrive pas à récupérer le nom du relais en utlisant :

>>> soupe.find(class_ = "mag")
>>> 

D’après ce que je comprend de la réponse de @ZygOm4t1k dans le post suivant :

cela pourrait venir du fait que cette partie de la page est générée dynamiquement (via du JS dans mon cas et c’était de l’Ajax dans l’exemple ci-dessus). Si on inspecte la page, on trouve bien le nom du relais (voici une URL avec un exemple de colis).

image

En revanche, si on regarde le code source de la page ou qu’on l’enregistre au format HTML, le nom du relais ne se trouve pas dedans.

SuiviMondialRelais.html.txt (63,1 Ko)

Si quelqu’un a une idée, je suis preneur.

Merci.

Salut
faut éplucher res
aprés
res = requests.get(url)

je ferais une écriture de res dans un fichier.txt
puis je regarderais si le nom de ton relay est dedans …

Le nom du relais n’est malheureusement pas dedans.

Les infos du relais semble se faire en Ajax

Le numéro du relais et le code Pays peuvent être récupérés dans la page

soupe.find(id="numeroTemp")["value"]
u'42056'

soupe.find(id="codePaysTemp")["value"]
u'FR'

Ensuite en faisait un post sur l’URL suivante avec les bonnes valeurs

res = requests.post("https://www.mondialrelay.fr/_mvc/fr-FR/Map/SummaryInfosPointsRelais",json={"codePays":"FR","numero":"42056"})

On récupère bien les infos :

"\r\n\r\n        \u003cdiv class=\"row\"\u003e\r\n            \u003clabel class=\"label-center pb15\" for=\"point_42056\"\u003e\r\n                \u003cul\u003e\r\n                    \u003cli\u003e\r\n                        \u003cspan class=\"ico icon-localisation3\"\u003e\u003cspan class=\"path1\"\u003e\u003c/span\u003e\u003cspan class=\"path2\"\u003e\u003c/span\u003e\u003cspan class=\"path3\"\u003e\u003c/span\u003e\u003cspan class=\"path4\"\u003e\u003c/span\u003e\u003c/span\u003e\r\n                        \u003cstrong class=\"mag\"\u003eART\u0026#39;BOUTIQUE (GRANIFLOR)\u003c/strong\u003e\r\n                    \u003c/li\u003e\r\n                    \u003cli\u003e3 GRANDE RUE\u003c/li\u003e\r\n                    \u003cli\u003eFR-16200 JARNAC\u003c/li\u003e\r\n                \u003c/ul\u003e\r\n\r\n            \u003c/label\u003e\r\n        \u003c/div\u003e\r\n"

Reste maintenant à l’extraire mais un soupe.find(class_ = "mag") ne donne rien. Je continue à creuser.

il va te falloir traiter la 2ième requette toi même.

en faite ce sont des ligne on le vois avec les \r\n
il faut le lire une a une puis nettoyer celle qui t’interesse
les \u003c et \u003e sont les < et > des balises je te laisse deviner et inventer la suite

ta balise mag est bien dedans

\u003cstrong class=\"mag\"\u003eART\u0026#39;BOUTIQUE (GRANIFLOR)\u003c/strong\u003e\r\n

se traduit par

<strong class="mag">ART'BOUTIQUE (GRANIFLOR)</strong>

peut être en supprimant tous les \r\n …

Effectivement, voici ce que ca donne.

>>> res2 = res.text.replace("\\u003c","<").replace("\\u003e",">").replace("\\r","").replace("\\n","").replace("\\","")
>>> soupe2=BeautifulSoup(res2, "html.parser")
>>> soupe2.find(class_ ="mag").text
u'ARTu0026#39;BOUTIQUE (GRANIFLOR)'

ta oublier de faire le replace u0026#39; par '

et il risque d’y en avoir d’autre si caractères spéciaux ou accentués …

:+1: bravo tu est bien partit

Oui, il faut que je trouve un moyen pour remplacer tout les caractères spéciaux et accentués possibles. Je vais regarder çà.

EDIT : On peut effectivement faire plus simple en utlisant le codec unicode-escape pour convertir uniquement la partie unicode, réencoder en bytes puis redécoder en utf-8

>>> res2 = res.content.decode('unicode-escape').encode('latin1').decode('utf8')

Ce qui donne :

>>> print(res2)
"

        <div class="row">
            <label class="label-center pb15" for="point_42056">
                <ul>
                    <li>
                        <span class="ico icon-localisation3"><span class="path1"></span><span class="path2"></span><span class="path3"></span><span class="path4"></span></span>
                        <strong class="mag">ART&#39;BOUTIQUE (GRANIFLOR)</strong>
                    </li>
                    <li>3 GRANDE RUE</li>
                    <li>FR-16200 JARNAC</li>
                </ul>

            </label>
        </div>
"

Du coup, on peut parser directement :

>>> soup2 = BeautifulSoup(res2, "html.parser")

Et chercher la classe

>>> soup2.find(class_ ="mag").text
"ART'BOUTIQUE (GRANIFLOR)"

image

bonjour,
j’ai un message d’erreur qui s’affiche depuis quelques jours , c’est général ou juste chez moi ?

Erreur pour [exterieur][Ensoleillement Actuellement][Actuellement] : Erreur sur /var/www/html/plugins/script/data/soupe 0 https://www.meteoblue.com/fr/meteo/semaine/saint-remy_france_2977227 2>&1 valeur retournée : 1. Détails : Traceback (most recent call last): File « /var/www/html/plugins/script/data/soupe », line 7, in print(int(soupe.find_all(class_ = « tab_sun »)[int(argv[1])].text[62:64]), end = ‹  ›) ValueError: invalid literal for int() with base 10: ’ ’

pour moi c’est du chinois !!! si quelqu’un a une idée ca serait super .
merci par avance

J’ai pas encore regarder il est possible que la structure de la page ait changée et que la requette ne corresponde plus … ou si le site est en panne …

le site fonctionne , pas de soucis de ce coté , j’ai vérifié

Idem chez moi :

Erreur sur /var/www/html/plugins/script/data/soupe 0 Météo Lohéac - meteoblue 2>&1 valeur retournée : 1. Détails : Traceback (most recent call last): File « /var/www/html/plugins/script/data/soupe », line 7, in print(int(soupe.find_all(class_ = « tab_sun »)[int(argv[1])].text[62:64]), end = ‹  ›) ValueError: invalid literal for int() with base 10: ’ ’

Salut,
A priori ils ont rajouté un ‹ h › derrière le digit, donc ça foire le cast en integer… [Edit] je dirais plutôt que la quantité d’espace à changé, donc la selection de texte foire pour n’avoir que le nombre [/edit]

dans mon script j’ai ajouter
import re

et remplacer
subData['soleil']=int(soupe.find_all(class_ = "tab_sun")[i].text[62:64].strip())
par
subData['soleil']=int(re.findall(r'\d+',soupe.find_all(class_ = "tab_sun")[i].text[0:200].strip())[0])

…à adapter of course.

Note : d’autre champs sont arrivé hors focus dans les sous selection de texte (.text[x,y]) !

Bonjour,

Si vous avez suivi exactement la doc d’Olive (je suis pas très expert en python :frowning: ), le nouveau script est…

#! /usr/bin/env python3
import requests
import re
from sys import argv
from bs4 import BeautifulSoup
res = requests.get(argv[2])
soupe=BeautifulSoup(res.content, "html.parser")
print(int(re.findall(r'\d+',soupe.find_all(class_ = "tab_sun")[int(argv[1])].text[0:200].strip())[0]), end = '')

Dans mon cas, ça remarche.

Merci,

Laurent.

1 « J'aime »

Merci ça marche mieux :ok_hand:

Bravo @LaurentP il faut juste apprendre a te servir de la balise </> pour mettre du code dans community :wink:
tutoriel cliquez ici

Ou envoyer un message privé à @sheldon-bot démarrer tutoriel avancé pour apprendre à utiliser les menus :wink:

un badge a gagner pour la 2ième option :wink:

ps: j’ai éditer le 1er post avec ce code pour ceux qui ne sont pas adepte de lecture …

2 « J'aime »