用正则表达式和pyperclip实现号码邮箱的提取

本文介绍如何使用Python的正则表达式从文本中提取电话号码和电子邮件地址,并将结果复制到剪贴板。通过逐步解析正则表达式的语法,演示了如何创建复杂规则并组织代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

详细教程见《Automate the boring stuff with Python》。

本文是正则表达式的一个简答应用,配合pyperclip最终实现:当有文本复制到剪贴板后,运行程序,便可打印出其中包含的电话号码和邮箱。

正则表达式的基本语法

1.步骤
想要识别出一段文本中的号码,当然可以写个函数。号码一般是有规律的,比如415-555-4242(美国),第一部分是地区号,后面接3个数字,再接4个数字。如果定义一个函数,先检查这串字符长度是不是12,然后用一系列 if 和 for 循环检查1、2、3位是不是数字,4位是不是连字符,5,6,7位是不是数字......也行,但是函数冗长,显得很笨拙。

既然号码是有规律的,那么只要能和计算机约定这种规律,让它也按照我们认识到的规律去查找不就行了?因此,正则表达式,可以理解为“约定某种规则”的表达式。它的英文名也确实如此,“Regular Expression”

假定用“\d”代表一个从0-9的数字(digit),那么上面的号码就可以表示为“\d\d\d-\d\d\d-\d\d\d\d“

在Python中需要先引入 re 模块,然后使用其中的 compile 方法约定这种规则。
import re
phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')

(Regex是正则表达式的缩写,r' '代表raw string原始字符串,可以无视字符串中的转义符)

对正则表达式使用search方法,会自动寻找输入文本中匹配的对象,创造出一个match对象。这里把它赋给“mo”。
mo = phoneNumRegex.search('My number is 415-555-4242.')

注意mo不是一个变量,而是个match对象,直接打印是不能看到结果的,通过group方法才可以看到结果。

>>>print('Phone number found: ' + mo.group())
Phone number found: 415-555-4242

综上,创建一个regex匹配有四步:

①引入re模块。

②用re模块里的compile函数,创建一个regex对象。

③把文本传递给regex对象的search方法,返回一个match对象。
④通过match对象的group方法访问结果。

2.括号分组
号码是由几部分组成的,在正则表达式中也能通过“()”约定好分组,然后在group()方法中输入对应的编号,访问对应的结果。
>>>phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)')
>>>mo = phoneNumRegex.search('My number is 415-555-4242.')
>>>mo.group(1)
'415'
>>>mo.group(2)
'555-4242'
>>>mo.group(0)
'415-555-4242'
>>>mo.group()
'415-555-4242'

想看到完整的分组结果,可以用groups方法。

>>>mo.groups()
('415','555-4242')
>>>areaCode,mainNumber = mo.groups()
>>>print(areaCode)
415
>>>print(mainNumber)
555-4242

groups方法返回一个元组(tuple),所以可以把其中的两个值分别赋给两个变量areaCode和mainNumber。

3.其它约定
号码的地区号是可有可无的,有的部分可能还更长一点,邮箱是由数字和字母组成的,又该如何在raw string中约定好这种规则呢?
以下是其它约定。
  • ? 放在一组括号的后面,表示这一部分可有可无。
  • * 表示这一部分可以有任意个。
  • + 表示这一部分有一个或多个。
  • {n} 表示这一部分出现了n次。
  • {n,m} 表示这一部分出现了n到m次。
  • 上面几种方式默认查找符合条件的最长的一串字符,如果要最短的,再加上一个 ?
  • ^xx 表示字符串必须以xx开头
  • xx$ 表示字符串必须以xx结尾
  • . 表示任意一个字符,除了空行字符。(.at 可以匹配cat,hat,rat,匹配flat的话结果是lat)
  • \d 代表数字,\s 代表空格,\w 代表字母。(如果大写\D\S\W,就代表除了数字、空格、字母的任意字符)
  • [abc] 代表方括号中出现的任意字符。(如果写成[a-zA-z]就表示a到z、A到Z的任意字母,所以[0-9]也可以表示数字)
  • [^abc] 代表任何不是abc的字符。
  • 如果要表示括号,句号本身,加个反斜杠。如:\(xx\)表示(xx)
  • 竖号又称pipe,“|”,表示“或”,a|b 表示找到两者之一即可。
4.组织复杂的正则表达式
约定的规则一般是很长的,可以用以下方式实现分行加注释。后面的re.VERBOSE开启verbose模式,会自动忽视raw string中的空格和注释。

phoneRegex = re.compile(r'''(
    (\d{3}|\(\d{3}\))?                  #地区号
    (\s|-\.)?                           #连字符
    (\d{3})                             #三个数字
    (\s|-\.)                            #连字符
    (\d{4})                             #四个数字
    (\s*(ext|x|ext.)\s*(\d{2,5}))?      #拓展号码
    )''',re.VERBOSE)

开始吧

宏观上思考,提取号码和邮箱分为以下三个步骤:
  1. 从剪贴板上获取文本
  2. 找到文本中所有的号码和邮箱
  3. 把它们粘贴到剪贴板上
那么具体代码的实现,应该包含这些:
  1. 使用pyperclip模块完成字符串的拷贝和粘贴。
  2. 创建两个正则表达式,一个用于匹配号码,一个用于匹配邮箱。
  3. 找出两个正则表达式的所有匹配结果。
  4. 把所有结果工整排版,放进一个字符串里,方便粘贴。
  5. 如果没有找到匹配的话,展示某些信息。

代码如下:(注意:①安装pyperclip模块②“-”.join方法用于以“-”连字符把几串字符连接起来。)

#! python3
# phoneAndEmail.py - Finds phone numbers and email addresses on the clipboard.

import pyperclip,re

#创建两个正则表达式
phoneRegex = re.compile(r'''(
    (\d{3}|\(\d{3}\))?                  #地区号
    (\s|-\.)?                           #连字符
    (\d{3})                             #三个数字
    (\s|-\.)                            #连字符
    (\d{4})                             #四个数字
    (\s*(ext|x|ext.)\s*(\d{2,5}))?      #拓展号码
    )''',re.VERBOSE)

emailRegex = re.compile(r'''(
    [a-zA-Z0-9.%+-]+                    #用户名
    @                                   #@符号
    [a-zA-z0-9.-]+                      #域名
    (\.[a-zA-z]{2,4})                   #.com等等
    )''',re.VERBOSE)


#找出文本中的匹配
text = str(pyperclip.paste())
matches = []
for groups in phoneRegex.findall(text):
    phoneNum = '-'.join([groups[1],groups[3],groups[5]])
    if groups[8] != '':
        phoneNum += 'x' + groups[8]
    matches.append(phoneNum)

for groups in emailRegex.findall(text):
    matches.append(groups[0])


#把结果拷贝到剪贴板上
if len(matches) > 0:
    pyperclip.copy('\n'.join(matches))
    print('Copied to clipboard:')
    print('\n'.join(matches))
else:
    print('No phone numbers or email addresses found.')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值