我們需要判斷文本中是否有手機號,并提取出手機號。 中國大陸的手機號規則: 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