Cette page se propose d'expliquer en détails quelques aspects du paramétrage d'un COLD et d'un modèle d'analyse COLD. ====== Centre d'apprentissage ====== Le centre d'apprentissage est l'interface qui vous permet de paramétrer un modèle d'analyse COLD. ===== Filtre de champ ===== Le filtre de champ permet de spécifier un motif à rechercher dans la page au moyen d'une expression régulière. Exemple : Votre Cold porte sur l'indexation de factures clients. Chaque facture comporte une ligne "Numéro client : xxxxxx". Plutôt qu'indiquer une position absolue on préfèrera rechercher le motif "Numéro client : " En expression régulière cela se traduit par "Numéro client : \d*" (/!\ sans les doubles quotes, ou guillements en français) Afin de tirer parti des expressions régulières, qui sont un outil fondamental pour l'analyse de documents, nous vous recommandons vivement de vous familiariser avec leurs notions et syntaxes. Vous pouvez consulter la [[http://fr.wikipedia.org/wiki/Expression_rationnelle|page wikipedia sur les expressions régulières]] ou encore celle-ci [[http://docs.python.org/2/library/re.html| Module python pour les expressions régulières]] sachant que c'est ce module qui traitera vos expressions régulières. ===== Les macros ===== Ce que nous appelons macro sont simplement des fonctions spécifiques à EzGED ==== Macros de formatage ==== Ces macros sont utilisables dans le champ **post formatage** **@self** fait référence à la valeur du champ.\\ **@** fait référence à une variable (nommée arbitrairement x) capturée dans l'expression régulière du filtre de champ. ^ Macro ^Description ^Exemple ^ |@caststr(@) | Convertit en chaîne de caractères la variable | | |@concat('@sep:',@,@,...)| Concatène, avec un séparateur si précisé, les valeurs de chaque groupe capturé | @concat("@sep:-",@,@,@)| |@concatdate('@sep:',@,@,...)| Idem que la macro concat mais applique à sa sortie la macro Smartdate | @concatdate("@sep:-",@,@,@)| |@getinlist('table','champ_recherche','champ_retour') | cherche dans //table// l'enregistrement pour lequel le champ //champ_recherche// a pour valeur celle trouvée par l'analyse et retourne la valeur du champ //champ_retour// | |@getinlist('table','champ_recherche','champ_retour') | | |@getfromdatasource(2,'table','champ_recherche','champ_retour') | | |@int2month() | Convertit un mois sous forme numérique en sa représentation littérale| @int2month(3) ou @int2month("03") = "mars"| |@int2day() | Convertit un jour sous forme numérique en sa représentation littérale| @int2day(3) ou @int2day("03") = "mercredi"| |@keepdigits(@self)| Ne conserve que les caractères numériques. | | |@monthint(@self) | Convertit un mois sous forme littérale en sa représentation numérique | février deviendra 2| |@Smartdate(@self) | Convertit la chaîne de caractères trouvée en date valide (si possible). | | |@Smartfloat(@self) | Convertit la chaîne de caractères trouvée en flottant. | | === @concat (depuis la révision 4244) === Pour préciser un séparateur ( i.e une chaine de caractères à insérer entre chaque valeur ) il faut que le premier argument de la macro soit **'@sep:////'** où est à remplacer par le caractère (ou la chaine de caractères) de votre choix. En dehors des variables (exemple : **@** ) tous les paramètres de la macro doivent être entourés de guillemets simples. Les guillements simples sont donc à proscrire en dehors de cet usage. Exemple de concaténation d'une capture ( stockée dans la variable numero ) sans séparateur : @concat('N° ',@) Exemple de concaténation avec séparateur. Nous choisirons ici le tiret : @concat('@sep:-',@,@,@) => exemple : 63-54-108 ==== Recherche par SIREN ==== La macro **@society** cherche dans le document à analyser un numéro de SIREN et retourne le nom de la société correspondante. Pour bien comprendre les résultats retournés par @society, voici comment procède la macro : - Elle interroge tout d'abord votre base données en lançant une requête sur la table societycache. Si un résultat est trouvé elle le retourne. - Si elle interroge notre base de données et retourne le résultat si trouvé. - En dernier recours elle effectue une interrogation sur différents moteurs de recherches et analyse le flux de résultats. - Enfin, si aucun résultat n'est trouvé à la suite des étapes 1,2 et 3 elle retournera la valeur "Inconnu". **/!\ MAJ revision 4111** si @society ne parvenant pas à joindre le serveur il ne renvoie pas //Inconnu// et donc l'analyse bloquera si le champ est obligatoire. Cette maj fait suite à ce bug : http://mantis.ezdev.fr/view.php?id=439 ==== Recherche par Numéro de TVA ==== La macro **@societyeu** cherche dans le document à analyser un numéro de TVA Intracommunautaire et retourne le nom de la société correspondante. ATTENTION !cette macro n'est pas disponible en version ONE. Pour bien comprendre les résultats retournés par @societyeu, voici comment procède la macro : La macro cherche par ordre de préférence les numéro de TVA dans cet ordre par défaut, "FR,BE,IT,GB,LU,DK,EL,IE,NL,AT,PT,FI,SE,HU,PL,CY,CZ,EE,LV,SI,RO,DE,ES,SK,BG,HR,MT,LT" puis interroge un web service de la base européenne : Pour l'instant les bases des pays suivants ne sont pas interrogeables : DE,ES,SK,BG,HR,MT,LT c'est pour cela qu'ils sont en dernier dans l'ordre de recherche par défaut, toutefois vous pouvez utiliser la base de cache pour les faire fonctionner, pour cela modifier le champs societycache_code en Varchar de 20. Vous pouvez changer l'ordre de recherche ou le limiter à certains pays uniquement en ajoutant la variable suivante dans instance.conf exemple ici limitation aux pays limitrophes à la France avec francophones de préférence + Angleterre et Irlande: [ezged] mytvacountries = FR,BE,LU,IT,GB,IE,DE,ES Vous pouvez également renseigner la variable suivante pour ignorer votre ou vos numéros de TVA mytvaeu = FR72515180115, BE1234567890 ===== Fonctions avancées ===== Vous disposez d'une possibilité très intéressante, celle d'utiliser des fonctions pythons dans la zone de texte "Fonctions avancées sur le champ". Toute fonction python n'est pas utilisable et vous serez principalement intéressés par celles s'appliquant aux chaînes de caractères. ==== Manipulations de chaînes de caractères ==== === Remplacement === str**.replace**//(ancien,nouveau)// : remplace dans la chaîne identifiée par //str// toutes les occurrences de //ancien// par //nouveau//. Exemple : "Ceci est un fruit".replace("fruit","légume") affichera "Ceci est un légume" Exemple dans EzGED : Nous avons un champ de recherche appelé //RECHERCHE_nom// dont le numéro est 7 et contenant un nom. Comme vous le savez déjà nous pouvons récupérer cette valeur par //@FLD42//. Imaginons que notre champ //RECHERCHE_nom// contienne la valeur **Dupont** après recherche du nom dans le document. Pas de chance, sur l'ensemble de nos documents nous avons confondu Dupont et Dupond. Nous voudrions néanmoins que le document soit indexé avec le nom correct. Voici comment faire : @FLD3.replace("t","d") === Remplacement + expression régulière === On peut utilisation la fonction **re.sub**(expr,nouveau,chaine) === Découpage === str**.split**//(séparateur)// : retourne une liste des mots contenus dans //str//. Le découpage des mots s'effectue en fonction du paramètre //séparateur//. S'il n'est pas spécifié le séparateur sera l'espace. Exemple : "tomate,poivron,courgette".split(",") retourne la liste ["tomate","poivron","courgette"]. Exemple dans EzGED : Le champ de recherche numéro 3 se voit affecter lors de l'analyse le nom du fichier qui est "747_reservation_sydney.pdf" (sans les ") Pour retrouver le numéro de réservation avec la fonction split c'est très simple : @FLD3.split("_")[0] Ce qui nous retourne **747**. Vous remarquerez ici que nous avons fait suivre l'appel de la fonction par //[0]//. Pour comprendre de quoi il s'agit voir la section sur les indices. ==== Découpage / Slicing ==== En python les indices sont notamment utilisés pour les listes et les chaînes de caractères, ces dernières pouvant être vues comme des listes de caractères. Un indice permet de se positionner dans une liste. Il est important de noter qu'en python (comme dans la plupart des langages informatiques) la numérotation des indices débute à 0. Le premier élément d'une liste aura donc pour indice 0. Exemple : chiffres = ["un","deux","trois"] print chiffres[1] Ceci affichera **deux** puisqu'il s'agit de la valeur de l'élément de la liste en position 1. Nous comprenons maintenant l'exemple vu un peu plus haut avec notre champ contenant la valeur **747_reservation_sydney.pdf** @FLD3.split("_")[0] Tout d'abord la fonction **.split** va retourner la liste ["747","reservation","sydney.pdf"] puis avec //[0]// nous indiquons à Python que nous souhaitons récupérer le premier élément (position 0) de cette liste. === Indices négatifs === Voilà une fonctionnalité extrêmement pratique que nous offre python. Reprenons l'exemple précédent. Nous avons notre liste résultat du split sur le nom de fichier. >>> liste = "747_reservation_sydney.pdf".split("_") >>> ["747","reservation","sydney.pdf"] Supposons que vous souhaitiez récupérer le dernier élément de cette liste. Vous pourriez faire ceci : >>> liste[2] >>> 'sydney.pdf' Mais imaginez que la taille de cette liste ne soit pas connue. Vous savez que le nom de la ville est en dernière position dans le nom du fichier (juste avant l'extension) mais il se peut que d'autres chaînes de caractères s’intercalent entre le mot //reservation// et le nom de la ville. En python néanmoins le problème se résout facilement comme ceci : >>> liste[-1] >>> 'sydney.pdf' On indique que l'on souhaite récupérer l'élément en première position à partir de la fin de la liste, c'est-à-dire le dernier élément. === Extractions === Ce que nous avons vu sur les indices jusqu'ici, et ce que nous savons des listes et des chaînes de caractères, va nous permettre de réaliser des extractions au sein, par exemple, d'une chaîne de caractère. Prenons la chaîne de caractère suivante : >>> s = "un_nom_de_fichier_quelconque.pdf" Nous souhaitons extraire le nom du fichier sans son extension. Évidemment la longueur du nom n'est pas connue à l'avance. Nous allons donc extraire les caractères depuis le début de la chaîne (position 0) jusqu'à 4 caractères avant la fin. >>> s[0:-4] >>> 'un_nom_de_fichier_quelconque' ==== Exemple complet ==== Combinons l'ensemble des notions abordées afin d'extraire le seul nom de la ville dans un nom de fichier, en prenant soin de capitaliser sa première lettre. Dans notre exemple le nom de fichier est **747_reservation_sydney.pdf** et il est contenu dans le champ numéro 3. @FLD3.split("_")[-1][0:-4].capitalize() Nous retournera bien **Sydney** ==== Dates et échéance ==== On peut facilement récupérer la date courante : _common.tstamp() Plus intéressant encore, la fonction //tstamp()// accepte un paramètre, à savoir un nombre de seconde depuis une certaine époque (cf. [[http://fr.wikipedia.org/wiki/Heure_Unix|Heure Unix]] Pour récupérer le nombre de seconde depuis cette date jusqu'à maintenant on utilise en python : time.time() On comprend alors facilement comment obtenir une date d'échéance de X jours après la date courante. Il suffit d'additionner le nombre de secondes représentant la date courante avec le nombre de secondes dans X jours. Exemple si l'on veut une date d'échéance à 30 jours après la date courante : >>>_common.tstamp(time.time()+30*24*3600) '2014-11-14 11:12:52' ====== Mise en garde ====== ===== Utilisation de @filename et @filedate ===== L'analyse passe dans le centre d'apprentissage mais échoue en mode travail. Il faut noter que la macro **@filename** récupère le nom du fichier apprenti lorsque l'on est dans le centre d'apprentissage. Or, ce fichier apprenti est préfixé par le numéro de job. Il faut prendre en compte que ce numero ne sera pas contenu dans le nom du fichier lors de l'exécution "normale". Nb: la même précaution s'applique à la macro @filedate qui dans le centre d'apprentissage vous retournera la date de dernière modification du fichier apprenti ( le fichier apprenti étant une copie du fichier résultat de l'ocr).