我们需要判断文本中是否有手机号,并提取出手机号。 中国大陆的手机号规则: 1. 通常为11位数字。 2. 目前手机号段分配如下: - 移动号段:134(0-8)、135、136、137、138、139、147、148、150、151、152、157、158、159、172、178、182、183、184、187、188、195、198 - 联通号段:130、131、132、145、146、155、156、166、175、176、185、186 - 电信号段:133、149、153、173、177、180、181、189、190、191、193、199 - 虚拟运营商:170、171 3. 但是,我们通常只需要考虑前三位(或者前两位)来判断是否属于手机号段,另外还有一些号段是14x、16x、17x、18x、19x等。 注意:手机号可能出现在文本中的任何位置,可能与其他数字混合,所以我们需要用正则表达式来匹配。 考虑到手机号可能出现的情况: 1. 手机号可能是连续11位数字,但前后可能有其他字符(非数字),例如在文本中单独出现,或者被空格、标点等隔开。 2. 手机号中间不应该出现空格、连字符等(因为题目要求的是手机号,一般我们认为是连续11位数字),但有时用户可能会用分隔符,比如写成“135-1234-5678”或“135 1234 5678”。不过,按照标准,我们通常认为连续11位数字,或者有时会加上分隔符,但题目没有明确说明,所以这里我们按照连续11位数字来匹配,如果用户使用了分隔符,那么可能就不匹配了。
所以,我们分两步: 1. 用正则表达式匹配所有连续的11位数字,并且要求是以1开头的。 2. 检查每个匹配到的11位数字的前三位是否在有效的前三位集合中。 这样,我们就能准确地提取手机号。 另外,为了避免匹配到其他长数字中的11位(比如身份证号中可能包含11位连续数字),我们可以在匹配时加上边界限制(使用\b表示单词边界)。 但是,手机号在文本中可能出现的位置,前后可能不是空格,可能是标点,所以我们也可以使用非数字边界:即匹配前后不是数字的位置。我们可以用负向零宽断言,但这样写正则表达式会复杂。我们可以在匹配后,检查匹配到的字符串前后字符是否为非数字(或者开头和结尾),但正则表达式本身可以用\b来匹配单词边界,因为数字和汉字、字母、标点之间都有边界。 因此,正则表达式可以写为:r'\b1\d{10}\b',但是这样会匹配所有1开头的11位数字,然后我们再过滤前三位。 但是,注意:如果手机号在文本中紧跟着一个英文单词,那么\b可能不起作用,因为\b是单词边界,而数字和字母之间被认为是边界。所以,我们也可以使用:r'(?<!\d)1\d{10}(?!\d)',这表示前后不能是数字。这样更好。 所以,我们使用正则表达式:`r'(?<!\d)(1\d{10})(?!\d)'` 来匹配前后不是数字的1开头的11位数字。 步骤: 1. 导入re模块 2. 定义有效的前三位集合(见上面) 3. 使用re.findall找到所有匹配的字符串 4. 遍历匹配到的字符串列表,检查前三位是否在有效集合中,如果在,则加入结果列表。 注意:有可能同一个手机号在文本中出现多次,我们都要提取出来。 函数设计: 输入:文本字符串 输出:返回两个值:一个布尔值(表示是否有手机号),一个列表(包含所有提取到的手机号) 或者,我们可以直接返回提取到的手机号列表,然后通过判断列表是否为空来确定是否有手机号。但是题目要求判断是否有,并提取,所以我们可以返回一个元组:(has_phone, phone_list) 但是,也可以直接返回列表,然后由调用者判断列表是否为空。这里按照要求,返回两个值
import redef find_mobile_numbers(text):"""判断文本中是否有手机号,并提取所有手机号。参数:text (str): 待检查的文本返回:tuple: (是否存在手机号, 手机号列表)"""# 中国手机号正则表达式(匹配11位数字,以常见号段开头)pattern = r'(?<!\d)(1(?:3[0-9]|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8})(?!\d)'# 查找所有匹配的手机号mobile_numbers = re.findall(pattern, text)# 返回结果(布尔值和手机号列表)return (bool(mobile_numbers), mobile_numbers)# 测试示例
if __name__ == "__main__":test_text = """我的联系方式是:13800138000,备用号码是18912345678。无效号码:12345678901(首位错误)、1380013800(10位)、客服电话:10086,座机:0755-12345678。新号码:17612345678,虚拟运营商:17012345678"""has_mobile, numbers = find_mobile_numbers(test_text)print("是否存在手机号:", has_mobile)print("提取到的手机号:", numbers)
函数说明:
-
正则表达式解析:
-
(?<!\d)
:确保前面不是数字(防止匹配更长数字中的部分) -
(1...)
:手机号以1开头 -
(?:3[0-9]|...)
:匹配第二位和第三位(常见号段) -
\d{8}
:匹配剩余8位数字 -
(?!\d)
:确保后面不是数字(防止匹配更长数字中的部分
-
-
运行结果:
是否存在手机号: True
提取到的手机号: ['13800138000', '18912345678', '17612345678', '17012345678']进程已结束,退出代码为 0