ogx786 commited on
Commit
c22c8cc
·
verified ·
1 Parent(s): d7b8c4f

Create make_data.py

Browse files
Files changed (1) hide show
  1. make_data.py +503 -0
make_data.py ADDED
@@ -0,0 +1,503 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import json
3
+ import csv
4
+ import pandas as pd
5
+ from tqdm import tqdm
6
+
7
+
8
+ # ============================================================
9
+ # CONFIGURATION
10
+ # ============================================================
11
+
12
+ INPUT_FILE = "hbl_mongodb_export.txt"
13
+
14
+ OUTPUT_FILE = "hbl_nadra_clean.csv"
15
+
16
+
17
+ # For testing:
18
+ # Example:
19
+ # LIMIT_ROWS = 10000
20
+ #
21
+ # Full dataset:
22
+ LIMIT_ROWS = None
23
+
24
+
25
+ # Required API fields
26
+ FIELDS = [
27
+ "name",
28
+ "fatherName",
29
+ "motherName",
30
+ "address1",
31
+ "address2",
32
+ "placeOfBirth"
33
+ ]
34
+
35
+
36
+ # ============================================================
37
+ # MONGODB TEXT PARSER
38
+ # ============================================================
39
+
40
+
41
+ def clean_mongo_syntax(text):
42
+
43
+ """
44
+ Convert Mongo shell syntax into JSON compatible syntax
45
+ """
46
+
47
+ # ObjectId("xxx") -> "xxx"
48
+ text = re.sub(
49
+ r'ObjectId\("([^"]+)"\)',
50
+ r'"\1"',
51
+ text
52
+ )
53
+
54
+
55
+ # ISODate("xxx") -> "xxx"
56
+ text = re.sub(
57
+ r'ISODate\("([^"]+)"\)',
58
+ r'"\1"',
59
+ text
60
+ )
61
+
62
+
63
+ # NumberInt(200) -> 200
64
+ text = re.sub(
65
+ r'NumberInt\((\d+)\)',
66
+ r'\1',
67
+ text
68
+ )
69
+
70
+
71
+ return text
72
+
73
+
74
+
75
+ def extract_documents(path):
76
+
77
+ """
78
+ Extract individual Mongo documents
79
+ """
80
+
81
+ print("Reading MongoDB export...")
82
+
83
+
84
+ with open(
85
+ path,
86
+ "r",
87
+ encoding="utf-8"
88
+ ) as f:
89
+
90
+ content = f.read()
91
+
92
+
93
+
94
+ content = clean_mongo_syntax(
95
+ content
96
+ )
97
+
98
+
99
+ documents = []
100
+
101
+
102
+ decoder = json.JSONDecoder()
103
+
104
+
105
+ index = 0
106
+
107
+
108
+ while index < len(content):
109
+
110
+ # skip whitespace
111
+ while (
112
+ index < len(content)
113
+ and content[index].isspace()
114
+ ):
115
+ index += 1
116
+
117
+
118
+ if index >= len(content):
119
+ break
120
+
121
+
122
+ # Find next object
123
+ if content[index] != "{":
124
+
125
+ index += 1
126
+ continue
127
+
128
+
129
+ try:
130
+
131
+ obj, end = decoder.raw_decode(
132
+ content,
133
+ index
134
+ )
135
+
136
+ documents.append(obj)
137
+
138
+ index = end
139
+
140
+
141
+ except Exception:
142
+
143
+ index += 1
144
+
145
+
146
+
147
+ return documents
148
+
149
+
150
+
151
+ # ============================================================
152
+ # TEXT NORMALIZATION
153
+ # ============================================================
154
+
155
+
156
+ def remove_unicode_artifacts(text):
157
+
158
+ if not text:
159
+ return ""
160
+
161
+
162
+ text = str(text)
163
+
164
+
165
+ # Directional marks
166
+ text = re.sub(
167
+ r"[\u202A-\u202E]",
168
+ "",
169
+ text
170
+ )
171
+
172
+
173
+ # Zero width characters
174
+ text = re.sub(
175
+ r"[\u200B-\u200D\uFEFF]",
176
+ "",
177
+ text
178
+ )
179
+
180
+
181
+ return text
182
+
183
+
184
+
185
+ def clean_urdu(text):
186
+
187
+ if not text:
188
+ return ""
189
+
190
+
191
+ text = remove_unicode_artifacts(
192
+ text
193
+ )
194
+
195
+
196
+ # Normalize spaces only
197
+ text = re.sub(
198
+ r"\s+",
199
+ " ",
200
+ text
201
+ )
202
+
203
+
204
+ return text.strip()
205
+
206
+
207
+
208
+ def clean_roman(text):
209
+
210
+ if not text:
211
+ return ""
212
+
213
+
214
+ text = remove_unicode_artifacts(
215
+ text
216
+ )
217
+
218
+
219
+ # Uppercase
220
+ text = text.upper()
221
+
222
+
223
+ # Remove punctuation
224
+ text = re.sub(
225
+ r"[.,،؛:()\[\]{}]",
226
+ " ",
227
+ text
228
+ )
229
+
230
+
231
+ # Remove unwanted symbols
232
+ text = re.sub(
233
+ r"[^A-Z0-9\s]",
234
+ "",
235
+ text
236
+ )
237
+
238
+
239
+ # Normalize spaces
240
+ text = re.sub(
241
+ r"\s+",
242
+ " ",
243
+ text
244
+ )
245
+
246
+
247
+ return text.strip()
248
+
249
+
250
+
251
+ # ============================================================
252
+ # PIPE FORMAT CREATION
253
+ # ============================================================
254
+
255
+
256
+ def create_pipe_string(data, cleaner):
257
+
258
+ values = []
259
+
260
+
261
+ for field in FIELDS:
262
+
263
+ value = data.get(
264
+ field,
265
+ ""
266
+ )
267
+
268
+
269
+ value = cleaner(
270
+ value
271
+ )
272
+
273
+
274
+ values.append(
275
+ value
276
+ )
277
+
278
+
279
+ return "|".join(values)
280
+
281
+
282
+
283
+ # ============================================================
284
+ # PROCESS DATA
285
+ # ============================================================
286
+
287
+
288
+ def process_documents(documents):
289
+
290
+ rows = []
291
+
292
+
293
+ stats = {
294
+
295
+ "total": 0,
296
+ "success": 0,
297
+ "missing": 0,
298
+ "pipe_error": 0
299
+
300
+ }
301
+
302
+
303
+ print("Processing records...")
304
+
305
+
306
+ for doc in tqdm(documents):
307
+
308
+ stats["total"] += 1
309
+
310
+
311
+ try:
312
+
313
+
314
+ # Only successful API responses
315
+
316
+ if doc.get("message") != "Success":
317
+ continue
318
+
319
+
320
+ if doc.get("statusCode") != 200:
321
+ continue
322
+
323
+
324
+
325
+ urdu_data = doc.get(
326
+ "REQUEST_BODY",
327
+ {}
328
+ )
329
+
330
+
331
+ roman_data = doc.get(
332
+ "data",
333
+ {}
334
+ )
335
+
336
+
337
+
338
+ if not urdu_data or not roman_data:
339
+
340
+ stats["missing"] += 1
341
+ continue
342
+
343
+
344
+
345
+ urdu_text = create_pipe_string(
346
+ urdu_data,
347
+ clean_urdu
348
+ )
349
+
350
+
351
+ roman_text = create_pipe_string(
352
+ roman_data,
353
+ clean_roman
354
+ )
355
+
356
+
357
+
358
+ # Check empty fields
359
+
360
+ if (
361
+ "" in urdu_text.split("|")
362
+ or
363
+ "" in roman_text.split("|")
364
+ ):
365
+
366
+ stats["missing"] += 1
367
+ continue
368
+
369
+
370
+
371
+ # Pipe validation
372
+
373
+ if (
374
+ urdu_text.count("|")
375
+ !=
376
+ roman_text.count("|")
377
+ ):
378
+
379
+ stats["pipe_error"] += 1
380
+ continue
381
+
382
+
383
+
384
+ rows.append(
385
+ {
386
+ "urdu": urdu_text,
387
+ "roman": roman_text
388
+ }
389
+ )
390
+
391
+
392
+ stats["success"] += 1
393
+
394
+
395
+
396
+ except Exception:
397
+
398
+ continue
399
+
400
+
401
+
402
+ print("\nStatistics")
403
+ print("----------------")
404
+ for k,v in stats.items():
405
+ print(k, ":", v)
406
+
407
+
408
+
409
+ return rows
410
+
411
+
412
+
413
+ # ============================================================
414
+ # MAIN
415
+ # ============================================================
416
+
417
+
418
+ documents = extract_documents(
419
+ INPUT_FILE
420
+ )
421
+
422
+
423
+ print(
424
+ "Documents loaded:",
425
+ len(documents)
426
+ )
427
+
428
+
429
+
430
+ if LIMIT_ROWS:
431
+
432
+ documents = documents[:LIMIT_ROWS]
433
+
434
+
435
+
436
+ rows = process_documents(
437
+ documents
438
+ )
439
+
440
+
441
+
442
+ df = pd.DataFrame(
443
+ rows
444
+ )
445
+
446
+
447
+
448
+ print(
449
+ "\nRemoving duplicates..."
450
+ )
451
+
452
+
453
+ before = len(df)
454
+
455
+
456
+ df = df.drop_duplicates(
457
+ subset=[
458
+ "urdu",
459
+ "roman"
460
+ ]
461
+ )
462
+
463
+
464
+ print(
465
+ "Duplicates removed:",
466
+ before - len(df)
467
+ )
468
+
469
+
470
+
471
+ # Shuffle
472
+
473
+ df = df.sample(
474
+ frac=1,
475
+ random_state=42
476
+ ).reset_index(
477
+ drop=True
478
+ )
479
+
480
+
481
+
482
+ print(
483
+ "Final rows:",
484
+ len(df)
485
+ )
486
+
487
+
488
+
489
+ # Save
490
+
491
+ df.to_csv(
492
+ OUTPUT_FILE,
493
+ index=False,
494
+ encoding="utf-8-sig",
495
+ quoting=csv.QUOTE_ALL
496
+ )
497
+
498
+
499
+
500
+ print(
501
+ "\nSaved:",
502
+ OUTPUT_FILE
503
+ )