La història d'un petit projecte de dotze anys de durada (sobre BIRMA.NET per primera vegada i francament de primera mà)

El naixement d'aquest projecte es pot considerar una petita idea que em va sorgir a finals de 2007, que estava destinada a trobar la seva forma definitiva només 12 anys més tard (en aquest moment, és clar, tot i que la implementació actual, segons per a l'autor, és molt satisfactori).

Tot va començar quan, en el procés de complir els meus deures oficials a la biblioteca, vaig cridar l'atenció sobre el fet que el procés d'introduir dades del text escanejat de taules de continguts de publicacions de llibres (i música) a la base de dades existent, aparentment, es pot simplificar i automatitzar significativament, aprofitant la propietat d'ordre i repetibilitat de totes les dades necessàries per a l'entrada, com ara el nom de l'autor de l'article (si estem parlant d'una col·lecció d'articles), el títol de l'article (o el subtítol reflectit a la taula de continguts) i el número de pàgina de la taula de continguts actual. Al principi, estava pràcticament convençut que un sistema adequat per dur a terme aquesta tasca es podia trobar fàcilment a Internet. Quan em va sorprendre el fet de no trobar aquest projecte, vaig decidir intentar implementar-lo pel meu compte.

Al cap de poc temps, va començar a funcionar el primer prototip, que de seguida vaig començar a utilitzar en les meves activitats diàries, depurant-lo simultàniament en tots els exemples que em van venir a la mà. Afortunadament, al meu lloc de treball habitual, on no era de cap manera un programador, encara em vaig sortir amb un "temps d'inactivitat" visible en el meu treball, durant el qual estava depurant intensament la meva idea, una cosa gairebé impensable en les realitats actuals, que implica informes diaris de la feina feta durant el dia. El procés de poliment del programa va durar un total de no menys d'un any, però fins i tot després d'això difícilment es podria dir que el resultat era completament exitós: inicialment es van establir massa conceptes diferents que no estaven del tot clars per a la implementació: elements opcionals que poden ser saltat; visualització cap endavant d'elements (amb la finalitat de substituir elements anteriors als resultats de la cerca); fins i tot el nostre propi intent d'implementar alguna cosa com expressions regulars (que té una sintaxi única). He de dir que abans ja havia abandonat una mica la programació (durant uns 8 anys, si no més), així que la nova oportunitat d'aplicar les meves habilitats a una tasca interessant i necessària em va captar completament l'atenció. No és d'estranyar que el codi font resultant -a falta d'un enfocament clar del seu disseny per part meva- es convertís ràpidament en una mescla inimaginable de peces dispars en llenguatge C amb alguns elements de C++ i aspectes de programació visual (inicialment es va decidir utilitzar un sistema de disseny com Borland C++ Builder - "gairebé Delphi, però en C"). Tot i això, finalment, tot això va donar els seus fruits en l'automatització de les activitats diàries de la nostra biblioteca.

Al mateix temps, vaig decidir, per si de cas, fer cursos per formar desenvolupadors de programari professionals. No sé si realment és possible aprendre a “ser programador” des de zero, però tenint en compte les habilitats que ja tenia en aquell moment, vaig poder dominar una mica les tecnologies que eren més rellevants en aquell moment, com ara com C#, Visual Studio per al desenvolupament sota .NET, així com algunes tecnologies relacionades amb Java, HTML i SQL. Tota la formació va durar un total de dos anys i va servir de punt de partida per a un altre projecte meu, que finalment es va allargar durant diversos anys, però aquest és un tema per a una publicació separada. Aquí només seria apropiat assenyalar que vaig intentar adaptar els desenvolupaments que ja tenia en el projecte descrit per crear una aplicació de finestra completa en C# i WinForms que implementi la funcionalitat necessària i utilitzar-la com a base per al proper projecte de diplomatura.
Amb el temps, aquesta idea em va començar a semblar digna de ser expressada en conferències anuals amb la participació de representants de diverses biblioteques com “LIBKOM” i “CRIMEA”. La idea, sí, però no la meva implementació en aquell moment. Llavors també vaig esperar que algú el reescrigués utilitzant enfocaments més competents. D'una manera o altra, l'any 2013 vaig decidir escriure un informe sobre el meu treball previ i enviar-lo al Comitè Organitzador de la Jornada amb una sol·licitud de subvenció per participar a la Jornada. Per a la meva sorpresa, la meva sol·licitud va ser aprovada i vaig començar a fer algunes millores al projecte per preparar-lo per a la presentació a la conferència.

En aquell moment, el projecte ja havia rebut un nou nom BIRMA, va adquirir diverses capacitats addicionals (no tant completament implementades, sinó assumides): tots els detalls es poden trobar al meu informe.

Per ser sincers, era difícil anomenar BIRMA 2013 alguna cosa completa; Francament parlant, va ser una manualitat molt hack feta de pressa. Pel que fa al codi, pràcticament no hi va haver innovacions especials, tret d'un intent bastant indefens de crear algun tipus de sintaxi unificada per a l'analitzador, en aparença que recorda el llenguatge de format IRBIS 64 (i, de fet, també el sistema ISIS - amb parèntesis com a estructures cícliques; per què Aleshores em va semblar molt bonic). L'analitzador va ensopegar amb aquests cercles de parèntesis del tipus adequat (ja que els parèntesis també tenien un altre paper, és a dir, marcaven estructures opcionals durant l'anàlisi que es poden saltar). Remeixo de nou tots els que vulguin familiaritzar-se amb la sintaxi injustificada i difícil d'imaginar de BIRMA amb més detall al meu informe d'aquella època.

En general, a part de lluitar amb el meu propi analitzador, no tinc res més a dir sobre el codi d'aquesta versió, tret de la conversió inversa de les fonts existents a C++ tot preservant algunes característiques típiques del codi .NET (per ser honest, és difícil d'entendre, què em va impulsar exactament a tornar-ho tot enrere, probablement una estúpida por per mantenir en secret els meus codis font, com si fos una cosa equivalent a la recepta secreta de la Coca-Cola).

Potser aquesta decisió estúpida rau també la raó de les dificultats per emparellar la biblioteca DLL resultant amb la interfície existent d'una estació de treball casolana per introduir dades en un catàleg electrònic (sí, no he esmentat cap altre fet important: a partir d'ara, tots el codi del "motor" de BIRMA era el que s'esperava, està separat de la part de la interfície i empaquetat a la DLL adequada). Per què va ser necessari escriure una estació de treball separada per a aquests propòsits, que de totes maneres, en la seva aparença i mètode d'interacció amb l'usuari, va copiar sense vergonya la mateixa estació de treball "Catalogitzador" del sistema IRBIS 64: aquesta és una pregunta a part. En resum: va donar la solidesa necessària als meus desenvolupaments d'aleshores per al meu projecte de graduació (en cas contrari, el motor d'analitzador indigerible no era suficient). A més, aleshores vaig trobar algunes dificultats per implementar la interfície de l'estació de treball del Catalogador amb els meus mòduls, implementats tant en C++ com en C#, i accedir directament al meu motor.

En general, curiosament, va ser aquest prototip bastant maldestre del futur BIRMA.NET el que estava destinat a convertir-se en el meu "cavall de batalla" durant els propers quatre anys. No es pot dir que durant aquest temps no he intentat almenys trobar la manera d'una implementació nova i més completa d'una idea de llarga data. Entre altres innovacions, ja hi hauria d'haver hagut seqüències cícliques imbricades que podrien haver inclòs elements opcionals; així és com anava a donar vida a la idea de plantilles universals per a descripcions bibliogràfiques de publicacions i altres coses interessants. No obstant això, en les meves activitats pràctiques en aquell moment, tot això tenia poca demanda, i la implementació que tenia en aquell moment era bastant suficient per introduir taules de contingut. A més, la direcció de desenvolupament de la nostra biblioteca va començar a desviar-se cada cop més cap a la digitalització dels arxius dels museus, la divulgació i altres activitats de poc interès per a mi, que al final em van obligar a abandonar-la definitivament, donant pas als qui ho farien. estar més content amb tot això.

Paradoxalment, va ser després d'aquests fets dramàtics que el projecte BIRMA, que en aquell moment ja tenia tots els trets característics d'un projecte de construcció típic a llarg termini, va semblar començar a agafar la seva nova vida tant esperada! Vaig tenir més temps lliure per a pensaments ociosos, vaig tornar a començar a pentinar la World Wide Web a la recerca d'alguna cosa semblant (afortunadament, ara ja podia endevinar que buscaria tot això no a qualsevol lloc, sinó a GitHub), i en algun lloc de At the a principis d'aquest any, finalment em vaig trobar amb un producte corresponent de la coneguda empresa Salesforce amb el nom insignificant Gorp. Per si mateix, podria fer gairebé tot el que necessitava des d'un motor d'anàlisi d'aquest tipus, és a dir, aïllar de manera intel·ligent fragments individuals de text arbitrari, però clarament estructurat, tot i tenir una interfície bastant fàcil d'utilitzar per a l'usuari final, incloses essències tan comprensibles, com ara un patró, una plantilla i una ocurrència, i al mateix temps utilitzant la sintaxi familiar de les expressions regulars, que esdevé incomparablement més llegible a causa de la divisió en grups semàntics designats per a l'anàlisi.

En general, vaig decidir que aquest és el mateix Gorp (Em pregunto què significa aquest nom? Potser una mena d'"analitzador regular orientat a general"?) - exactament el que he estat buscant durant molt de temps. És cert que la seva implementació immediata per a les meves pròpies necessitats va tenir un problema tal que aquest motor requeria una adhesió massa estricta a la seqüència estructural del text font. Per a alguns informes, com ara fitxers de registre (és a dir, els desenvolupadors els van col·locar com a exemples clars d'ús del projecte), això és molt adequat, però per als mateixos textos de les taules de contingut escanejades és poc probable. Al cap i a la fi, la mateixa pàgina amb una taula de continguts pot començar amb les paraules "Taula de continguts", "Continguts" i qualsevol altra descripcions preliminars que no necessitem col·locar als resultats de l'anàlisi previst (i tallant-los manualment). cada cop també és incòmode). A més, entre elements repetitius individuals, com ara el nom de l'autor, el títol i el número de pàgina, la pàgina pot contenir una certa quantitat d'escombraries (per exemple, dibuixos i només caràcters aleatoris), que també seria bo poder tallar. Tanmateix, l'últim aspecte encara no era tan significatiu, però a causa del primer, la implementació existent no va poder començar a buscar les estructures necessàries en el text des d'un lloc determinat, sinó que simplement el va processar des del principi, no va trobar el va especificar patrons allà i... va acabar la meva feina. Òbviament, calia fer alguns retocs per deixar almenys espai entre les estructures repetides, i això em va fer tornar a treballar.

Un altre problema va ser que el projecte en si es va implementar en Java, i si tenia previst implementar en el futur algun mitjà per connectar aquesta tecnologia amb aplicacions conegudes per introduir dades a bases de dades existents (com ara el "Cataloguer") d'Irbis, almenys, almenys feu-ho en C# i .NET. No és que Java en si sigui un llenguatge dolent: fins i tot el vaig utilitzar una vegada per implementar una aplicació de finestra interessant que implementava la funcionalitat d'una calculadora programable domèstica (com a part d'un projecte de curs). I pel que fa a la sintaxi és molt semblant al mateix C sostingut. Bé, això només és un avantatge: més fàcil serà per a mi finalitzar un projecte existent. No obstant això, no volia submergir-me de nou en aquest món força inusual de les tecnologies Java de finestres (o més aviat d'escriptori); després de tot, el llenguatge en si no estava "adaptat" per a aquest ús, i no tenia ganes de repetir-ho. l'experiència anterior. Potser és precisament perquè C# juntament amb WinForms està molt més a prop de Delphi, amb el qual molts de nosaltres vam començar. Afortunadament, la solució necessària es va trobar amb força rapidesa, en forma de projecte IKVM.NET, que facilita la traducció dels programes Java existents al codi .NET gestionat. És cert que el projecte en si ja havia estat abandonat pels autors en aquell moment, però la seva darrera implementació em va permetre dur a terme amb força èxit les accions necessàries per als textos font. Gorp.

Així que vaig fer tots els canvis necessaris i ho vaig reunir tot en una DLL del tipus adequat, que podria ser fàcilment "recollida" per qualsevol projecte per al .NET Framework creat a Visual Studio. Mentrestant, vaig crear una altra capa per a una presentació còmoda dels resultats retornats Gorp, en forma d'estructures de dades corresponents que seria convenient processar en una vista de taula (prenent com a base tant files com columnes; tant claus de diccionari com índexs numèrics). Bé, les utilitats necessàries per processar i mostrar els resultats es van escriure amb força rapidesa.

A més, el procés d'adaptació de plantilles per al nou motor per tal d'ensenyar-li a analitzar mostres existents de textos de la taula de continguts escanejats no va causar cap complicació especial. De fet, ni tan sols vaig haver de fer referència a les meves plantilles anteriors: simplement vaig crear totes les plantilles necessàries des de zero. A més, si les plantilles dissenyades per funcionar amb la versió anterior del sistema estableixen un marc força estret per als textos que es podien analitzar correctament amb la seva ajuda, el nou motor ja va permetre desenvolupar plantilles força universals adequades per a diversos tipus de marcatge a un cop. Fins i tot vaig intentar escriure algun tipus de plantilla completa per a qualsevol text arbitrari de la taula de continguts, tot i que, per descomptat, fins i tot amb totes les noves possibilitats que m'obrien, inclosa, en particular, la capacitat limitada d'implementar les mateixes seqüències repetides imbricades ( com, per exemple, cognoms i inicials diversos autors seguits), això va resultar ser una utopia.

Potser en el futur serà possible implementar un determinat concepte de metaplantilles, que podran comprovar el text d'origen si compleixen diverses de les plantilles disponibles alhora, i després, d'acord amb els resultats obtinguts, seleccionar el el més adequat, utilitzant algun tipus d'algorisme intel·ligent. Però ara em preocupava més una altra pregunta. Un analitzador com Gorp, malgrat tota la seva versatilitat i les modificacions que vaig fer, encara era inherentment incapaç de fer una cosa aparentment senzilla que el meu analitzador escrit per si mateix va ser capaç de fer des de la primera versió. És a dir: tenia la capacitat de trobar i extreure del text d'origen tots els fragments que coincideixen amb la màscara especificada dins de la plantilla utilitzada al lloc correcte, tot i que no li interessava gens el que conté el text donat als espais entre aquests fragments. Fins ara, només he millorat lleugerament el nou motor, permetent-li buscar totes les repeticions noves possibles d'una seqüència determinada d'aquestes màscares des de la posició actual, deixant la possibilitat de la presència en el text de conjunts de caràcters arbitraris que eren completament. no es té en compte a l'anàlisi, tancat entre les estructures repetides detectades. Tanmateix, això no va permetre establir la següent màscara independentment dels resultats de la cerca del fragment anterior amb la màscara corresponent: l'estricte de l'estructura del text descrita encara no deixava espai per a inclusions arbitràries de caràcters irregulars.

I si per als exemples de taules de contingut que em vaig trobar, aquest problema encara no semblava tan greu, llavors quan intento aplicar un nou mecanisme d'anàlisi a una tasca similar d'anàlisi del contingut d'un lloc web (és a dir, el mateix anàlisi), és les limitacions són aquí, van aparèixer amb tota la seva obvietat. Al cap i a la fi, és bastant fàcil establir les màscares necessàries per als fragments de marcatge web, entre els quals s'han de situar les dades que busquem (que cal extreure), però com podem forçar l'analitzador a passar immediatament a la següent fragment similar, malgrat totes les possibles etiquetes i atributs HTML que es poden col·locar als espais entre ells?

Després de pensar una mica, vaig decidir introduir un parell de patrons de servei (%all_before) и (%all_after), amb el propòsit evident d'assegurar que tot el que pot contenir el text d'origen s'omet abans de qualsevol patró (màscara) que els segueix. A més, si (%all_before) simplement ignorava totes aquestes inclusions arbitràries, doncs (%all_after), per contra, permetia afegir-los al fragment desitjat després de passar del fragment anterior. Sembla bastant senzill, però per implementar aquest concepte vaig haver de revisar de nou les fonts de Gorp per fer les modificacions necessàries per no trencar la lògica ja implementada. Al final, vam aconseguir fer-ho (tot i que fins i tot la primera implementació del meu analitzador, encara que amb errors, es va escriure, i encara més ràpid, en un parell de setmanes). A partir d'ara, el sistema va adoptar una forma realment universal, no menys de 12 anys després dels primers intents de fer-lo funcionar.

Per descomptat, aquest no és el final dels nostres somnis. També podeu reescriure completament l'analitzador de plantilles Gorp en C#, utilitzant qualsevol de les biblioteques disponibles per implementar una gramàtica lliure. Crec que el codi s'hauria de simplificar significativament, i això ens permetrà desfer-nos del llegat en forma de fonts Java existents. Però amb el tipus de motor existent, també és molt possible fer diverses coses interessants, inclòs un intent d'implementar les metaplantilles que ja he esmentat, per no parlar de l'anàlisi de diverses dades de diversos llocs web (no obstant això, no descarto que les eines de programari especialitzades existents són més adequades per a això; només que encara no he tingut l'experiència adequada d'utilitzar-les).

Per cert, aquest estiu ja he rebut una invitació per correu electrònic d'una empresa que utilitza tecnologies de Salesforce (el desenvolupador de l'original Gorp), aprovar una entrevista per al treball posterior a Riga. Malauradament, de moment no estic preparat per a aquest tipus de redistribucions.

Si aquest material desperta algun interès, a la segona part intentaré descriure amb més detall la tecnologia per compilar i posteriorment analitzar plantilles utilitzant l'exemple de la implementació utilitzada a Salesforce. Gorp (les meves pròpies addicions, amb l'excepció d'un parell de paraules de funció ja descrites, pràcticament no fan canvis a la sintaxi de la plantilla, de manera que gairebé tota la documentació del sistema original Gorp Apte per a la meva versió també).

Font: www.habr.com

Afegeix comentari