Python正则爬取网站手机号异常:本地正常线上仅获未知数字
看起来你遇到的情况挺典型的——本地测正则好好的,一爬网站就跑偏,还拿到莫名其妙的数字。我碰到过好几个类似的案例,大概率是这几个原因,咱们一个个排查:
1. 动态内容渲染的坑
你用requests库直接请求网页,只能拿到静态HTML源码,但很多现代网站会用JavaScript动态加载联系方式(比如滚动到特定位置才加载、或者通过异步接口获取)。你本地测试的时候,可能是直接复制了浏览器里已经渲染完成的完整页面内容,自然能匹配到目标号码;但爬虫拿到的是未渲染的原始代码,里面根本没目标号码,反而把页面里的无关数字(比如年份、页面元素ID、参数值)当成匹配结果抓了——1999、8211大概率就是这类内容。
解决办法:
改用支持JS渲染的工具,模拟浏览器加载完整页面后再提取内容。比如用selenium的示例代码:
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import re links = [ 'http://www.latamcham.org/contact-us/', 'http://www.cityscape.com.sg/?page_id=37' ] def FetchPhone(site): # 初始化浏览器驱动(需提前对应浏览器版本安装驱动) driver = webdriver.Chrome() driver.get(site) # 等待页面核心内容加载完成,这里以等待body元素为例 WebDriverWait(driver, 10).until( EC.presence_of_element_located(('tag name', 'body')) ) # 获取渲染后的完整页面源码 page_source = driver.page_source driver.quit() # 替换成你的正则匹配逻辑 phone_pattern = re.compile(r'你的优化后正则表达式') phones = phone_pattern.findall(page_source) return phones
2. 正则表达式的匹配范围太宽泛
你本地测试的样例可能只有目标电话号码,但实际网页里有大量其他数字串(比如文章年份、产品编号、URL参数)刚好符合你的正则规则。比如如果你的正则是\d{4},那1999、8211这类4位数字就会被误匹配。
解决办法:
给正则增加上下文约束,匹配符合电话号码格式的特征(比如区号、连字符、括号、前缀标识)。举几个通用的电话号码正则示例:
- 匹配带国际区号的号码:
r'\+?\d{1,3}[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}' - 匹配本地固定电话/手机号(可根据目标地区调整):
r'\(?\d{3}\)?[-.\s]?\d{7,8}'
另外,建议你把爬取到的原始页面源码保存到本地文件(用res.text写入文件),打开看看里面到底有没有目标号码,以及1999、8211是从哪里来的——这样能精准定位正则的问题。
3. 网页编码解析错误
有时候requests默认的编码和网页实际编码不一致,导致页面内容乱码,正则匹配失效,反而抓到乱码里的零散数字。
解决办法:
让requests自动检测并适配网页编码:
res = requests.get(site) res.encoding = res.apparent_encoding # 自动识别正确编码 page_content = res.text
最后,优先排查页面内容是否一致:把爬虫拿到的源码和你本地测试用的内容对比,如果不一样,基本就是动态加载的问题;如果内容一致但匹配不到,就重点优化正则表达式。
内容的提问来源于stack exchange,提问作者SIM

