手工复制粘贴100个网站的邮箱电话花了整整一天,用Python正则写了20行代码跑了500个站只用了3分钟,提取出来的邮箱有效率达到97%,手工会漏掉将近三分之一的联系方式
做外贸客户开发的时候,老板甩过来一份500个潜在客户网站的Excel表格,要求两天内把每个网站的邮箱和电话整理出来。第一反应是打开网站→找到Contact Us页面→复制邮箱→粘贴到Excel→下一个,做了50个之后手已经开始抖了,而且发现很多网站的联系方式藏在页面底部、关于我们页面、甚至JS动态加载的元素里,肉眼找根本找不全。
后来写了一个Python脚本,requests发请求、正则匹配邮箱和电话、pandas输出Excel,20行代码跑完500个站不到3分钟。事后对比了一下手工提取和脚本提取的结果:手工提取漏掉了大约三分之一的联系方式,因为很多邮箱嵌在mailto链接里、藏在JavaScript变量中、或者写在页脚极小字号的位置,肉眼直接跳过了。
网站联系方式提取这件事,从手动到自动有四个层级:
| 层级 | 方式 | 适合数量 | 准确率 | 核心瓶颈 |
|---|---|---|---|---|
| 第一层 | 手工复制粘贴 | 10个以内 | 60-70% | 人眼会漏,尤其JS渲染的联系方式 |
| 第二层 | Chrome插件(Email Extractor等) | 单页面提取,批量靠手动翻页 | 80-90% | 不能批量输入URL列表自动跑 |
| 第三层 | Python脚本(requests+正则) | 几百到几千个 | 90-97% | JS动态渲染的页面抓不到 |
| 第四层 | Selenium/Playwright+正则 | 无上限 | 95-99% | 速度慢、资源消耗大 |
一、Chrome插件:零门槛,适合单页面快速提取
对于不懂代码、只需要偶尔提取几个网站联系方式的用户,Chrome插件是最快的入门方案。安装一个插件,打开目标网页,点一下插件图标,页面上所有的邮箱和电话号码自动列出来。
| 插件名称 | 免费额度 | 能提取什么 | 能否批量 | 适合场景 |
|---|---|---|---|---|
| Email Extractor | 完全免费 | 邮箱 | 不能 | 单页面快速提取 |
| Hunter.io | 25次/月 | 邮箱+域名关联 | 支持 | 按域名批量查找企业邮箱 |
| Snov.io | 50积分/月 | 邮箱+电话+社交账号 | 支持 | 外贸客户开发全流程 |
| Thunderbit | 有免费版 | AI识别邮箱+任意字段 | 支持 | 非技术用户批量采集 |
| 蜂邮采集助手 | 有免费版 | 邮箱(含隐藏邮箱) | 有限 | 国内网站邮箱采集 |
Chrome插件的优点是零门槛、即时可用,不需要装Python环境、不需要写代码。但局限也很明显:绝大多数免费插件只能单页面提取,你要处理500个网站就得手动打开500个网页、点500次插件按钮。部分付费插件(Hunter.io、Snov.io)支持按域名批量查找,但每月免费额度有限(25-50次),大批量使用需要付费。
另外要注意:Chrome插件提取的是页面渲染后的DOM内容,包括了JS动态加载的联系方式,这比单纯抓HTML源代码的覆盖率高。如果目标网站的联系方式是通过JS异步加载的(比如用Vue/React渲染的单页应用),Chrome插件能抓到,但单纯requests请求抓不到。
二、Python脚本:真正的批量提取,几百个站几分钟跑完
当网站数量超过20个,手工或插件方案就不现实了。Python脚本才是真正的批量提取方案——把URL列表放进Excel或txt文件,脚本自动逐个访问、提取联系方式、输出结果。
核心正则表达式:邮箱和电话的匹配模式
提取联系方式的核心是正则表达式。邮箱的格式相对固定(xxx@xxx.xxx),电话的格式就五花八门了——国内座机带区号、手机号11位、400电话、带国际区号的、用括号或横线分隔的,一个正则表达式很难全覆盖。

联系方式提取常用的正则表达式:
| 提取目标 | 正则表达式 | 匹配示例 |
|---|---|---|
| 通用邮箱 | [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,} | info@example.com |
| 中国大陆手机号 | 1[3-9]\d{9} | 13812345678 |
| 座机(带区号) | 0\d{2,3}[-\s]?\d{7,8} | 010-12345678 |
| 400电话 | 400[-\s]?\d{3}[-\s]?\d{4} | 400-888-9999 |
| QQ号码 | [1-9]\d{4,10} | 123456789 |
| mailto链接中的邮箱 | mailto:([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}) | <a href="mailto:info@abc.com"> |
完整Python脚本:从URL列表批量提取邮箱和电话
Python批量提取脚本(可直接复制使用)
import requestsimport reimport pandas as pdfrom urllib.parse import urlparse# 读取URL列表(Excel文件,第一列为网址)df_urls = pd.read_excel('urls.xlsx', header=None)urls = df_urls[0].tolist()# 正则表达式EMAIL_PATTERN = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'PHONE_PATTERN = r'1[3-9]\d{9}'TEL_PATTERN = r'0\d{2,3}[-\s]?\d{7,8}'QQ_PATTERN = r'[1-9]\d{4,10}'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}results = []for url in urls:url = str(url).strip()if not url.startswith('http'):url = 'https://' + urldomain = urlparse(url).netloctry:resp = requests.get(url, headers=headers, timeout=10)html = resp.textemails = list(set(re.findall(EMAIL_PATTERN, html)))phones = list(set(re.findall(PHONE_PATTERN, html)))tels = list(set(re.findall(TEL_PATTERN, html)))qqs = list(set(re.findall(QQ_PATTERN, html)))results.append({'网站': url,'域名': domain,'邮箱': '; '.join(emails) if emails else '未找到','手机号': '; '.join(phones) if phones else '未找到','座机': '; '.join(tels) if tels else '未找到','QQ': '; '.join(qqs) if qqs else '未找到'})print(f'✅ {domain}')except Exception as e:results.append({'网站': url, '域名': domain,'邮箱': f'访问失败: {str(e)[:50]}','手机号': '', '座机': '', 'QQ': ''})print(f'❌ {domain}: {str(e)[:50]}')# 导出结果df_result = pd.DataFrame(results)df_result.to_excel('联系方式提取结果.xlsx', index=False)print(f'\n提取完成,共处理 {len(results)} 个网站')这个脚本的局限在于:只能提取HTML源代码中的联系方式。如果目标网站用React/Vue等前端框架渲染,联系方式是通过JS动态生成的,requests拿到的HTML里就没有。另外有些网站把邮箱写成了图片、或者用JS做了简单的混淆(比如把@替换成了#),正则也匹配不到。
三、Selenium/Playwright方案:专治JS渲染和反爬网站
当requests方案遇到JS渲染的网站(现在越来越多),就需要出动无头浏览器了。Selenium或Playwright可以模拟真实浏览器打开网页、等待JS执行完毕、再提取页面内容。这种方案能覆盖99%的网站,代价是速度慢——每个页面要等浏览器渲染完,500个站可能要跑十几分钟到半小时。
Playwright方案:处理JS渲染的网页(需要 pip install playwright)
from playwright.sync_api import sync_playwrightimport reEMAIL_PATTERN = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'def extract_from_page(url):with sync_playwright() as p:browser = p.chromium.launch(headless=True)page = browser.new_page()try:page.goto(url, timeout=15000, wait_until='domcontentloaded')# 等待页面完全渲染page.wait_for_timeout(2000)html = page.content()emails = list(set(re.findall(EMAIL_PATTERN, html)))return emailsfinally:browser.close()# 使用方式和requests方案一样,逐个传入URL即可emails = extract_from_page('https://example.com/contact')print(emails)两种方案的取舍很清晰:requests方案快但覆盖率约85-90%,Playwright方案慢但覆盖率95-99%。实际操作中可以先跑requests方案快速筛一遍,然后把"未找到"的网站再跑Playwright补漏,兼顾速度和覆盖率。
四、提取完还要做三步处理,直接拿来用大概率会出问题
正则表达式是"宁可错杀一千不放过一个"的逻辑,会匹配到很多不是联系方式的邮箱。比如example@domain.com、test@test.com、noreply@xxx.com这类测试和系统邮箱,以及CDN路径中的@符号(user@host格式的URL)。提取完后至少要过滤掉:包含example/test/noreply/admin/info@domain的邮箱、重复的邮箱(同一个邮箱出现在多个页面)、格式正确但明显不是联系人的邮箱。

blacklist = ['example', 'test', 'noreply', 'admin', 'support', 'info']
valid_emails = [e for e in emails if not any(b in e.lower() for b in blacklist)]
网站上的邮箱不一定是活跃的——可能是离职员工的、过期的、或者干脆是乱写的。提取出来的邮箱需要做SMTP验证(检查邮箱服务器是否存在、该用户名是否有效)。可以用verify-email库或调用第三方API(Hunter.io、ZeroBounce、NeverBounce)批量验证。但要注意:频繁的SMTP验证请求可能被目标邮件服务器封IP。
提取出500个邮箱但不知道哪个邮箱对应哪个网站、哪个部门、哪个联系人,后续没法用。提取脚本应该输出"网站URL→域名→提取到的邮箱→提取位置(Contact页面还是首页底部)→邮箱前缀推测的部门(sales@/hr@/info@)"。如果能进一步从页面提取公司名称和联系人姓名,价值翻倍。
五、四个提取时容易遇到的坑,每个都可能让你白忙一场
邮箱写在图片里
有些网站为了防爬虫,把邮箱做成图片。正则匹配不到,需要OCR识别。但OCR准确率有限,尤其是小字号、花体字。这种网站不多,遇到了就当缘分不够。
JS混淆邮箱地址
邮箱被写成'user'+'@'+'domain.com'或base64编码。正则匹配不到原始格式。Playwright渲染后能看到最终结果,但requests抓到的还是混淆版本。
Cloudflare/反爬拦截

访问频率太高被目标网站识别为爬虫,返回403或Cloudflare验证页面。解决方法:加延时(time.sleep 1-3秒)、换User-Agent、用代理IP轮换。
编码问题导致中文乱码
有些网站用GBK编码,requests默认UTF-8解码会乱码。提取前先检测编码:resp.apparent_encoding,然后resp.encoding正确设置。
六、合规提醒:批量提取联系方式的法律边界
批量提取网站联系方式这件事,技术门槛不高,但法律风险不低。几个关键的合规边界需要心里有数:
- 只提取网站公开显示的联系方式,不要尝试绕过登录验证、不要攻击网站漏洞、不要从数据库直接拖数据
- 控制访问频率,高频爬取可能被认定为对目标网站的攻击行为(DDoS性质的访问)
- 遵守robots.txt,如果网站明确在robots.txt中禁止爬虫访问,应当遵守
- 提取的邮箱只能用于合法商业联系,不能用于群发垃圾邮件、不能转卖、不能用于诈骗
- 涉及欧盟用户的数据需遵守GDPR,中国大陆需遵守《个人信息保护法》
- 用于外贸客户开发时注意出口管制和制裁名单,部分国家的公司联系信息受到贸易管制
最后说两句
网站联系方式批量提取这件事,本质上是一个"正则匹配+批量访问+结果清洗"的流水线。技术本身不复杂,Python二十行代码就能搞定核心逻辑。真正拉开效率差距的是对提取结果的后处理——去重、过滤垃圾邮箱、验证有效性、关联网站上下文。很多人花一小时写提取脚本,然后花十分钟扫一眼结果就开始用,里面混了大量example@test.com和noreply@xxx.com,等于白忙。
选工具的策略也很简单:10个以内网站用Chrome插件点几下就行;50个以上必须写脚本;如果目标网站大多是React/Vue构建的现代网站,直接用Playwright方案,不要浪费时间在requests上调反爬。最后一定要记得:能提取出来不代表能用,不验证、不过滤、不关联上下文,提取出来的联系方式就是一堆垃圾数据。
核心要点:
- 10个以内网站用Chrome插件(Email Extractor免费、Hunter.io/Snov.io功能更全)
- 50个以上必须写Python脚本,requests+正则方案覆盖85-90%的网站
- JS渲染的网站用Playwright/Selenium无头浏览器,覆盖率95-99%但速度慢
- 邮箱正则:[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,};手机号:1[3-9]\d{9}
- 提取完必须做三步处理:去重过滤无效邮箱、SMTP验证有效性、关联原始网站上下文
- 注意合规边界:只提取公开信息、控制访问频率、遵守robots.txt、不群发垃圾邮件
- 效率技巧:先requests快速筛,未命中的再用Playwright补漏,兼顾速度和覆盖率
