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éécrire sur un fichier txt de zéro dans une boucle temporel [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Février 2024
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Février 2024
    Messages : 6
    Par défaut Réécrire sur un fichier txt de zéro dans une boucle temporel
    Bonjour à tous,

    Tout d'abord je précise, je ne suis pas un expert python ça va faire un mois que je le pratique.
    Avant de poster ce programme, j'ai fait de multiple recherche, mais je n'ai rien trouver sur le sujet.

    Je vous expose mon objectif :

    Scrapper des informations d'une seul page, tout les x temps car les données évolues régulièrement dessus, tout cela dans une certaine plage horaire.
    Les données doivent être enregistrées à chaque tour de boucle sur le même fichier au format txt.
    Se fichier doit être écrasé à chaque tour de boucle, je ne veux pas que les données soient écrit à la suite sur le fichier.

    Maintenant j'expose mon problème:

    Aucun soucis pour l'ensemble de la programmation, que ce soit la plage horaire, la boucle temporel, le scrapping.
    Mon soucis, est que l'écriture du fichier ne repart pas d'une page blanche à chaque boucle temporel
    Pourtant afin d'être sur, j'ai mis une fonction pour supprimer le fichier avant l'ouverture de celui-ci dans la boucle, je vérifie bien que le fichier est bien fermer à chaque boucle.
    Et j'utilise bien la fonction 'w' pour ouvrir le fichier.
    Rien n'y fait, a chaque boucle temporel, le scrapping se cumul au précédent lorsqu'il est écrit sur le fichier txt
    Comme si il gardait en mémoire tampon le précédent scrapping.

    Merci d'avance pour toute aide que vous pourriez m'apporter

    Si besoin de la totalité du code n'hésitez pas a demander.
    Voici la partie de mon programme qui ne doit pas marcher correctement:

    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
        if egal_mlsec >= 0.5 :
            connection = 0
            print('mlsec_bis : ',egal_mlsec)
            proxies_rand = choice(proxies)
            browser_headers_rand = browser_headers[choice(mylist)]
            proxies_rand = {"http": proxies_rand}
            print('Proxies : ',proxies_rand)
            try:
                response = requests.get(url, headers=browser_headers_rand, proxies=proxies_rand, timeout=timeout)
                if response.ok :
                    connection = 1
            except Exception:
                print(f"Proxy {proxies_rand} failed, trying another one")
     
            if connection == 1 :
                soup = BeautifulSoup(response.text, 'html.parser')
                tds = soup.find_all('td')
     
                if os.path.exists('scraping.txt'):                                                   #suppression du fichier txt
                    os.remove('scraping.txt')
                if not os.path.exists('scraping.txt'):                                              #vérification que le fichier est bien supprimée
                    print('fichier supprimé')
     
                fichier = open('scraping.txt', 'w', encoding = 'utf-8')                         #Création du fichier txt
     
                for td in tds:                                                                      
                    links.append(td.text)                                                           
     
                #Création du fichicher de scraping
     
                with fichier as file:
                    for annonce in links:
                        annonce = annonce.replace(',','.')                                             
                        file.write(annonce + ';')                                                        #écriture du fichier txt                                                       
                    if file.closed == False:
                        fichier.close()
                        print('Fichier fermé = ', file.closed)                                         #Fermeture du fichier txt
     
            Nowdate = Nowdate_bis

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Février 2024
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Février 2024
    Messages : 6
    Par défaut
    Finalement je viens de comprendre où était le problème après avoir penché dessus plus d'une journée...
    C'est en écrivant le précédent message que j'ai compris.

    link =[] était tout simplement en dehors de ma boucle temporel, et donc ne se réinitialisais pas.

    Le sujet peux être supprimé ou marqué comme résolue.

    Désolé pour la gène occasionnée.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Zemoda Voir le message
    Désolé pour la gène occasionnée.
    Pas grave, ça peut aider.
    En revanche ton code a quelques maladresses
    • connection=1 => si ça doit être un flag vrai/faux (ce qui semble être le cas) alors True/False. Maintenant étant donné que tu as déjà l'info dans response.ok rajouter la même info dans une seconde variable...
    • Code python : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      if os.path.exists('scraping.txt'):                                                   #suppression du fichier txt
      	os.remove('scraping.txt')
      if not os.path.exists('scraping.txt'):                                              #vérification que le fichier est bien supprimée
      	print('fichier supprimé')
      Mouais. Et s'il n'existait pas au préalable ? Le programme affichera "fichier supprimé" ce qui n'est pas vraiment la vérité vraie. Quant à "vérifier" que cela a bien été effectué c'est Python qui s'en charge (si la suppression échoue ça lève une exception)
      pathlib.Path("scraping.txt").unlink(missing_ok=True) et tu n'as pas à gérer s'il existait ou pas au préalable ; ou ...unlink(missing_ok=False) et là tu gères via l'exception. Et dans tous les cas, si "scrapping.txt" existe mais sous une autre forme (dossier par exemple) là ça cafouille méchamment (à toi de voir si ça vaut le coup de gérer le cas => Formule mathématique)
    • with fichier as file alors là c'est intéressant car je ne l'avais jamais vu. Toutefois vu que tu fermes manuellement le fichier, tu ne sembles pas avoir perçu le but du gestionnaire de contexte with car justement son rôle est de s'assurer que les ressources demandées sont libérées quand on le quitte. Ici il s'agit d'un fichier donc le fichier est automatiquement fermé. Donc soit tu l'utilises et tu ne t'occupes pas de la fermeture, soit tu veux gérer explicitement la fermeture (ce n'est pas interdit) et dans ce cas, pas besoin de with.
      Et si tu veux l'utiliser, tu peux alors appeler directement with open(...) as file
    • if file.closed == False: non, ça jamais. On ne compare pas avec False, c'est un non sens logique. A la limite on peut comparer avec True éventuellement mais le souci c'est que beaucoup d'expressions sont considérées comme True (ou False) sans l'être réellement.
      Code python : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      >>> toto=123
      >>> print("ok" if toto == True else "bad")
      bad
      On peut évidemment transformer l'expression en booléen avant de la comparer...
      Code python : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      >>> toto=123
      >>> print("ok" if bool(toto) == True else "bad")
      ok
      ... mais le plus simple est de laisser Python s'en charger.
      Code python : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      >>> toto=123
      >>> print("ok" if toto else "bad")		# if not toto pour inverser le test...
      ok
    • et vaut mieux link = list() plutôt que link = []. Ce n'est pas interdit évidemment mais on conseille généralement d'écrire les choses de façon explicite


    Citation Envoyé par Zemoda Voir le message
    Désolé pour la gène occasionnée.
    Bah, tu vois que finalement ça n'a pas été si inutile...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 323
    Par défaut
    bonjour
    Citation Envoyé par Sve@r Voir le message
    [*]et vaut mieux link = list() plutôt que link = []. Ce n'est pas interdit évidemment mais on conseille généralement d'écrire les choses de façon explicite[/list]
    Pour info, mon linter n'est pas d'accord et donne la raison (vitesse)

  5. #5
    Membre Expert
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    923
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 923
    Billets dans le blog
    8
    Par défaut
    Bonjour,
    Citation Envoyé par papajoker Voir le message
    bonjour

    Pour info, mon linter n'est pas d'accord et donne la raison (vitesse)
    Dans le cas présent, il s'agit d'une liste et non pas d'un dictionnaire. De plus Se@r, initialise liste une vide...
    Ceci étant dit , je ne pense pas qu'il soit préférable d'écrire liste = list() à [] ou vice versa . En tous cas la PEP ne semble pas l'évoquer

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par MPython Alaplancha Voir le message
    Dans le cas présent, il s'agit d'une liste et non pas d'un dictionnaire.
    celle là même moi j'aurais pas osé...
    Un exemple montré avec dict pourra être répercuté sur list sans trop changer la donne.
    De fait...
    • python3 -m timeit "[]" => 20000000 loops, best of 5: 20.4 nsec per loop
    • python3 -m timeit "list()" => 5000000 loops, best of 5: 45.6 nsec per loop

    Et là je suis forcé de constater que...

    Citation Envoyé par MPython Alaplancha Voir le message
    En tous cas la PEP ne semble pas l'évoquer
    Pep 20: Explicit is better than implicit.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Citation Envoyé par MPython Apalancha
    Dans le cas présent, il s'agit d'une liste et non pas d'un dictionnaire. De plus Se@r, initialise liste une vide...
    Seulement si on lit jusqu'au bout le document proposé par @papajoker, on est amené vers un lien analysant l'ensemble des initialisations et ajout de valeurs sur tous les types python.

    Citation Envoyé par Sve@r
    Explicit is better than implicit.
    Explicit is better than implicit est une histoire d'interprétation, en ce qui me concerne [] est suffisamment explicite sur ce que ça représente.

    Citation Envoyé par Zemoda
    Si vous avez d'autre idée d'amélioration je suis preneur.
    Il y a déjà les informations données par Sve@r, mais faudrait quand même donner l'ensemble du code pour en dire plus...

  8. #8
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 323
    Par défaut
    1) list ne sert strictement à rien ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    soup = BeautifulSoup(response.text, 'html.parser')
    for annonce in soup.find_all('td'):
        annonce = annonce.text
    ou, (si tu comprends)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    soup = BeautifulSoup(response.text, 'html.parser')
    for annonce in (td.text for td in soup.find_all('td')):
        ...
    2) tes annonce.replace
    Si pas possible d'utiliser une regex, alors créer un function type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def filter(annonce):
       for match in  ("(jan)" ... "(dec)"):  annonce.replace(match
    ...
    file.write(filter(annonce) + ';')
    3) pourquoi refaire la confif proxi/entete dans la boucle

    4) pas compris ta demande générale (ta boucle)
    ? récupérer la même url toutes les 0.5 secondes et écraser/sauver le résultat dans toujours le même fichier
    A la limite, si ce script est un service (a la place des boucles python existe des cron). Mais alors je suppose qu'un autre service doit lire en temps réel ? Et il a de grandes chances de lire un fichier corrompu puisqu'en cours d'écriture.

    Si j'ai bien compris, alors c'est une boucle du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def download(connexion_config):
        print("requests.get ...")
        time.sleep(0.4)
     
    connexion_conf = "browser_headers + proxi + ..."
     
    start = datetime.now()
    end = start + timedelta(hours=1)
    while datetime.now() < end:
        start_dl = time.time()
        if download(connexion_conf) < 0 : break
        time.sleep(0.5 - (time.time() - start_dl))

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Février 2024
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Février 2024
    Messages : 6
    Par défaut
    Bonsoir,

    Merci pour ses généreuse informations.

    Grace à vous, j'ai bien compris que je pourrais optimiser mes replaces, je le ferais plus tard quand j'aurais l'ensemble des éléments a remplacer d'ici quelque mois.
    Le code est voué a évoluer de se coté là régulièrement.

    Pour répondre à ta question n°4 papajoker les proxy et headers change à chaque boucle.

    Je ne veux pas qu'il y ai de time.sleep car cela fige tout le code, les 0.5 seconde pourrais être réduit dans le future.

    Je ne rencontre aucun problème de lecture avec mon autre programme et je n'ai malheureusement aucune compétence en Cron déjà je me débrouille comme je peux avec mes 1 mois de python .

    Par contre j'ai pas trop compris ton 1) ou ton 2).

    Voici mon code complet (sauf l'http) les horaires ne sont pas encore figé vu que je travail encore sur le code:

    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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    import time
    from datetime import timedelta
    import keyboard
    import yaml
    import requests
    from random import choice
    from bs4 import BeautifulSoup
    import os
     
    #url site à scraper
    url = "https://"
     
    #Programation de la temporalité pour la boucle
    Nowdate = time.time()
    Now = time.localtime()
    Heure = Now.tm_hour
    Min = Now.tm_min
    Sec = Now.tm_sec
    print(time.strftime("%Y-%m-%d %H:%M:%S %Z", Now))
    start = 0
     
    #Programation horaire :
    Heure_début = 10
    Minute_début = 15
    Heure_fin = 23
    Minute_fin = 5
     
    #Progamation attente réponse serveur scraping
    timeout = 0.45
     
    #Ouverture et lecture des proxy
    proxies = [word.strip() for word in open("proxy_liste.txt", encoding="utf-8")]
     
    #Changement headers pour se faire passer pour une recherche sur un explorer :
    with open("headers.yml") as f_headers:
        browser_headers = yaml.safe_load(f_headers)
        mylist = ["Firefox","Chrome","Edge","IE","Brave"]
     
    #Boucle temporelle
    while (Heure == Heure_début and Min >= Minute_début) or Heure > Heure_début:
        Nowdate_bis = time.time()
        Now_bis = time.localtime()
        Heure_bis = Now_bis.tm_hour
        Min_bis = Now_bis.tm_min
     
        egal_mlsec = Nowdate_bis - Nowdate
     
        if start == 0 and ((Heure_bis == Heure_fin and Min_bis <= Minute_fin ) or Heure_bis < Heure_fin):
            print('start')
            print('egal_mlsec : ',egal_mlsec)
            start = 1
        if egal_mlsec >= 0.5 :
            print('mlsec_bis : ',egal_mlsec)
            proxies_rand = choice(proxies)
            browser_headers_rand = browser_headers[choice(mylist)]
            proxies_rand = {"http": proxies_rand}
            print('Proxies : ',proxies_rand)
            try:
                response = requests.get(url, headers=browser_headers_rand, proxies=proxies_rand, timeout=timeout)
                if response.ok :
                    soup = BeautifulSoup(response.text, 'html.parser')
                    tds = soup.find_all('td')
                    links =[]
     
                    links=list(td.text for td in tds)
     
                    with open('scraping.txt', 'w', encoding = 'utf-8') as file:
                        for annonce in links:
                            annonce = annonce.replace(',','.')
                            annonce = annonce.replace(' (Jan.)','')
                            annonce = annonce.replace(' (Févr.)','')
                            file.write(annonce + ';')
            except Exception:
                print(f"Proxy {proxies_rand} failed, trying another one")
     
            Nowdate = Nowdate_bis
     
        if (Heure_bis == Heure_fin and Min_bis >= Minute_fin ) or Heure_bis > Heure_fin:
            print('stop')
            break
        if keyboard.is_pressed("ctrl + 9"):
            print("stop by pressing ctrl + 9")
            break

  10. #10
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    @zemoda

    Est-il nécessaire de recalculer l'heure actuelle à chaque itération de la boucle ?

    Les lignes suivantes vérifient l'heure à chaque itération de la boucle, ce qui peut être inefficace :

    Citation Envoyé par zemoda
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Nowdate_bis = time.time()
    Now_bis = time.localtime()
    Heure_bis = Now_bis.tm_hour
    Min_bis = Now_bis.tm_min
    Au lieu de recalculer l'heure et la date à chaque itération, nous pouvons vérifier moins fréquemment l'heure ou utiliser une logique conditionnelle qui diminue la nécessité de vérifications constantes. Voici une proposition simplifiée qui minimise les vérifications...

    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
    def est_dans_la_periode_cible(heure, minute, heure_debut, minute_debut, heure_fin, minute_fin):
        debut = heure_debut * 60 + minute_debut
        fin = heure_fin * 60 + minute_fin
        maintenant = heure * 60 + minute
        return debut <= maintenant <= fin
     
    while True:
        maintenant = time.localtime()
        heure_actuelle, minute_actuelle = maintenant.tm_hour, maintenant.tm_min
     
            # Vérifie si on est toujours dans la période désirée avant de continuer
            if not est_dans_la_periode_cible(heure_actuelle, minute_actuelle, Heure_début, Minute_début, Heure_fin, Minute_fin):
                print("Hors de la période cible, arrêt du script.")
                break
     
        # Ici, placez la logique de votre script qui s'exécute à chaque période valide
        # Attendre avant la prochaine vérification pour réduire la charge
     
        time.sleep(periode_verification)
    Je passe les proxy et les headers, je n'ai pas compris pourquoi on avait une partie aléatoire... plutôt que les définir avant la boucle.

    Citation Envoyé par zemoda
    if egal_mlsec >= 0.5 :
    Pourquoi ne pas éviter cette condition en plaçant un time.sleep(0.5) à la fin de ta boucle ?

    Après on pourrait améliorer le code aussi à coup de try-except concernant les exceptions (timeout, ConnectionError, ...)

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

Discussions similaires

  1. Donnée de fichier txt sans séparateur dans une bd sqlite
    Par Kriskev dans le forum Général Java
    Réponses: 6
    Dernier message: 17/11/2016, 20h33
  2. Réponses: 2
    Dernier message: 11/08/2008, 10h00
  3. Réponses: 8
    Dernier message: 20/09/2007, 18h58
  4. Ecriture sur un fichier.txt dans tomcat
    Par xsafary dans le forum Java ME
    Réponses: 1
    Dernier message: 21/05/2007, 08h39
  5. Réponses: 8
    Dernier message: 08/03/2007, 16h54

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