filename = input('Saisissez un fichier conll:\n> ')
patterns = input("Saisissez les motifs (séparés par une virgule): ")
# on récupère les patrons saisis et on initialise le dictionnaire
patterns_list = patterns.split(',')
pattern_dico = {}
# on crée une entrée pour chaque patron
for pattern in patterns_list:
pattern_dico[pattern] = []
Nous demandons à l'utilisateur le nom du fichier à traiter et les patrons à extraire. Nous créons un dictionnaire pattern_dico avec chaque patron comme clé et une liste vide comme valeur pour stocker le résultat. La liste patterns_list est également conservée pour la recherche de patrons.
Variables générées : pattern_dico (dictionnaire patron-résultat), patterns_list (liste des patrons saisis)
# on lit le fichier et on sépare les phrases
with open(filename, 'r', encoding = 'utf-8', newline = '\n') as fichier:
contenu = fichier.read()
phrase_liste = contenu.split('\n\n')
phrase_liste.pop()
Nous lisons le contenu du fichier et nous le séparons en phrase. Dans un fichier conll, les phrases sont séparées avec une suite de deux sauts de ligne. Par contre il y a aussi un double sauts de ligne à la fin du fichier, il faut donc l'enlever pour pas qu'il gêne les traitements suivants. A l'issu de cette étape, nous avons une liste des phrases.
Variables générées : phrase_liste (liste de phrases)
# on traite toujours phrase par phrase
for phrase in phrase_liste:
lignes = phrase.split('\n')
# on filtre les commentaires
mots = list(filter(lambda x: x and x.startswith("#") is False, lignes))
# on initialise les listes tokens et tags
tokens = []
tags = []
# on analyse chaque ligne de tableau et on met à jour les listes
for mot in mots:
champs = mot.split('\t')
tokens.append(champs[1])
tags.append(champs[3])
# on transforme la liste tags en une chaîne de caractères
tags_str = " ".join(tags)
# pour chaque patron enregistré dans patterns_list
for pattern in patterns_list:
# si on trouve une suite identique au patron
if pattern in tags_str:
# on calcule la longueur du patron
num = len(pattern.split(" "))
# on génère les listes de n-gram token (n_grams) et tag (n_pos) en fonction de la longueur du patron
n_grams = []
n_pos = []
for i in range(0, len(tags) - num + 1):
n_grams.append(" ".join(tokens[i:i+num]))
n_pos.append(" ".join(tags[i:i+num]))
# on initialise un compteur comme ancre de recherche
start_i = 0
while True:
try:
# on récupère l'index du patron dans n_pos et on prend le n-gram correspondant dans n_grams
pos_i = n_pos.index(pattern, start_i)
pattern_dico[pattern].append(n_grams[pos_i])
start_i = pos_i + 2
except:
break
Nous traitons phrase par phrase. D'abord nous filtrons les commentaires, les lignes vides et les phrases n'ayant qu'un seul token, puis nous extrayons la liste de tokens et de POS tags, appelées tokens et tags.
Les tags sont ensuite transformés en une chaîne de caractère tags_str. Pour chaque patron cherché, nous regardons s'il existe dans tags_str. Si oui, nous calculons la longueur du patron num et nous générons deux listes de num-gram, l'une des tokens n_grams et l'autre de tags n_pos. Nous cherchons le patron dans n_pos, nous récupérons son index et nous sortons le n-gram correspondant dans n_grams qui est enregistré dans pattern_dico.
# on écrit le résultat dans le fichier de sortie
with open('sortie_non_trie.txt', 'w', encoding = 'utf-8', newline = '\n') as sortie:
for pattern, patrons in pattern_dico.items():
tmp = list(map(lambda x: sortie.write(x + '\n'), patrons))
sortie.write('\n\n')
Dernière étape, nous écrivons le contenu du pattern_dico dans les fichiers de sortie. Nous commençons par la sortie non triée en parcourant pattern_dico directement et en écrivant toutes les valeurs.
# on initialise le compteur
# à noter qu'il compte le nombre total des patrons trouvés, sans distinction entre les patterns
countresult = 0
# pour chaque entrée dans patrons_dico
for pattern, patrons in pattern_dico.items():
# on inisitalise un dictionnaire temporaire
tmp = {}
for patron in patrons:
# on compte le nombre d'occurrences de chaque patron
try:
tmp[patron] += 1
except KeyError:
tmp[patron] = 1
# on trie les entrées
tmplist = sorted(tmp.items(), key=lambda x: x[1], reverse=True)
# on met à jour le compteur
countresult += len(patrons)
# on met à jour le dictionnaire
pattern_dico[pattern] = tmplist
with open('sortie_trie.txt', 'w', encoding = 'utf-8', newline = '\n') as sortie:
sortie.write('{} éléments trouvés\n'.format(countresult))
for pattern, patrons in pattern_dico.items():
sortie.write("Type de pattern: {}\n".format(pattern))
tmp = list(map(lambda x: sortie.write(x + '\n'), patrons))
sortie.write('\n\n')
Ensuite nous écrivons le contenu trié dans une autre sortie. Il s'agit de la même procédure que dans BAO3_1. Nous pouvons également paramétrer le format d'écriture pour qu'il ne garde que les informations qui nous intéressent.