smartlex-search 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smartlex_search-1.0.0/LICENSE +14 -0
- smartlex_search-1.0.0/PKG-INFO +188 -0
- smartlex_search-1.0.0/pyproject.toml +33 -0
- smartlex_search-1.0.0/readme.md +170 -0
- smartlex_search-1.0.0/setup.cfg +4 -0
- smartlex_search-1.0.0/src/smartlex/__init__.py +0 -0
- smartlex_search-1.0.0/src/smartlex/core/__init__.py +0 -0
- smartlex_search-1.0.0/src/smartlex/core/config.py +23 -0
- smartlex_search-1.0.0/src/smartlex/core/index_manager.py +21 -0
- smartlex_search-1.0.0/src/smartlex/core/keyword_extraction.py +29 -0
- smartlex_search-1.0.0/src/smartlex/core/logger.py +23 -0
- smartlex_search-1.0.0/src/smartlex/core/processor.py +54 -0
- smartlex_search-1.0.0/src/smartlex/core/scanner.py +159 -0
- smartlex_search-1.0.0/src/smartlex/core/search_engine.py +15 -0
- smartlex_search-1.0.0/src/smartlex/core/text_extraction.py +28 -0
- smartlex_search-1.0.0/src/smartlex/gui/__init__.py +0 -0
- smartlex_search-1.0.0/src/smartlex/gui/main_window.py +412 -0
- smartlex_search-1.0.0/src/smartlex/gui/threads.py +113 -0
- smartlex_search-1.0.0/src/smartlex/gui/widgets.py +87 -0
- smartlex_search-1.0.0/src/smartlex/main.py +74 -0
- smartlex_search-1.0.0/src/smartlex_search.egg-info/PKG-INFO +188 -0
- smartlex_search-1.0.0/src/smartlex_search.egg-info/SOURCES.txt +24 -0
- smartlex_search-1.0.0/src/smartlex_search.egg-info/dependency_links.txt +1 -0
- smartlex_search-1.0.0/src/smartlex_search.egg-info/entry_points.txt +2 -0
- smartlex_search-1.0.0/src/smartlex_search.egg-info/requires.txt +7 -0
- smartlex_search-1.0.0/src/smartlex_search.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Copyright (c) 2025 DAKSH GOEL
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
This software and associated documentation files (the “SmartLex”) are the
|
|
5
|
+
intellectual property of DAKSH GOEL.
|
|
6
|
+
|
|
7
|
+
Unauthorized copying, modification, distribution, or use of this software,
|
|
8
|
+
in whole or in part, is strictly prohibited without explicit written
|
|
9
|
+
permission from the copyright holder.
|
|
10
|
+
|
|
11
|
+
The Software may not be used for commercial, educational, or research
|
|
12
|
+
purposes without prior consent.
|
|
13
|
+
|
|
14
|
+
For inquiries about licensing or usage, contact: `goel.daksh2008@gmail.com`.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: smartlex-search
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A lexical, ultra-fast cross-platform search engine
|
|
5
|
+
Author-email: Daksh Goel <daksh@example.com>
|
|
6
|
+
License: Custom Proprietary License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: PyQt5==5.15.9
|
|
12
|
+
Requires-Dist: PyMuPDF==1.23.8
|
|
13
|
+
Requires-Dist: rake-nltk==1.0.6
|
|
14
|
+
Requires-Dist: nltk==3.8.1
|
|
15
|
+
Requires-Dist: python-docx==1.1.0
|
|
16
|
+
Requires-Dist: tqdm==4.66.1
|
|
17
|
+
Requires-Dist: watchdog==3.0.0
|
|
18
|
+
|
|
19
|
+
# Smart Lexical Search Engine
|
|
20
|
+
|
|
21
|
+
## A powerful desktop search application that searches **inside** PDF and Word documents based on content keywords given by the user.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
### Core Features
|
|
26
|
+
|
|
27
|
+
- **Content-based search**: Find documents by keywords inside them
|
|
28
|
+
- **Multi-format support**: PDF and DOCX files
|
|
29
|
+
- **Fast search**: ~0.02 seconds after initial indexing
|
|
30
|
+
- **Smart ranking**: Results sorted by relevance
|
|
31
|
+
- **Auto-complete**: Suggests keywords dynamically as you type
|
|
32
|
+
|
|
33
|
+
### Enhanced Features (New)
|
|
34
|
+
|
|
35
|
+
- **Standalone Executable**: No Python needed! Run straight from your desktop.
|
|
36
|
+
- **Cross-Platform Package**: Install via `pip install smartlex-search`
|
|
37
|
+
- **Modern UI**: Clean, beautifully designed Qt interface with dynamic status indicators.
|
|
38
|
+
- **Parallel processing**: Uses multithreading for blazingly fast background indexing.
|
|
39
|
+
- **Automated Setup**: Completely self-contained, handles NLTK and indexing without scripts!
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
### Method 1: The Standalone App (No Python Required!)
|
|
46
|
+
|
|
47
|
+
1. Go to the **Releases** page of this GitHub repository.
|
|
48
|
+
2. Download `SmartLex.exe`.
|
|
49
|
+
3. Double-click it! The app will automatically handle indexing and open right up.
|
|
50
|
+
|
|
51
|
+
### Method 2: Terminal Package (For Developers)
|
|
52
|
+
|
|
53
|
+
You can install this directly into your Python environment as a global package.
|
|
54
|
+
|
|
55
|
+
1. **Install via pip**
|
|
56
|
+
```bash
|
|
57
|
+
pip install smartlex-search
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
2. **Run it from anywhere**
|
|
61
|
+
```bash
|
|
62
|
+
smartlex
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
*(Note: To install the developer version from source, simply clone the repo and run `pip install -e .`)*
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
|
|
71
|
+
### First Run (Indexing)
|
|
72
|
+
|
|
73
|
+
Whether you use the `.exe` or the `smartlex` terminal command, the application will automatically detect if it is your first time running it. It will launch a background scanner that sweeps your drives for PDFs and Word documents, extracts their keywords using advanced NLP, and builds your local index.
|
|
74
|
+
|
|
75
|
+
⏱️ **First run**: Depends on the number of files (usually a few minutes)
|
|
76
|
+
⏱️ **Subsequent runs**: Instant! The UI will pop open in less than a second.
|
|
77
|
+
|
|
78
|
+
### Regular Usage
|
|
79
|
+
|
|
80
|
+
1. Type keywords in the modern search bar (e.g., "machine learning").
|
|
81
|
+
2. The dynamic auto-complete will suggest words based specifically on the contents of your own files!
|
|
82
|
+
3. Press Enter or click Search.
|
|
83
|
+
4. Click or double-click any beautifully formatted result to instantly open the document.
|
|
84
|
+
|
|
85
|
+
### Keyboard Shortcuts
|
|
86
|
+
|
|
87
|
+
- `Enter`: Search / Open selected document
|
|
88
|
+
- `Tab`: Switch between search bar and results
|
|
89
|
+
- `↑/↓`: Navigate through results
|
|
90
|
+
- `Ctrl+F`: Focus the search bar
|
|
91
|
+
- `Esc`: Clear search / Close application
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## How It Works
|
|
96
|
+
|
|
97
|
+
### Architecture
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
User Query → RAKE Extraction → Keyword Matching → Ranking → Results
|
|
101
|
+
↑
|
|
102
|
+
Document Index ← Multithreading ← Automated File Scanner
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Step-by-Step Process
|
|
106
|
+
|
|
107
|
+
#### 1️ **File Collection** (First Run Only)
|
|
108
|
+
- The internal Python scanner recursively sweeps all connected system drives.
|
|
109
|
+
- It strictly filters out system folders (`Windows`, `Program Files`, `.git`) for maximum speed.
|
|
110
|
+
- It collects all PDF and DOCX file paths.
|
|
111
|
+
|
|
112
|
+
#### 2️ **Parallel Indexing** (First Run Only)
|
|
113
|
+
- Multiple background threads parse the documents simultaneously to maximize CPU efficiency.
|
|
114
|
+
|
|
115
|
+
#### 3️ **Keyword Extraction** (RAKE Algorithm)
|
|
116
|
+
```text
|
|
117
|
+
Input: "Machine learning algorithms use neural networks"
|
|
118
|
+
↓
|
|
119
|
+
Remove stopwords: "Machine learning algorithms use neural networks"
|
|
120
|
+
↓
|
|
121
|
+
Extract phrases: ["machine learning algorithms", "neural networks"]
|
|
122
|
+
↓
|
|
123
|
+
Split to words: ["machine", "learning", "algorithms", "neural", "networks"]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### 4️ **Index Storage**
|
|
127
|
+
The system builds an ultra-fast lookup dictionary (`output.json`):
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"C:/docs/paper1.pdf": ["machine", "learning", "neural", "network"],
|
|
131
|
+
"C:/docs/paper2.pdf": ["algorithm", "optimization", "training"]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### 5️ **Search Process**
|
|
136
|
+
```text
|
|
137
|
+
User types: "neural network training"
|
|
138
|
+
↓
|
|
139
|
+
Extract keywords: ["neural", "network", "training"]
|
|
140
|
+
↓
|
|
141
|
+
Find matching documents:
|
|
142
|
+
paper1.pdf: 2 matches (neural, network)
|
|
143
|
+
paper2.pdf: 1 match (training)
|
|
144
|
+
↓
|
|
145
|
+
Rank by relevance:
|
|
146
|
+
1. paper1.pdf (score: 2)
|
|
147
|
+
2. paper2.pdf (score: 1)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Project Structure
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
SmartLex/
|
|
156
|
+
│
|
|
157
|
+
├── pyproject.toml # Package configuration
|
|
158
|
+
├── run.py # PyInstaller entry point
|
|
159
|
+
│
|
|
160
|
+
├── src/smartlex/
|
|
161
|
+
│ ├── main.py # Core application entry
|
|
162
|
+
│ ├── core/ # NLP, parsing, and indexing logic
|
|
163
|
+
│ └── gui/ # PyQt5 interface and background threads
|
|
164
|
+
│
|
|
165
|
+
├── requirements.txt
|
|
166
|
+
├── config.json
|
|
167
|
+
└── README.md
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Reference
|
|
173
|
+
|
|
174
|
+
- [Base Paper / Reference PDF](https://drive.google.com/file/d/10f3bUmaTRzAZ2jOq6oWFu0ilP6Q6dyJx/view?usp=sharing)
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Sample Screenshots
|
|
179
|
+
- ### 🪟 Initial Window
|
|
180
|
+

|
|
181
|
+
|
|
182
|
+
### 📄 Output Window
|
|
183
|
+
|
|
184
|
+

|
|
185
|
+
|
|
186
|
+
### Future enhancement
|
|
187
|
+
- Working on adding support for additional file types such as TXT, CSV, XLSX, PPTX, HTML, etc.
|
|
188
|
+
- Currently working on similar functionality for images, audios etc.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "smartlex-search"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name="Daksh Goel", email="daksh@example.com" },
|
|
10
|
+
]
|
|
11
|
+
description = "A lexical, ultra-fast cross-platform search engine"
|
|
12
|
+
readme = "readme.md"
|
|
13
|
+
license = { text = "Custom Proprietary License" }
|
|
14
|
+
requires-python = ">=3.8"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"PyQt5==5.15.9",
|
|
21
|
+
"PyMuPDF==1.23.8",
|
|
22
|
+
"rake-nltk==1.0.6",
|
|
23
|
+
"nltk==3.8.1",
|
|
24
|
+
"python-docx==1.1.0",
|
|
25
|
+
"tqdm==4.66.1",
|
|
26
|
+
"watchdog==3.0.0"
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
smartlex = "smartlex.main:main"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
license-files = []
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Smart Lexical Search Engine
|
|
2
|
+
|
|
3
|
+
## A powerful desktop search application that searches **inside** PDF and Word documents based on content keywords given by the user.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### Core Features
|
|
8
|
+
|
|
9
|
+
- **Content-based search**: Find documents by keywords inside them
|
|
10
|
+
- **Multi-format support**: PDF and DOCX files
|
|
11
|
+
- **Fast search**: ~0.02 seconds after initial indexing
|
|
12
|
+
- **Smart ranking**: Results sorted by relevance
|
|
13
|
+
- **Auto-complete**: Suggests keywords dynamically as you type
|
|
14
|
+
|
|
15
|
+
### Enhanced Features (New)
|
|
16
|
+
|
|
17
|
+
- **Standalone Executable**: No Python needed! Run straight from your desktop.
|
|
18
|
+
- **Cross-Platform Package**: Install via `pip install smartlex-search`
|
|
19
|
+
- **Modern UI**: Clean, beautifully designed Qt interface with dynamic status indicators.
|
|
20
|
+
- **Parallel processing**: Uses multithreading for blazingly fast background indexing.
|
|
21
|
+
- **Automated Setup**: Completely self-contained, handles NLTK and indexing without scripts!
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
### Method 1: The Standalone App (No Python Required!)
|
|
28
|
+
|
|
29
|
+
1. Go to the **Releases** page of this GitHub repository.
|
|
30
|
+
2. Download `SmartLex.exe`.
|
|
31
|
+
3. Double-click it! The app will automatically handle indexing and open right up.
|
|
32
|
+
|
|
33
|
+
### Method 2: Terminal Package (For Developers)
|
|
34
|
+
|
|
35
|
+
You can install this directly into your Python environment as a global package.
|
|
36
|
+
|
|
37
|
+
1. **Install via pip**
|
|
38
|
+
```bash
|
|
39
|
+
pip install smartlex-search
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
2. **Run it from anywhere**
|
|
43
|
+
```bash
|
|
44
|
+
smartlex
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
*(Note: To install the developer version from source, simply clone the repo and run `pip install -e .`)*
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
### First Run (Indexing)
|
|
54
|
+
|
|
55
|
+
Whether you use the `.exe` or the `smartlex` terminal command, the application will automatically detect if it is your first time running it. It will launch a background scanner that sweeps your drives for PDFs and Word documents, extracts their keywords using advanced NLP, and builds your local index.
|
|
56
|
+
|
|
57
|
+
⏱️ **First run**: Depends on the number of files (usually a few minutes)
|
|
58
|
+
⏱️ **Subsequent runs**: Instant! The UI will pop open in less than a second.
|
|
59
|
+
|
|
60
|
+
### Regular Usage
|
|
61
|
+
|
|
62
|
+
1. Type keywords in the modern search bar (e.g., "machine learning").
|
|
63
|
+
2. The dynamic auto-complete will suggest words based specifically on the contents of your own files!
|
|
64
|
+
3. Press Enter or click Search.
|
|
65
|
+
4. Click or double-click any beautifully formatted result to instantly open the document.
|
|
66
|
+
|
|
67
|
+
### Keyboard Shortcuts
|
|
68
|
+
|
|
69
|
+
- `Enter`: Search / Open selected document
|
|
70
|
+
- `Tab`: Switch between search bar and results
|
|
71
|
+
- `↑/↓`: Navigate through results
|
|
72
|
+
- `Ctrl+F`: Focus the search bar
|
|
73
|
+
- `Esc`: Clear search / Close application
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## How It Works
|
|
78
|
+
|
|
79
|
+
### Architecture
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
User Query → RAKE Extraction → Keyword Matching → Ranking → Results
|
|
83
|
+
↑
|
|
84
|
+
Document Index ← Multithreading ← Automated File Scanner
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Step-by-Step Process
|
|
88
|
+
|
|
89
|
+
#### 1️ **File Collection** (First Run Only)
|
|
90
|
+
- The internal Python scanner recursively sweeps all connected system drives.
|
|
91
|
+
- It strictly filters out system folders (`Windows`, `Program Files`, `.git`) for maximum speed.
|
|
92
|
+
- It collects all PDF and DOCX file paths.
|
|
93
|
+
|
|
94
|
+
#### 2️ **Parallel Indexing** (First Run Only)
|
|
95
|
+
- Multiple background threads parse the documents simultaneously to maximize CPU efficiency.
|
|
96
|
+
|
|
97
|
+
#### 3️ **Keyword Extraction** (RAKE Algorithm)
|
|
98
|
+
```text
|
|
99
|
+
Input: "Machine learning algorithms use neural networks"
|
|
100
|
+
↓
|
|
101
|
+
Remove stopwords: "Machine learning algorithms use neural networks"
|
|
102
|
+
↓
|
|
103
|
+
Extract phrases: ["machine learning algorithms", "neural networks"]
|
|
104
|
+
↓
|
|
105
|
+
Split to words: ["machine", "learning", "algorithms", "neural", "networks"]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### 4️ **Index Storage**
|
|
109
|
+
The system builds an ultra-fast lookup dictionary (`output.json`):
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"C:/docs/paper1.pdf": ["machine", "learning", "neural", "network"],
|
|
113
|
+
"C:/docs/paper2.pdf": ["algorithm", "optimization", "training"]
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### 5️ **Search Process**
|
|
118
|
+
```text
|
|
119
|
+
User types: "neural network training"
|
|
120
|
+
↓
|
|
121
|
+
Extract keywords: ["neural", "network", "training"]
|
|
122
|
+
↓
|
|
123
|
+
Find matching documents:
|
|
124
|
+
paper1.pdf: 2 matches (neural, network)
|
|
125
|
+
paper2.pdf: 1 match (training)
|
|
126
|
+
↓
|
|
127
|
+
Rank by relevance:
|
|
128
|
+
1. paper1.pdf (score: 2)
|
|
129
|
+
2. paper2.pdf (score: 1)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Project Structure
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
SmartLex/
|
|
138
|
+
│
|
|
139
|
+
├── pyproject.toml # Package configuration
|
|
140
|
+
├── run.py # PyInstaller entry point
|
|
141
|
+
│
|
|
142
|
+
├── src/smartlex/
|
|
143
|
+
│ ├── main.py # Core application entry
|
|
144
|
+
│ ├── core/ # NLP, parsing, and indexing logic
|
|
145
|
+
│ └── gui/ # PyQt5 interface and background threads
|
|
146
|
+
│
|
|
147
|
+
├── requirements.txt
|
|
148
|
+
├── config.json
|
|
149
|
+
└── README.md
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Reference
|
|
155
|
+
|
|
156
|
+
- [Base Paper / Reference PDF](https://drive.google.com/file/d/10f3bUmaTRzAZ2jOq6oWFu0ilP6Q6dyJx/view?usp=sharing)
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Sample Screenshots
|
|
161
|
+
- ### 🪟 Initial Window
|
|
162
|
+

|
|
163
|
+
|
|
164
|
+
### 📄 Output Window
|
|
165
|
+
|
|
166
|
+

|
|
167
|
+
|
|
168
|
+
### Future enhancement
|
|
169
|
+
- Working on adding support for additional file types such as TXT, CSV, XLSX, PPTX, HTML, etc.
|
|
170
|
+
- Currently working on similar functionality for images, audios etc.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# core/config.py
|
|
2
|
+
import json
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
CONFIG_FILE = Path("config.json")
|
|
6
|
+
|
|
7
|
+
DEFAULT_CONFIG = {
|
|
8
|
+
"NUM_PROCESSES": 8,
|
|
9
|
+
"TOP_KEYWORDS": 150,
|
|
10
|
+
"AUTOCOMPLETE_WORDS": 100,
|
|
11
|
+
"SUPPORTED_FORMATS": [".pdf", ".docx"],
|
|
12
|
+
"INDEX_FOLDER": "all",
|
|
13
|
+
"OUTPUT_FILE": "output.json",
|
|
14
|
+
"AUTOCOMPLETE_FILE": "autocomplete_words.json",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def load_config():
|
|
19
|
+
if CONFIG_FILE.exists():
|
|
20
|
+
with open(CONFIG_FILE, "r") as f:
|
|
21
|
+
user_config = json.load(f)
|
|
22
|
+
return {**DEFAULT_CONFIG, **user_config}
|
|
23
|
+
return DEFAULT_CONFIG
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections import Counter
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def save_index(data, output_file):
|
|
7
|
+
with open(output_file, "w") as f:
|
|
8
|
+
json.dump(data, f, indent=2)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def load_index(output_file):
|
|
12
|
+
with open(output_file, "r") as f:
|
|
13
|
+
return json.load(f)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def generate_autocomplete(data, top_n):
|
|
17
|
+
words = []
|
|
18
|
+
for kws in data.values():
|
|
19
|
+
words.extend(kws)
|
|
20
|
+
freq = Counter(words)
|
|
21
|
+
return [w for w, _ in freq.most_common(top_n)]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from rake_nltk import Rake
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def rake_keywords(text):
|
|
7
|
+
if not text or not text.strip():
|
|
8
|
+
return []
|
|
9
|
+
|
|
10
|
+
r = Rake()
|
|
11
|
+
r.extract_keywords_from_text(text)
|
|
12
|
+
ranked_phrases = r.get_ranked_phrases()
|
|
13
|
+
filtered = []
|
|
14
|
+
|
|
15
|
+
for phrase in ranked_phrases:
|
|
16
|
+
if any(
|
|
17
|
+
[
|
|
18
|
+
re.search(r"\b\w\b", phrase),
|
|
19
|
+
re.search(r"\d", phrase),
|
|
20
|
+
re.search(r"[*&!()?/>.<,:;\"\]\[\}\{]", phrase),
|
|
21
|
+
]
|
|
22
|
+
):
|
|
23
|
+
continue
|
|
24
|
+
|
|
25
|
+
for word in phrase.split():
|
|
26
|
+
if len(word) > 2:
|
|
27
|
+
filtered.append(word.lower())
|
|
28
|
+
|
|
29
|
+
return filtered
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# core/logger.py
|
|
2
|
+
import logging
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def setup_logger(name="search_engine", log_file="search_engine.log"):
|
|
7
|
+
log_path = Path("logs")
|
|
8
|
+
log_path.mkdir(exist_ok=True)
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(name)
|
|
11
|
+
logger.setLevel(logging.INFO)
|
|
12
|
+
|
|
13
|
+
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
|
|
14
|
+
|
|
15
|
+
fh = logging.FileHandler(log_path / log_file)
|
|
16
|
+
sh = logging.StreamHandler()
|
|
17
|
+
|
|
18
|
+
fh.setFormatter(formatter)
|
|
19
|
+
sh.setFormatter(formatter)
|
|
20
|
+
|
|
21
|
+
logger.addHandler(fh)
|
|
22
|
+
logger.addHandler(sh)
|
|
23
|
+
return logger
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import concurrent.futures
|
|
2
|
+
import os
|
|
3
|
+
from collections import Counter
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from smartlex.core.keyword_extraction import rake_keywords
|
|
7
|
+
from smartlex.core.logger import setup_logger
|
|
8
|
+
from smartlex.core.text_extraction import extract_text_docx, extract_text_pdf
|
|
9
|
+
|
|
10
|
+
logger = setup_logger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def extract_keywords_from_file(file_path):
|
|
14
|
+
if file_path.endswith(".pdf"):
|
|
15
|
+
text = extract_text_pdf(file_path)
|
|
16
|
+
elif file_path.endswith(".docx"):
|
|
17
|
+
text = extract_text_docx(file_path)
|
|
18
|
+
else:
|
|
19
|
+
return []
|
|
20
|
+
return rake_keywords(text)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def process_batch(batch_file):
|
|
24
|
+
result = {}
|
|
25
|
+
if not os.path.exists(batch_file):
|
|
26
|
+
logger.error(f"Batch file not found: {batch_file}")
|
|
27
|
+
return result
|
|
28
|
+
|
|
29
|
+
with open(batch_file, "r", encoding="utf-8") as f:
|
|
30
|
+
paths = [line.strip() for line in f]
|
|
31
|
+
|
|
32
|
+
for path in paths:
|
|
33
|
+
if os.path.exists(path):
|
|
34
|
+
kws = extract_keywords_from_file(path)
|
|
35
|
+
if kws:
|
|
36
|
+
result[path] = kws
|
|
37
|
+
return result
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def refine_keywords(data, top_n):
|
|
41
|
+
for k, v in data.items():
|
|
42
|
+
c = Counter(v)
|
|
43
|
+
top_values = [w for w, _ in c.most_common(top_n)]
|
|
44
|
+
data[k] = list(set(top_values))
|
|
45
|
+
return data
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def process_all_batches(batch_files, top_n):
|
|
49
|
+
D = {}
|
|
50
|
+
with concurrent.futures.ProcessPoolExecutor() as executor:
|
|
51
|
+
results = list(executor.map(process_batch, batch_files))
|
|
52
|
+
for res in results:
|
|
53
|
+
D.update(res)
|
|
54
|
+
return refine_keywords(D, top_n)
|