网页爬虫正则提取邮箱失败求助(电话提取功能正常)
解决方案:修复邮箱提取问题
问题根源分析
你的邮箱提取失败主要有两个核心原因:
- 正则表达式转义错误:你使用的
"\b..."是普通字符串,其中\b会被Python解析为退格符,而非正则表达式的单词边界。 - 网页邮箱的存在形式多样:很多网站不会直接把邮箱明文放在文本节点中,而是藏在
mailto:链接的属性里,或者用HTML实体编码、JavaScript动态生成。
具体修复步骤
1. 修正正则表达式
使用原始字符串定义正则(前缀r),避免转义冲突,同时修正字符类的错误:
# 修正后的邮箱正则:用原始字符串,去掉多余的|符号 mail_regex = r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,7}\b"
2. 提取多种形式的邮箱
除了匹配文本节点,还要处理mailto:链接、HTML编码的邮箱:
修改后的完整代码
import requests from bs4 import BeautifulSoup import re from html import unescape def extract_contact_info(url): address_t = [] phone_num_t = [] email_t = [] # 发送请求 response = requests.get(url) soup = BeautifulSoup(response.content, "html.parser") # 提取电话号码 phone_regex = r"(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}" phone_matches = soup.find_all(string=re.compile(phone_regex)) if phone_matches: phone_num_t.extend([match.strip() for match in phone_matches]) print("找到电话号码:", phone_num_t) else: print("未找到电话号码") # 提取邮箱:处理三种情况 mail_regex = r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,7}\b" # 情况1:匹配文本节点中的明文邮箱 text_matches = soup.find_all(string=re.compile(mail_regex)) email_t.extend([match.strip() for match in text_matches]) # 情况2:提取mailto链接中的邮箱 mailto_links = soup.find_all("a", href=re.compile(r"^mailto:")) for link in mailto_links: email = link["href"].replace("mailto:", "").strip() # 解码可能的HTML实体 email = unescape(email) if re.match(mail_regex, email): email_t.append(email) # 情况3:解码HTML实体后匹配(处理编码的邮箱) all_text = soup.get_text() decoded_text = unescape(all_text) encoded_matches = re.findall(mail_regex, decoded_text) email_t.extend([match.strip() for match in encoded_matches]) # 去重 email_t = list(set(email_t)) if email_t: print("找到邮箱:", email_t) else: print("未找到邮箱") return address_t, phone_num_t, email_t # 测试目标网站 extract_contact_info('https://www.zimmermanfinancialgroup.com/about') extract_contact_info('https://www.benefitexperts.com/about-us/')
3. 处理动态加载的邮箱(可选)
如果上述方法仍无法提取,说明邮箱是通过JavaScript动态渲染的,此时需要使用浏览器渲染工具(如Selenium):
from selenium import webdriver from selenium.webdriver.common.by import By import time def extract_dynamic_email(url): driver = webdriver.Chrome() driver.get(url) time.sleep(2) # 等待页面加载 # 获取页面所有文本 page_text = driver.find_element(By.TAG_NAME, "body").text mail_regex = r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,7}\b" emails = re.findall(mail_regex, page_text) # 提取mailto链接 mailto_elements = driver.find_elements(By.CSS_SELECTOR, "a[href^='mailto:']") for elem in mailto_elements: email = elem.get_attribute("href").replace("mailto:", "").strip() emails.append(email) emails = list(set(emails)) print("动态页面找到邮箱:", emails) driver.quit() return emails
关键说明
- 原始字符串:使用
r""定义正则可以避免Python对反斜杠的自动转义,确保正则语法正确。 - 去重处理:同一邮箱可能在多个位置出现,用
list(set(email_t))去重。 - HTML实体解码:
html.unescape()可以把a这类编码转成正常字符,解决邮箱被编码的问题。 - 动态内容处理:如果网站用JS加载邮箱,必须用浏览器渲染工具获取完整页面内容。
内容的提问来源于stack exchange,提问作者anonymous13
相关产品推荐
相关产品推荐

