数据识别概述

数据识别场景

数据识别确实可以分为两种主要类型:直接识别和间接识别(或称为从文本中发现)。下面我将详细解释这两种类型:

  1. 直接识别

    • 定义:直接识别是指直接判断某个数据是否符合特定的标准或条件。
    • 应用场景:例如,判断一个数字是否是偶数,或者判断一个字符串是否是有效的电子邮件地址。
    • 方法:通常使用规则或算法直接对数据进行检查,如使用正则表达式来验证电子邮件地址的格式。
  2. 间接识别(从文本中发现)

    • 定义:间接识别是指从一段文本中提取出符合特定条件的数据。
    • 应用场景:例如,从一篇新闻文章中提取出所有的日期,或者从社交媒体帖子中识别出所有的地理位置信息。
    • 方法:通常涉及自然语言处理(NLP)技术,如命名实体识别(NER)、关键词提取等。这些技术可以帮助从文本中识别和提取出特定的数据类型。

这两种方法在实际应用中常常结合使用,以提高数据识别的准确性和效率。例如,在处理大量文本数据时,可以先使用间接识别方法提取出潜在的相关数据,然后再使用直接识别方法对这些数据进行进一步的验证和分类。


直接识别和间接识别在代码处理方式上有所不同,以python代码识别email为例:

对于直接识别,正则表达式可以用 ^$ 限定正则的边界,保证正则表达式是完全匹配而不是匹配一部分,同时判断逻辑使用: re.match(PATTERN, TARGET) is not None

import re

def is_valid_email(email):
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None

# 示例
email = "example@example.com"
print(is_valid_email(email))  # 输出: True

对于间接识别,正则表达式不能使用^$,同时判断逻辑使用re.findall(PATTERN, TARGET) 返回所有匹配的结果

import re

def extract_emails(text):
    pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
    return re.findall(pattern, text)

# 示例
text = "Contact us at example@example.com or support@example.com"
print(extract_emails(text))  # 输出: ['example@example.com', 'support@example.com']

奇技淫巧

1. 限定识别对象的边界

例如,我要查找一个6位数号码,而实际数据中有超过6位数的号码,如果处理不当,会把长串数字中的6为子串提取出来,这显然是不对的。

def extract_bank_cards(text):
    pattern = '\d{6}'
    return re.findall(pattern, text)

# 示例
text = "Bank cards: 123456, 1234567890123456, 1234567890123457"
print(extract_bank_cards(text))  # 输出: ['123456', '123456', '789012', '123456', '789012']

如何避免呢,使用正则的负向断言

这个正则表达式 (?<!\d)\d{6}(?!\d) 的含义是匹配一个六位数字,并且这个六位数字的前后都不能紧跟着其他数字。

让我们分解这个正则表达式:

  1. (?<!\d) 是一个负向前瞻断言(negative lookbehind assertion),表示在当前位置之前不能有数字。
  2. \d{6} 匹配六个连续的数字。
  3. (?!\d) 是一个负向后瞻断言(negative lookahead assertion),表示在当前位置之后不能有数字。

假设我们有以下文本:

123456 7890123 1234567 123456

使用正则表达式 (?<!\d)\d{6}(?!\d) 进行匹配:

import re

text = "123456 7890123 1234567 123456"
pattern = r'(?<!\d)\d{6}(?!\d)'
matches = re.findall(pattern, text)
print(matches)  # 输出: ['123456', '123456']

在这个例子中,正则表达式匹配了两个 “123456”,因为它们的前后都没有紧跟着其他数字。而 “7890123” 和 “1234567” 没有被匹配,因为它们的前后都有其他数字。

注意:

  • 负向前瞻和负向后瞻断言不消耗字符,它们只检查特定条件是否满足。
  • 这个正则表达式适用于匹配独立的六位数字,而不包括其他数字。

通过使用这种正则表达式,可以精确地匹配特定格式的数字,避免匹配到不符合条件的数字序列。

2. 非捕获组

当写了一个非常复杂的正则表达式,里面用括号定义了很多捕获组(capturing group),直接使用findall可能捕获返回期望的结果。

import re

def extract_url(text):
    pattern = 'https?://([\da-zA-Z_\.]+)(:\d+)?((/[a-zA-Z\d\.]+)+)?'
    return re.findall(pattern, text)

# 示例
text = "url地址为:http://www.baidu.com:9090/hello/kugou"
print(extract_url(text))  # 输出: [('www.baidu.com', ':9090', '/hello/kugou', '/kugou')]

此时你需要将正则中的捕获组改成非捕获组,即把(...) 改写成 (?:...)

import re

def extract_url(text):
    pattern = r'https?://(?:[\da-zA-Z_\.]+)(?::\d+)?(?:(?:/[a-zA-Z\d\.]+)+)?'
    return re.findall(pattern, text)

# 示例
text = "url地址为:http://www.baidu.com:9090/hello/kugou"
print(extract_url(text))  # 输出: ['http://www.baidu.com:9090/hello/kugou']
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颹蕭蕭

白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值