Der beste Weg, einen Namen aus einer Zeichenfolge zu extrahieren [geschlossen]Python

Python-Programme
Anonymous
 Der beste Weg, einen Namen aus einer Zeichenfolge zu extrahieren [geschlossen]

Post by Anonymous »

Ich habe eine Funktion, die eine Zeichenfolge als Eingabe verwendet und versucht, den Vor- und Nachnamen zu extrahieren. Es ist eine Kombination aus NER und Regex, um zu versuchen, die vorhandenen Namen zu extrahieren. Gibt es eine bessere oder effizientere Möglichkeit, dies zu tun? Es hat vor allem Probleme mit zusammengesetzten Namen, also Vorname + Zweitname + Nachname. Ein Benutzer könnte „John Michael Smith“ eingeben und der Code hat Schwierigkeiten herauszufinden, welcher Teil zu welchem ​​gehört.

Code: Select all

def extract_name(self, text: str):
all_names = []

# Method 1: Named Entity Recognition (NER)
try:
tokens = nltk.word_tokenize(text)
pos_tags = nltk.pos_tag(tokens)
named_entities = nltk.ne_chunk(pos_tags)

for chunk in named_entities:
if hasattr(chunk, 'label') and chunk.label() == 'PERSON':
name = ' '.join([token for token, pos in chunk.leaves()])
all_names.append(name)
except Exception as e:
logger.debug(f"NER extraction failed: {e}")

# Method 2: POS Tagging + Pattern Recognition
# Define action verbs to skip (must match before combining into names)
action_verbs_lower = {
'change', 'remove', 'update', 'delete', 'add', 'create',
'show', 'find', 'get', 'view', 'display', 'list',
'fetch', 'retrieve', 'pull', 'access', 'lookup', 'search', 'locate', 'bring',
'mark', 'set', 'record', 'edit', 'modify', 'alter', 'revise',
'erase', 'drop', 'register', 'enroll'
}

try:
tokens = nltk.word_tokenize(text)
pos_tags = nltk.pos_tag(tokens)

i = 0
while i < len(pos_tags):
if pos_tags[i][1] == 'NNP':
# Skip if this word is an action verb
if pos_tags[i][0].lower() in action_verbs_lower:
i += 1
continue

name_parts = [pos_tags[i][0]]
j = i + 1
while j < len(pos_tags) and pos_tags[j][1] == 'NNP':
# Skip action verbs even in the middle of proper noun sequences
if pos_tags[j][0].lower() not in action_verbs_lower:
name_parts.append(pos_tags[j][0])
j += 1

# Only add if we have actual name parts (not just action verbs)
if len(name_parts) >= 1:
all_names.append(' '.join(name_parts))
i = j
else:
i += 1
except Exception as e:
logger.debug(f"POS extraction failed: {e}")

# Method 3: Regex Pattern Matching
patterns = [
r'\b[A-Z][a-z]+\s+[A-Z][a-z]+\b',  # Standard Firstname Lastname
r'\b[A-Z][a-z]+\b',  # Single capitalized name
]

for pattern in patterns:
matches = re.findall(pattern, text)
# Filter out action verbs from regex matches
for match in matches:
words = match.split()
# Only add if no word in the match is an action verb
if not any(word.lower() in action_verbs_lower for word in words):
all_names.append(match)

# Filter out common false positives (action verbs and system words)
false_positives = {
# Action verbs
'Change', 'Remove', 'Update', 'Delete', 'Add', 'Create',
'Show', 'Find', 'Get', 'View', 'Display', 'List',
'Fetch', 'Retrieve', 'Pull', 'Access', 'Lookup', 'Search', 'Locate', 'Bring',
'Mark', 'Set', 'Record', 'Edit', 'Modify', 'Alter', 'Revise',
'Erase', 'Drop', 'Register', 'Enroll',
}
filtered_names = []

for name in all_names:
if name not in filtered_names and not any(fp in name for fp in false_positives):
filtered_names.append(name)

# Use voting/frequency to determine most likely name
if filtered_names:
name_counts = Counter(filtered_names)
most_common = name_counts.most_common(1)[0][0]
confidence = name_counts[most_common] / len(all_names) if all_names else 0
return most_common, confidence, filtered_names

return None, 0.0, []

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post