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 :

Aide pour un projet de moteur de recherche interne


Sujet :

Python

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 2
    Par défaut Aide pour un projet de moteur de recherche interne
    Bonjour,

    J'ai un petit projet à effecrtuer en langage python. Ce projet consiste à créer une sorte de moteur de recherche, on rentre un mot à rechercher et le programme renverrai si ce mot existe dans le C: et où il se trouve seulement dans les fichiers .txt .
    Pour ceci, il me faut réussir a lister/à obtenir tout les fichiers .txt existant dans le C: et réussir ensuite à aller chercher les mots à l'intérieur de chaque fichier texte.

    Malheuresement, je n'arrive pas à parcourir ou lister tout les fichiers texte de mon C: .
    J'ai deja essayé avec glob.glob, oswalk, os.listdir mais rien de concluant.

    Si quelqu'un pourrait m'aider à résoudre ce problème, ce serait bien sympa
    Pour ce qui est du reste, j'ai déjà avancé car j'arrive à faire marcher ce programme avec un seul fichier seulement.
    Merci d'avance.

    Bonne soirée

  2. #2
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 309
    Par défaut
    Salut,

    Avec os.walk, tu avais tout ce qu'il fallait pour parcourir ton arborescence.

    Montres-nous comment tu l'utilise, le problème ne peut-être que là.

  3. #3
    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,

    Comme j'avais déjà fait ça pour chercher des mots dans mes sources Python, et que c'est un problème amusant, je propose le petit code (sans prétention) suivant.

    A mon avis, il faut tester chaque entrée dans chaque répertoire séparément, parce que les Windows récents empêchent de rentrer dans certains d'entre eux, et qu'il faut donc gérer ce genre d'erreur.

    En entrée, on a les arguments suivant:

    rep = le répertoire
    mot = le mot à chercher
    select = la liste des motifs à chercher pour les noms de fichier
    sousrep = True si on veut examiner aussi les sous-répertoires
    majusc = True si on veut que les comparaisons soient faites en majuscules

    Bien entendu, si sousrep=True, la recherche est récursive.

    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
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import sys, os
    import fnmatch
     
    ##############################################################################
    def okselect(nf, motifs=["*.txt"]):
        """retourne True si nf satisfait l'un des motifs. False sinon."""
        for motif in motifs:
            if fnmatch.fnmatch(nf, motif):
                return True # on a trouve un motif de selection qui marche
        return False # aucun motif de selection ne marche
     
    ##############################################################################
    def cherchemot(rep, mot="", select=["*.txt"], sousrep=True, majusc=False):
        """Cherche dans rep et ses sous-rep les fichiers qui contiennent le mot"""
     
        if majusc:
            mot = mot.upper()
     
        # lire le contenu du répertoire rep
        try:
            entrees = os.listdir(rep)
        except:
            return [["Erreur: impossible d'entrer dans %s" % rep]]
        listerep = []
        listefic = []
        for entree in entrees:
            if os.path.isdir(os.path.join(rep, entree)):
                listerep.append(entree)
            else:
                if okselect(entree, select):
                    listefic.append(entree)
        listerep.sort()
        listefic.sort()
     
        # cherche les fichiers qui contiennent le mot
        okrep = []
        if mot != "":
            for nf in listefic:
                okfic = []
                nfc = os.path.join(rep, nf)
                f = open(nfc,'r')
                for i, ligne in enumerate(f):
                    if majusc:
                        ligne = ligne.upper()
                    if ligne.find(mot) > 0:
                        if okfic == []:
                            okfic = [nf]
                        okfic.append(i+1)
                f.close()
                if okfic != []:
                    if okrep == []:
                        okrep = [[rep]]
                    okrep[-1].append(okfic)
     
        # traitement récursif des sous-répertoires si c'est demandé
        if sousrep:
            for repert in listerep:
                r = cherchemot(os.path.join(rep, repert), mot, select, sousrep, majusc)
                if r != []:
                    okrep += r
     
        return okrep
    Exemple d'utilisation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    repert = "C:"
    mot = "import"
    select = ["*.py", "*.pyw"]
    sousrep = True
    majusc = True
     
    okreps = cherchemot(repert, mot, select, sousrep, majusc)
    le résultat okreps est une liste de répertoires avec pour chacun d'entre eux la liste des fichiers qui ont le mot avec la liste des numéros de lignes. Bien entendu:

    - seuls les répertoires qui ont au moins un fichier qui va sont mentionnés.

    - seuls les fichiers qui ont le mot au moins 1 fois sont mentionnés

    Voilà comment on affiche le résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for okrep in okreps:
        print
        for okfic in okrep:
            print okfic
    Et voilà un extrait de résultat:

    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
     
    ...
    C:Python27\Lib\xml\parsers
    ['expat.py', 4]
     
    C:Python27\Lib\xml\sax
    ['__init__.py', 22, 23, 24, 37, 38, 39, 56, 59, 82, 83, 85, 99, 100, 105]
    ['_exceptions.py', 4, 129]
    ['expatreader.py', 8, 9, 10, 11, 12, 13, 15, 22, 23, 28, 37, 38, 42, 410]
    ['handler.py', 51]
    ['saxutils.py', 18, 21, 88]
    ['xmlreader.py', 6, 116]
     
    C:Python27\Scripts
    ['apirst2html.py', 22, 37]
    ['epydoc.py', 15]
    ['epydoc.pyw', 15]
    ['f2py.py', 10, 15, 18, 20]
    ['ipcluster.py', 16, 20]
    ['ipcontroller.py', 14, 18]
    ['ipengine.py', 14, 18]
    ['iptest.py', 6]
    ['ipython-wx.py', 9]
    ['ipython_win_post_install.py', 16]
    ['ipythonx.py', 9]
    ['irunner.py', 7]
    ['pywin32_postinstall.py', 69, 70, 89, 90, 104, 130, 131, 138, 167, 176, 189, 223, 248, 250, 251, 252, 259, 266, 285, 286, 313, 465, 468, 469, 475, 574]
    ...
    Erreur: impossible d'entrer dans C:PerfLogs
    ...
    On voit que l'impossibilité d'entrer dans l'un des répertoires est signalée.

    Sur mon C: de 240Go, cette recherche prend 5 minutes, ce qui est tout de même assez rapide.

    Ce code est très simplifié sur les points suivants:

    - il ne tient pas compte des encodages des fichiers: attention donc aux mots contenant des caractères accentués. Mais pour la recherche, il faudrait un "renifleur" d'encodage, car on ne sait pas d'avance si c'est, par exemple, du cp1252 (encodage windows), du cp850 (encodage DOS) ou de l'utf-8.

    - De même la comparaison en majuscule devrait neutraliser ces caractères accentués (j'ai une telle fonction si cela t'intéresse).

    - on pourrait avoir pour la recherche non pas une seul mot, mais une formule avec plusieurs mots reliés par des ET et des OU.

    Sans compter que pour une recherche rapide, il faudrait conserver et mettre à jour en tâche de fond les résultats pour ne pas avoir à tout tester à chaque fois.

    Bref, pour un code complet et "pro", il y a du boulot...

    Tyrtamos

  4. #4
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Bonjour.

    Citation Envoyé par tyrtamos Voir le message
    Il ne tient pas compte des encodages des fichiers: attention donc aux mots contenant des caractères accentués. Mais pour la recherche, il faudrait un "renifleur" d'encodage, car on ne sait pas d'avance si c'est, par exemple, du cp1252 (encodage windows), du cp850 (encodage DOS) ou de l'utf-8.
    Le module chardet propose cela.

    Citation Envoyé par tyrtamos Voir le message
    De même la comparaison en majuscule devrait neutraliser ces caractères accentués...
    Je suis intéressé.

    Citation Envoyé par tyrtamos Voir le message
    On pourrait avoir pour la recherche non pas une seul mot, mais une formule avec plusieurs mots reliés par des ET et des OU.
    Pourquoi pas utiliser les regex avec toute la puissance que cela fournit ?

    Citation Envoyé par tyrtamos Voir le message
    Sans compter que pour une recherche rapide, il faudrait conserver et mettre à jour en tâche de fond les résultats pour ne pas avoir à tout tester à chaque fois.
    Cela pourrait être l'occasion d'utiliser une base de donnée.

    Je ne fais que lancer des idées...

  5. #5
    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 rambc,

    Pour la conversion de chaines quelconques en majuscules non accentuées, voilà la fonction que j'utilise. Attention: il ne faut pas l'utiliser en utf-8 mais soit en latin1 (par exemple), soit en unicode.

    J'ai retenu les accents habituels du français, avec en plus:

    - 'åÅ' qu'on rencontre dans certains noms de pays (les îles d'ÅLAND par exemple)
    - 'ÿŸ' qu'on rencontre dans certains noms propres, y compris noms de villes (L'Haÿ-les-Roses)
    J'ai laissé les 2 caractères liés: 'æ' et 'œ' sans chercher à les séparer.

    Attention: tel qu'écrit, le code laissera passer tel quel un caractère ne faisant pas partie de alpha1. Cela peut être un caractère majuscule non accentué ('A', 'B', ...), mais aussi un caractère étranger au français ('Ž', ' Š', 'ñ', ...), et, bien sûr, n'importe quel caractère non alphabétique ('€', ';', ...). Pour un autre usage, rien n'empêche de générer une exception dans ces cas-là.

    Version unicode:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    def majusc_sans_accent(ch):
        """Convertit la chaine de caractères ch en majuscules non accentuées """
        alpha1 = u"aàÀâÂäÄåÅæbcçÇdeéÉèÈêÊëËfghiîÎïÏjklmnoôÔöÖœpqrstuùÙûÛüÜvwxyÿŸz"
        alpha2 = u"AAAAAAAAAÆBCCCDEEEEEEEEEFGHIIIIIJKLMNOOOOOŒPQRSTUUUUUUUVWXYYYZ"
        x = u""
        for c in ch:
            k = alpha1.find(c)
            if k >= 0:
                x += alpha2[k]
            else:
                x += c
        return x
    Tyrtamos

  6. #6
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Merci.

    Il y a aussi maketrans du module string : http://docs.python.org/library/strin...ring.maketrans .

  7. #7
    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
    Citation Envoyé par rambc Voir le message
    Il y a aussi maketrans du module string : http://docs.python.org/library/strin...ring.maketrans .
    Je préfère mon code, parce que je sais ce qu'il fait, et que je peux le modifier facilement selon mes besoins. Par ailleurs, je travaille le plus souvent en unicode, et j'ai déjà rencontré des pb avec le module string.

    Mais en encodage courant de type '1 caractère=1 octet', ça marche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    import string
     
    alpha1 = u"aàÀâÂäÄåÅæbcçÇdeéÉèÈêÊëËfghiîÎïÏjklmnoôÔöÖœpqrstuùÙûÛüÜvwxyÿŸz".encode('cp1252')
    alpha2 = u"AAAAAAAAAÆBCCCDEEEEEEEEEFGHIIIIIJKLMNOOOOOŒPQRSTUUUUUUUVWXYYYZ".encode('cp1252')
    table=string.maketrans(alpha1, alpha2)
     
    x = u"abcéèçàùôë€ñ".encode('cp1252')
    y = x.translate(table)
     
    print y
    ABCEECAUOEۖ
    Je n'ai pas réussi à faire la même chose en unicode.

    Tyrtamos

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 790
    Par défaut
    Salut,

    Personnellement j'utilise ce que sait faire locale, via:

    locale.strcoll(string1, string2)¶
    Compares two strings according to the current LC_COLLATE setting. As any other compare function, returns a negative, or a positive value, or 0, depending on whether string1 collates before or after string2 or is equal to it.
    LC_COLLATE
    The LC_COLLATE category provides a collation sequence definition for numerous utilities in the XCU specification (sort, uniq, and so forth), regular expression matching (see Regular Expressions ) and the strcoll(), strxfrm(), wcscoll() and wcsxfrm() functions in the XSH specification.

    A collation sequence definition defines the relative order between collating elements (characters and multi-character collating elements) in the locale. This order is expressed in terms of collation values; that is, by assigning each element one or more collation values (also known as collation weights). This does not imply that implementations assign such values, but that ordering of strings using the resultant collation definition in the locale will behave as if such assignment is done and used in the collation process. At least the following capabilities are provided:

    1. Multi-character collating elements. Specification of multi-character collating elements (that is, sequences of two or more characters to be collated as an entity).

    2. User-defined ordering of collating elements. Each collating element is assigned a collation value defining its order in the character (or basic) collation sequence. This ordering is used by regular expressions and pattern matching and, unless collation weights are explicitly specified, also as the collation weight to be used in sorting.

    3. Multiple weights and equivalence classes. Collating elements can be assigned one or more (up to the limit {COLL_WEIGHTS_MAX}) collating weights for use in sorting. The first weight is hereafter referred to as the primary weight.

    4. One-to-Many mapping. A single character is mapped into a string of collating elements.

    5. Equivalence class definition. Two or more collating elements have the same collation value (primary weight).

    6. Ordering by weights. When two strings are compared to determine their relative order, the two strings are first broken up into a series of collating elements; the elements in each successive pair of elements are then compared according to the relative primary weights for the elements. If equal, and more than one weight has been assigned, then the pairs of collating elements are recompared according to the relative subsequent weights, until either a pair of collating elements compare unequal or the weights are exhausted.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 2
    Par défaut
    J'ai essayer notamment en m'aidant du code de tyrtamos et j'ai reussi a résoudre mon problème

    J'ai utilisé la fonction fnmatch pour filtrer les .txt et ensuite os.path.join.

    Maintenant je vais finir ce projet
    Merci de votre aide !
    Bon week end

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

Discussions similaires

  1. Recherche aide pour conception projet
    Par Christophe FRT dans le forum Débuter
    Réponses: 2
    Dernier message: 14/10/2008, 12h10
  2. Je recherche une aide pour un projet en VB 6
    Par nadège31 dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 12/01/2007, 20h42
  3. Besoin d'aide pour un projet
    Par ZiMo dans le forum Linux
    Réponses: 9
    Dernier message: 24/10/2005, 01h28
  4. Besoin d'aide pour un projet de jeu en ligne
    Par FLEO dans le forum Projets
    Réponses: 1
    Dernier message: 21/10/2005, 09h55
  5. [CAML] Recherche aide pour un projet
    Par tarzoon dans le forum Caml
    Réponses: 1
    Dernier message: 02/09/2005, 11h32

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