English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Introduction
Avec le développement du World Wide Web et l'arrivée de l'ère du big data, une quantité massive d'informations numériques est produite, stockée, transmise et transformée chaque jour. Comment trouver des informations qui répondent à nos besoins à partir d'une masse d'informations de manière appropriée, les organiser et les utiliser efficacement est un grand défi. La technologie de recherche全文检索 est l'application la plus courante d'information aujourd'hui. Utiliser les moteurs de recherche dans la vie quotidienne, chercher des informations dans les blogs et les forums, les principes de base de ces recherches sont la technologie de recherche全文检索 que nous allons réaliser dans cet article. Avec la numérisation des informations documentaires, le stockage efficace des informations et l'extraction précise en temps opportun sont des bases que chaque entreprise, entreprise et unité doit bien faire. Pour la recherche全文检索 en anglais, il existe déjà de nombreuses théories et méthodes matures, et l'open-source全文检索 moteur Lucene est un sous-projet du Jakarta Project Group de la Apache Software Foundation. Son objectif est de fournir aux développeurs de logiciels un ensemble d'outils simple et facile à utiliser, ce qui facilite la mise en œuvre de la fonction de recherche全文检索 dans le système cible. Lucene ne prend pas en charge le chinois, mais il existe déjà de nombreux outils de segmentation de mots chinois open-source qui peuvent indexer du contenu chinois. Dans cet article, sur la base de la recherche sur les principes de base de Lucene, nous avons respectivement réalisé l'extraction et la recherche de pages web en chinois et en anglais.
1 Introduction à Lucene
1.1 Introduction à Lucene
Lucene est un ensemble d'outils de recherche全文 écrit en Java, qui réalise les deux fonctions centrales de construction d'index et de recherche, et qui sont indépendantes l'une de l'autre, ce qui permet aux développeurs de s'étendre facilement. Lucene fournit une API riche, qui permet une interaction facile avec les informations stockées dans l'index. Il convient de noter qu'il ne s'agit pas d'une application de recherche全文 complète, mais d'un ensemble de fonctionnalités d'indexation et de recherche pour les applications. Autrement dit, pour que Lucene fonctionne vraiment, il est nécessaire de le développer de manière二次 sur cette base.
La conception de la structure de Lucene est assez similaire à la conception de la base de données, mais l'index de Lucene est très différent de celui de la base de données. Les bases de données et Lucene créent des index pour faciliter la recherche, mais la base de données ne crée des index que pour certains champs et nécessite de convertir les données en informations formatées et de les sauvegarder. Le recherche全文 consiste à indexer toutes les informations d'une certaine manière. Les différences et similitudes des deux recherches sont indiquées dans le tableau suivant1-1comme montré
Tableau1-1:Comparaison entre la recherche de base de données et la recherche Lucene
Comparaison |
Recherche Lucene |
Recherche de base de données |
Recherche de données |
Recherche dans les fichiers d'index de Lucene |
Recherche de records par l'index de la base de données |
Structure d'index |
Document (document) |
Enregistrement (record) |
Résultats de recherche |
Hit : les documents satisfaisant les relations |
Ensemble de résultats de recherche : les enregistrements contenant des mots-clés |
Recherche全文 |
Pris en charge |
Non pris en charge |
Recherche floue |
Pris en charge |
Non pris en charge |
Classement des résultats |
Définir le poids, effectuer un classement par pertinence |
Ne peut pas être classé |
1.2 Structure globale de Lucene
La forme de publication du paquet Lucene est un fichier JAR, les mises à jour des versions sont rapides et les écarts entre les versions sont importants, celui utilisé dans cet article est5.3.1de la version, les sous-paquets principalement utilisés sont indiqués dans le tableau suivant1-2comme montré
Tableau1-2:sous-paquet et fonction
Nom du paquet |
Fonction |
Org .apache.lucene .analysis |
Tokenisation |
Org .apache.lucene .document |
Gestion des documents de l'index |
Org .apache.lucene .index |
Opérations sur l'index, y compris l'ajout, la suppression, etc. |
Org .apache.lucene .queryParser |
Constructeur de requête, construction de l'expression de recherche |
Org .apache.lucene .search |
Gestion de recherche |
Org .apache.lucene .store |
Gestion de stockage des données |
Org .apache.lucene .util |
Classe publique |
1.3 Conception architecturale de lucene
Lucene est très puissant, mais fondamentalement, il comprend deux parties principales : d'une part, l'indexation des mots après la coupe du contenu texte ; d'autre part, la restitution des résultats en fonction des conditions de recherche, c'est-à-dire la création d'indices et la recherche.
如图1-1Comme montré, cet article met en avant les interfaces externes et les sources d'informations, et se concentre sur l'indexation et la recherche du contenu texte des爬取 des pages Web.
Figure1-1:Architecture de conception de Lucene
2 Installation de JDK et configuration des variables d'environnement
1.Téléchargement de JDK :
Télécharger le paquet compressé correspondant à la version du système sur le site Web d'Oracle. Cliquez sur Installer, suivez les instructions pour installer. Pendant l'installation, il sera demandé si vous souhaitez installer le jre, cliquez sur Oui.
http://www.oracle.com/technetwork/java/javase/downloads/index.html
2.Définir les variables d'environnement :
(1)Clic droit sur l'ordinateur=》Propriétés=》Paramètres système avancés=》Variables d'environnement=》Variables système=》Nouveau=》JAVA_HOME:chemin d'installation
(2)Ajouter dans Path => %JAVA_HOME%\bin
3.Tester si c'est réussi :
Commencer=》Exécuter=》CMD Entrée Dans la fenêtre DOS qui s'ouvre
Entrée : java -version apparaîtra des informations sur la version
Entrée : javac apparaît des informations sur l'utilisation de javac
Apparaît comme dans l'image suivante2-1Cela montre que c'est réussi.
Figure2-1cmd boîte de commande pour tester la configuration java
3 Écrire du code Java pour obtenir le contenu des pages Web
Parce que Lucene nécessite l'utilisation de différents analyseurs de mots pour différentes langues, l'anglais utilise l'analyseur standard, et le chinois choisit d'utiliser l'analyseur smartcn. Lors de l'obtention des pages Web, il faut d'abord obtenir la page Web et l'enregistrer sous forme de fichier html, dans l'html, en raison de l'interférence des balises, cela peut affecter l'effet de la recherche, par conséquent, il faut supprimer les balises html et convertir le contenu texte en fichier txt pour l'enregistrer. Sauf pour l'analyseur de mots, le chinois et l'anglais sont essentiellement identiques, par conséquent, les codes et les résultats d'expériences qui suivent choisiront l'un d'eux. Cet article choisit comme exemple cinquante pages Web de contes chinois et anglais.
La conception détaillée du code est comme suit : Url2Html.java enregistre le site web entrant en tant que fichier html, Html2Le fichier Txt.java réalise l'enlèvement des balises html du document html et l'enregistre sous forme de fichier txt. Le code détaillé est comme suit3-1et3-2.
public void way(String filePath,String url) throws Exception{ File dest = new File(filePath);//Créer un fichier InputStream is;//Recevoir le flux d'entrée de bytes FileOutputStream fos = new FileOutputStream(dest);//Flux de sortie de bytes URL wangzhi = new URL(url);//Définir l'URL de l'adresse is = wangzhi.openStream(); BufferedInputStream bis = new BufferedInputStream(is);//Ajouter un buffer au flux d'entrée d'octets BufferedOutputStream bos = new BufferedOutputStream(fos);//Ajouter un buffer au flux de sortie d'octets /* * Lire les octets */ int length; byte[] bytes = new byte[1024*20]; while((length = bis.read(bytes, 0, bytes.length)) != -1{ fos.write(bytes, 0, length); } /* * Fermer les flux de buffer et les flux d'entrée/sortie */ bos.close(); fos.close(); bis.close(); is.close(); }
public String getBody(String val){ String zyf = val.replaceAll("<",/?[^>]+>", ""); //Retirer les balises <html> return zyf; } public void writeTxt(String Str,String writePath) { File writename = new File(writePath); try { writename.createNewFile(); BufferedWriter out = new BufferedWriter(new FileWriter(writename)); out.write(Str); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } }
Prenez l'exemple de la page web de l'histoire de fée "Le loup paresseux va à l'école", le chemin du document est réglé sur "E:\work \lucene \test \data \html" et "E:\work\lucene\test\data\txt", et chaque fois que vous lisez la page web, vous devez définir les deux paramètres nécessaires: le nom de fichier filename et l'URL cible url. Créez une fonction main pour appeler ces deux méthodes. L'implémentation détaillée est illustrée comme suit3-3comme montré :
public static void main(String[] args) { String filename = "jingdizhi";//nom du fichier String url = "http://www.51test.net/show/8072125.html";//l'URL de la page web à crawler String filePath = "E:\\work\\lucene\\test\\data\\html\\"+filename+.html;//écrire le chemin d'accès au fichier html+nom de fichier String writePath = "E:\\work\\lucene\\test\\data\\txt\\"+filename+.txt;//écrire le chemin d'accès au fichier txt+nom de fichier Url2Html url2html = new Url2Html(); try { url2html.way(filePath,url); } catch (Exception e) { e.printStackTrace(); } Html2Txt html2txt = new Html2Txt(); String read=html2txt.readfile(filePath);//lire le fichier html String txt = html2txt.getBody(read);//supprimer les balises html System.out.println(txt); try { html2txt.writeTxt(txt,writePath); } catch (Exception e) { e.printStackTrace(); } }
Après l'exécution du programme, deux dossiers sont créés dans "bainloue.xue.html" et "bainloue.xue.txt".
4 Créer un index
Les principes fondamentaux de l'indexation et de la recherche :
Créer un index : l'index du moteur de recherche est en fait l'implémentation de "mot-Structure de données du "matrice de document". C'est aussi la première étape de la recherche全文, Lucene fournit la classe IndexWriter pour la gestion de l'index, principalement include(), delete(), update(). Il y a aussi la définition des valeurs de pondération, en définissant différentes valeurs de pondération des index, on peut retourner selon la taille de la pertinence lors de la recherche.
Recherche : la recherche directe initiale est une recherche séquentielle de documents, après la création de l'index, on peut trouver la position d'apparition des mots dans les documents à travers la recherche de l'index, puis retourner la position et le mot correspondant à l'élément d'index. Lucene fournit la classe IndexSearcher pour la recherche de documents, la forme de recherche principale est divisée en deux catégories, la première : la recherche de mot unique ; la deuxième : le constructeur de recherche personnalisé, qui peut définir des expressions de recherche personnalisées, avec de nombreuses formes de recherche, les méthodes spécifiques seront démontrées après.
4.1 environnement d'expérimentation
Ce PC utilise windows 10x64système,8G de mémoire,256G SSD. L'environnement de développement est Myeclipse 10, version JDK1.8. Pendant le processus de l'expérience, en raison de la transformation de certaines syntaxes, plusieurs classes ont adopté1.6implémentation de la version.
4.2 Créer un index
Créer une base de l'index : ajouter des enregistrements d'index à la base de l'index, Lucene fournit une interface pour ajouter un enregistrement d'index.
Il utilise principalement "écriture index", "document", "domaine" et3 Cette classe. Pour créer un index, il faut d'abord construire un objet Document, déterminer les différents domaines du Document, ce qui est similaire à la création de la structure de table dans une base de données relationnelle, le Document est équivalent à une ligne dans une table, et le domaine est équivalent à une colonne dans une ligne, dans Lucene, pour répondre aux besoins de propriétés et de données de différents domaines, les domaines peuvent également choisir différents types d'index/Règles de stockage des champs, dans cet expériment, le nom de fichier fileName, le chemin complet fullPath et le contenu du texte content sont utilisés comme domaines du Document.
IndexWriter est responsable d'accepter les documents ajoutés et d'écriture dans la base de l'index. Lors de la création de l'IndexWriter "écriture index", il est nécessaire de spécifier l'analyseur de langage utilisé. La création de l'index est divisée en deux catégories, la première : l'index non pondéré ; la deuxième : l'index pondéré.
public Indexer(String indexDir) throws Exception{ Directory dir=FSDirectory.open(Paths.get(indexDir)); Analyzer analyzer=new StandardAnalyzer(); // Tous les segments standard //SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer(); IndexWriterConfig iwc=new IndexWriterConfig(analyzer); writer=new IndexWriter(dir, iwc); }
Définir les champs d'index, Store indique si le contenu de l'index doit être stocké : fileName et fullPath consomment moins de mémoire et peuvent être stockés pour faciliter la recherche et le retour.
private Document getDocument(File f)throws Exception { Document doc=new Document(); doc.add(new TextField("contents", new FileReader(f))); doc.add(new TextField("fileName", f.getName(), Store.YES)); doc.add(new TextField("fullPath", f.getCanonicalPath(), Store.YES));//index de chemin return doc; }
Après l'exécution du code principal, le résultat est représenté comme suit : lors de la conception de l'index d'un fichier, le fichier "fichier d'index :+chemin du fichier
4.3 La suppression et la modification des index
Les opérations courantes sur la base de données incluent CRUD (ajout, suppression, modification, recherche), l'ajout consistant à choisir et à créer des éléments d'index, la recherche, en tant que fonction centrale, sera discutée plus en détail après, ici, nous enregistrons principalement les méthodes utilisées pour supprimer et mettre à jour des index.
La suppression est divisée en deux types, y compris la suppression normale et la suppression complète, car la suppression de l'index affecte l'ensemble de la base de données, et pour les systèmes de grande taille, la suppression de l'index signifie des modifications au niveau inférieur du système, ce qui est chronophage et épuisant, et ne peut pas être annulé. Lorsque l'index était vu précédemment, il a été généré plusieurs petits fichiers, et lors de la recherche, ces fichiers sont combinés et recherchés. La suppression normale ne fait que marquer simplement l'index précédemment créé, ce qui rend impossible la recherche et le retour. La suppression complète consiste à détruire l'index, ce qui ne peut pas être annulé. Par exemple, pour supprimer l'élément d'index "id",1par exemple, l'index de l'exemple:
Suppression ordinaire (suppression avant fusion):
writer.deleteDocuments(new Term("id","1)); writer.commit();
Suppression complète (suppression après fusion):
writer.deleteDocuments(new Term("id","1)); writer.forceMergeDeletes(); // Suppression强制性 writer.commit();
Le principe de modification de l'index est assez simple, il s'agit de réaliser un remplacement sur l'index existant, le code d'implémentation est le même que celui de l'ajout de l'index précédent, et n'est pas développé davantage ici.
4.4 Pondération de l'index
Lucene trie par défaut en fonction de la pertinence, Lucene fournit un paramètre de Boosting pour Field qui peut être réglé, ce paramètre est utilisé pour indiquer l'importance d'un enregistrement, lorsqu'il satisfait les conditions de recherche, les enregistrements importants sont considérés en priorité et retournés en premier, si il y a beaucoup d'enregistrements, les enregistrements avec un faible poids sont placés après la première page, donc l'opération de pondération de l'index est un facteur important influençant la satisfaction des résultats retournés, lors de la conception réelle du système d'information, il devrait y avoir une formule de calcul stricte pour les valeurs de pondération, ce qui facilite la modification des valeurs de pondération de Field, et mieux répondre aux besoins des utilisateurs.
Par exemple, un moteur de recherche attribue une plus grande pondération aux pages web avec un taux de clics élevé et des entrées et sorties de liens, et les classe en premier sur la première page. Le code d'implémentation est représenté sur la figure4-1comme montré, la comparaison entre les résultats sans pondération et avec pondération est représentée sur la figure4-2comme montré
TextField field = new TextField("fullPath", f.getCanonicalPath(), Store.YES); if("A GREAT GRIEF.txt".equals(f.getName())){ field.setBoost(2.0f);//Pondérer le chemin complet du fichier secondry story.txt } //Le poids par défaut est1.0, modifié en1.2C'est-à-dire ajouter du poids. doc.add(field);
Figure4-1Pondération de l'index
Figure4-2Avant pondération
Figure4-2Après pondération
Par exemple4-2Les résultats montrent que sans pondération, les résultats sont retournés en ordre alphabétique, donc first est avant secondry, après avoir pondéré le chemin d'accès au fichier secondry, l'ordre de retour change, ce qui teste la pondération des poids.
5 faire une recherche
L'interface de recherche de Lucene est principalement composée de QueryParser, IndexSearcher, Hits3 Ces classes constituent, QueryParser est le parseur de requête, responsable de l'analyse des mots-clés de recherche soumis par l'utilisateur, lors de la création d'un analyseur, il est nécessaire de spécifier le domaine à analyser et quel analyseur de langue à utiliser, l'analyseur de langue utilisé ici doit être le même que celui utilisé lors de la création de l'index, sinon les résultats de la recherche ne seront pas corrects. IndexSearcher est le rechercheur d'index, lors de l'instanciation d'IndexSearcher, il est nécessaire de spécifier le répertoire de l'index, IndexSearcher a une méthode search qui effectue la recherche de l'index, cette méthode accepte Query comme paramètre, retourne Hits, Hits est une collection d'ensembles de résultats de recherche bien ordonnés, les éléments de la collection sont Document. Il est possible d'obtenir des informations correspondantes au document par le biais de la méthode get de Document, par exemple : nom de fichier, chemin d'accès au fichier, contenu du fichier, etc.
5.1 Recherche de base
Il y a deux principales méthodes de recherche comme dans l'image, mais il est recommandé d'utiliser la première méthode de construction de l'expression QueryParser, qui peut avoir des modes de combinaison flexibles, y compris les expressions logiques booléennes et la correspondance floue, mais le deuxième Term ne peut être utilisé que pour la recherche de vocabulaire.
1Construction de l'expression de QueryParser :
QueryParser parser=new QueryParser("fullPath", analyzer); Query query=parser.parse(q);
2Recherche de l'élément spécifique :
Term t = new Term("fileName", q); Query query = new TermQuery(t);
Les résultats de la recherche sont montrés comme dans l'image5-1comme montré : par exemple, pour une recherche de fichiers nommés fileName contenant "grand".
Figure5-1: résultats de la recherche "grand"
5.2 Recherche floue
Lors de la construction de QueryParser, en modifiant le terme q, il est possible d'obtenir une correspondance exacte et floue. La correspondance floue est modifiée en ajoutant "~" après "q". Comme dans l'image5-2comme montré :
Figure5-2: correspondance floue
5.3 Recherche de conditions spécifiées
Recherche logique booléenne et recherche floue nécessitent uniquement de modifier le mot de recherche q, tandis que la recherche de conditions spécifiées nécessite de définir l'expression query, principalement divisées en plusieurs catégories :
Recherche de plage d'éléments spécifiés, plage numérique spécifiée, début de chaîne spécifié et recherche de multiples conditions, voici les requêtes appliquées, le paramètre true indique : inclure la limite supérieure et inférieure.
Spécification de la plage d'éléments :
TermRangeQuery query=new TermRangeQuery("desc", new BytesRef("b".getBytes()), new BytesRef("c".getBytes()), true, true);
指定数字范围:
NumericRangeQuery<Integer> query=NumericRangeQuery.newIntRange("id", 1, 2, true, true);
指定字符串开头:
PrefixQuery query=new PrefixQuery(new Term("city","a"));
多条件查询:
NumericRangeQuery<Integer>query1=NumericRangeQuery.newIntRange("id", 1, 2, true, true); PrefixQuery query2=new PrefixQuery(new Term("city","a")); BooleanQuery.Builder booleanQuery=new BooleanQuery.Builder(); booleanQuery.add(query1,BooleanClause.Occur.MUST); booleanQuery.add(query2,BooleanClause.Occur.MUST);
5.4 高亮查询
在百度、谷歌等搜索引擎中,进行查询时,返回的网页包含查询关键字的时候会显示为红色,且进行摘要显示,即对包含关键字的部分内容进行截取并返回。高亮查询即为实现对关键字的样式更改,本实验在myeclipse中进行,返回结果并不会有样式的改变,只会对返回内容的关键字添加html标签,如果显示到网页即产生样式的变化。
高亮的设置代码如图5-3如图所示,结果如图5-4如图所示,会对南京匹配词添加<b>和<font>标签,显示到网页上为加粗和变红。
QueryScorer scorer=new QueryScorer(query); Fragmenter fragmenter=new SimpleSpanFragmenter(scorer); SimpleHTMLFormatter simpleHTMLFormatter=new SimpleHTMLFormatter("<b><font color='red'>","</font></b>"); Highlighter highlighter=new Highlighter(simpleHTMLFormatter, scorer); highlighter.setTextFragmenter(fragmenter);
Figure5-3: Highlight settings
Figure5-4: Highlight the results
6 Problems and shortcomings encountered in the experiment process
Lucene version updates quickly, there is a good connection between jdk version, eclipse version, and lucene version, otherwise many incompatibilities will occur, and debugging version as well as jdk1.6and jdk1.8selection presents many difficulties, such as the append method in web page crawling in1.8version has been deleted and cannot be used. However, the reading of document path FSDirectory.open() still requires jdk1.8only supports.
The shortcomings of this experiment are mainly manifested in:
The flexibility of the code is low, and manual operation is required when crawling web pages, and both Chinese and English need to be processed separately. It should be improved to make a judgment on the language of the web page, and then automatically select different segmenters to execute.
The reusability of the code is low, there is no reasonable classification and construction of methods. For simplicity, comments and marks are basically made on several core codes to achieve the effect, which needs to be improved.
The portability of the code is low, the crawling of web pages uses jdk1.6version, Lucene's implementation uses jdk1.8version, when exporting to other machines, it is necessary to make some slight modifications and configurations, and cannot be realized with one-click operation.
7 Summary
This article starts from the principle of Lucene and understands the ideas and methods of full-text search, and performs experiments and tests on the commonly used functions. In the process of the experiment, I learned the principle of search engines and had a better practical experience based on the content of the information retrieval course. Lucene is an excellent open-source full-text search technology framework. Through in-depth study of it, I have become more familiar with its implementation mechanism. In the process of studying it, I have learned a lot of object-oriented programming methods and ideas. Its good system framework and scalability are worth learning and referencing.
Declaration: The content of this article is from the Internet, the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, does not edit the content manually, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (when sending an email, please replace # with @ to report abuse, and provide relevant evidence. Once verified, this site will immediately delete the infringing content.)