如何为 B2B 潜在客户生成开发可靠的联系人抓取器
让我们深入了解一下!
什么是接触式刮刀?
联系人搜索器是从公开的在线资源中自动提取联系人信息(如电子邮件地址、电话号码、姓名和公司详情)的工具。这些来源包括公司目录、社交媒体平台、评论网站和企业列表。使用联系人搜刮工具的主要好处是,它可以自动收集潜在客户,使企业无需手动操作即可扩大推广范围。
联系人抓取工具在 B2B 线索开发中尤其有价值,因为它们能帮助企业锁定特定行业的决策者,而这对成功的营销与销售外联至关重要。不过,抓取数据并不只是从网站下载信息那么简单。许多站点会使用反爬虫措施来阻止自动化抓取,而要应对这些挑战,就需要一个设计良好的抓取工具。
了解触点搜索的基础知识
在深入探讨制造触点刮研器的技术问题之前,了解刮研器的基本组成部分非常重要:
- 数据来源:提取联系人数据的网站或在线平台。B2B 潜在客户生成的热门来源包括公司目录、LinkedIn 等社交媒体网站、Yelp 等点评网站以及 Crunchbase 等利基数据库。
- 扫描工具:用于自动执行搜索过程的软件或脚本。 扫描工具 向目标网站发送请求,并解析返回的 HTML 数据,以提取所需的联系信息。
- 数据解析:获取数据后,必须对其进行解析和结构化处理,以便使用。解析包括识别网页上包含联系信息(如电子邮件地址、姓名或电话号码)的特定元素。
- 反僵尸措施:许多网站都采用了验证码、JavaScript 渲染等反僵尸技术。 IP 屏蔽 以防止自动刮擦。克服这些措施是制造可靠刮擦器时面临的主要挑战。
打造可靠触点刮刀的分步指南
联系人搜索有两种主要方法:基于代码和无代码。您可以根据自己的技术能力和需求,选择最适合自己的方法。
步骤 1:为联系人搜索选择正确的数据源
建立可靠的联系人搜索器的第一步是选择正确的数据源。根据您的潜在客户生成目标,最佳数据源会有所不同。以下是一些常见的 B2B 潜在客户生成来源:
- LinkedIn:LinkedIn 是一个功能强大的专业网络平台,它允许您根据职位名称、公司名称、行业等搜索数据。它是瞄准组织中特定决策者的理想工具。查看我的文章 最好的 LinkedIn 搜索引擎.
- Crunchbase:Crunchbase 是一个针对科技公司、初创企业和投资者的流行数据库。它是查找高增长公司决策者及其联系信息的重要来源。您还可以使用 Bright Data 的 Crunchbase Scraper 或 一个Apify.
- 天使列表:AngelList 是另一种识别初创企业创始人和关键员工的资源,尤其适用于种子投资、合作或招聘。
- Yelp 和黄页:这些本地企业名录非常适合查找中小型企业 (SMB) 的联系信息,尤其是在特定的地理区域。
- Trustpilot 和 Glassdoor:这些平台提供了对公司评论的宝贵见解,可用于寻找人力资源专业人员、招聘线索或客户见解。
步骤 2:克服反机器人措施
搜索联系人数据的主要障碍之一是应对反僵尸措施。网站通常会阻止或限制刮擦,以保护其数据并防止服务器过载。一些标准的反僵尸技术包括
- 验证码:这是需要人工干预才能解决的谜题式挑战。它们用于防止机器人访问网站。
- IP 屏蔽:许多网站会阻止在短时间内发送过多请求的 IP 地址。
- JavaScript 渲染:有些网站在很大程度上依赖 JavaScript 来加载内容,因此简单的刮擦工具很难检索到数据。
要克服这些挑战,你需要使用更高级的抓取工具,以绕过这些反爬措施。例如,有些工具会使用轮换代理来避免 IP 封禁,而另一些则提供无头浏览器,可以执行 JavaScript 来渲染内容,就像真实用户在浏览网站一样。
提示:在这方面,使用 Bright Data 这样的工具可以改变游戏规则。它提供旋转代理、无头浏览器支持和 JavaScript 渲染等功能,让您可以可靠地搜索数据而不会被阻止。
步骤 3:使用 Python 构建基于代码的搜索器
如果你擅长编码,Python 是构建网络刮擦工具最常用的语言之一。它拥有强大的库,如 requests 和 BeautifulSoup 来获取和解析网页内容。下面是一个综合示例,说明如何使用 Python 和 Bright Data 代理构建一个 scraper。
步骤 3.1:设置 Python 环境
- 如果尚未安装 Python,请在计算机上安装。从 python.org.
- 运行以下命令安装必要的程序库:
pip install requests
pip install beautifulsoup4
pip install lxml
步骤 3.2:配置 Bright 数据代理
首先,您需要设置 Bright Data 代理凭证。登录您的 Bright Data 账户 并从区域概览中获取代理证书:
- Host:
brd.superproxy.io - 港口:
33335(或您的特定端口) - 用户名:您的 Bright Data 用户名(例如、
brd-customer-[ACCOUNT_ID]-zone-[ZONE_NAME] (区域名称)) - 密码: 您的 Bright Data 代理区密码
import requests
from bs4 import BeautifulSoup
import time
import csv
import re
from urllib.parse import URLjoin
# 明亮数据代理配置
PROXY_HOST = "brd.superproxy.io"
代理端口 = "33335"
代理用户名 = "brd-customer-[ACCOUNT_ID]-zone-[ZONE_NAME]" # 替换为您的凭据
proxy_password = "[您的密码]" # 用密码代替
# 构建代理字典
代理 = {
"http": f "http://{proxy_username}:{代理密码}@{PROXY_HOST}:{PROXY_PORT}(端口",
"https": f "http://{proxy_username}:{代理密码}@{PROXY_HOST}:{PROXY_PORT}(端口"
}
# 模拟真实浏览器的请求标头
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Accept": "text/html,application/xhtml xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip、deflate、br",
"连接": "keep-alive",
}
步骤 3.3:创建用于数据验证的辅助函数
def is_valid_email(电子邮件):
"""验证电子邮件地址格式"""
模式 = r'^[a-zA-Z0-9._% -] @[a-zA-Z0-9.-] .[a-zA-Z]{2,}$'
return 关于match(模式、电子邮件) is not None
def 清洁手机(致电):
""清理并格式化电话号码"""
if not 电话
return None
# 删除除开头以外的所有非数字字符
cleaned = re.sub(r'[^d ]', ''电话)
return 洗净 if len(已清理) >= 10 else None
def 解码_cloudflare_email(encoded_str):
""解码受 Cloudflare 保护的电子邮件地址"""
try:
键 = int(encoded_str[:2], 16)
电子邮件 = "".join(
chr(int(encoded_str[i:i 2], 16)^ 键)
for i in range(2, len(encoded_str)、 2)
)
return 电子邮件 if is_valid_email(email) else None
except (值错误、索引错误):
return None
def 从 href 提取电子邮件(href):
""从 mailto: 链接中提取电子邮件"""
if not href:
return None
if href.startswith(邮件地址):
电子邮件 = href.replace(邮件地址, '').split('?')[0].strip()
return 电子邮件 if is_valid_email(email) else None
return None
步骤 3.4:创建主扫描功能
def fetch_page(url, retries=3):
""通过重试逻辑和错误处理功能获取页面内容"""
for 尝试 in range(重试):
try:
response = requests.get(
url、
代理服务器=PROXIES、
headers=HEADERS、
timeout=30
)
response.raise_for_status()
return response
except requests.exceptions.RequestException as e:
print(f"Attempt {尝试 1} 不符合 {url}: {str(e)}")
if 尝试 < 重试 - 1:
time.sleep(2 ** 尝试) # 指数退避
else:
print(f "Failed to fetch {url} 后 {重试} 尝试")
return None
return None
def 搜索列表(listing_page_url, link_selector=".企业名称 a"):
""从目录页面提取公司列表 URL""
print(f "获取列表页面: {listing_page_url}")
response = fetch_page(listing_page_url)
if not response:
return []
soup = BeautifulSoup(响应内容) lxml)
公司链接 = []
# 查找与选择器匹配的所有链接
for link in soup.select(link_selector):
href = link.get(href)
if href:
# 将相对 URL 转换为绝对 URL
absolute_url = urljoin(listing_page_url, href)
company_links.append(absolute_url)
# 删除重复内容,同时保留顺序
唯一链接 = list(dict.fromkeys(company_links))
print(发现 {len(unique_links)} 独特的公司列表")
return 唯一链接
def 刮取联系数据(公司网址):
""从公司页面提取联系信息"""
print(f "刮削: {company_url}")
response = fetch_page(company_url)
if not response:
return None
soup = BeautifulSoup(response.content、 lxml)
联系人数据 = {
'url'(网址: company_url、
`名称`: None,
电子邮件: None,
电话: None,
'address': None
}
# 提取公司名称
name_elem = soup.select_one(h1.business-name, h1[class*="business"], h1')
if name_elem:
contact_data[`名称`] = name_elem.get_text(strip=True)
# 提取电子邮件 - 检查多个来源
# 1.查找 mailto: 链接
电子邮件链接 = soup.select('a[href^="mailto:"]')
for link in 电子邮件链接:
email = extract_email_from_href(link.get(href))
if 电子邮件:
contact_data[电子邮件] = 电子邮件
break
# 2.查找受 Cloudflare 保护的电子邮件
if not contact_data[电子邮件]:
cf_email = soup.select_one(a.__cf_email__')
if cf_email 和 cf_email.get(数据-电子邮件):
decoded = decode_cloudflare_email(cf_email.get(数据-电子邮件))
if 已解码:
contact_data[电子邮件] = 已解码
# 3.在文本中搜索电子邮件模式
if not contact_data[电子邮件]:
text_content = soup.get_text()
email_pattern = r'b[A-Za-z0-9._% -] @[A-Za-z0-9.-] .[A-Z|a-z]{2,}b'
emails = re.findall(email_pattern, text_content)
for 电子邮件 in 电子邮件:
if is_valid_email(email):
contact_data[电子邮件] = 电子邮件
break
# 提取电话号码
phone_elem = soup.select_one('a[href^="tel:"],.phone, [class*="phone"]')
if phone_elem:
phone_text = phone_elem.get_text(strip=True)
contact_data[电话] = clean_phone(phone_text)
# 提取地址
address_elem = soup.select_one('.地址, [class*="address"], [itemprop="address"]')
if address_elem:
contact_data['address'] = address_elem.get_text(strip=True)
return 联系数据
步骤 3.5:实施主要搜索工作流程
def 刮取业务目录(base_url, max_pages=5,延迟=2):
"""
抓取商业目录的主要功能
参数:
base_url:目录列表的起始 URL
max_pages:要抓取的最大目录页数
延迟:请求之间的延迟(秒
"""
all_contacts = []
# 抓取列表页面
for 页码 in range(1, max_pages 1):
# 根据目标网站的分页方式调整 URL 格式
if 页码 == 1:
listing_url = base_url
else:
listing_url = f"{base_url}?page={page_num}"
print(处理页面 {page_num} ---")
company_urls = scrape_listing_urls(listing_url)
if not company_urls:
print(f "页面上未找到列表 {page_num},停止......")
break
# 抓取每家公司的联系页面
for idx、公司网址 in 罗列(company_urls、 1):
print(f"[{idx}/{len(company_urls)}]", end=" ")
contact_data = scrape_contact_data(company_url)
if contact_data:
all_contacts.append(contact_data)
# 速度限制 - 尊重目标站点
time.sleep(delay)
# 页与页之间的延迟
time.sleep(delay * 2)
return 所有联系人
def save_too_csv(联系人, 文件名=b2b_leads.csv):
""将搜索到的联系人保存到 CSV 文件"""
if not 联系:
print("无联系人可保存")
return
keys = contacts[0].keys()
with open(文件名: 'w', newline='', encoding='utf-8') as 输出文件:
dict_writer = csv.DictWriter(output_file, fieldnames=keys)
dict_writer.writeheader()
dict_writer.writerows(contacts)
print(f "n成功保存 {len(联系人)} 联系人 {文件名}")
# 主要执行
if __name__ == "__main__":
# 示例:搜索旧金山电工黄页
target_url = "https://www.yellowpages.com/san-francisco-ca/electricians"
print("启动 B2B 接触刮刀......")
print(f "目标: {target_url}n")
# 搜索目录
contacts = scrape_business_directory(
base_url=target_url、
max_pages=3, # 根据需要进行调整
延迟=2 # 以秒为单位的请求间延迟
)
# 显示结果
print(f "n{'='*50}")
print(f "清除完毕!")
print(f "清除的联系人总数: {len(联系人)}")
print(f"{'='*50}n")
# 显示扫描数据样本
if 联系:
print("样本数据(前 3 个条目):")
for i, 联系 in 罗列(联系人[......]):3], 1):
print(f "n{i}. {联系人['姓名']}")
print(f" 电子邮件: {联系人['电子邮件']}")
print(f" 电话: {联系人['电话']}")
print(f" 地址: {联系人['地址']}")
print(f" URL: {contact['url']}")
# 保存为 CSV
save_too_csv(contacts)
步骤 3.6:不同来源的高级配置
不同的网站有不同的 HTML 结构。下面介绍如何针对不同来源定制刮板:
# 不同数据源的配置
scraper_configs = {
黄页: {
列表选择器: '.企业名称 a',
名称选择器: h1.business-name,
电子邮件选择器: 'a[href^="mailto:"]',
电话选择器: .电话,
地址选择器: '.地址
},
yelp: {
列表选择器: a[href*="/biz/"]',
名称选择器: 'h1[class*="heading"]',
电子邮件选择器: 'a[href^="mailto:"]',
电话选择器: '[class*="电话"]',
地址选择器: 'address'
},
# 根据需要增加配置
}
def scrape_with_config(url, source_type=黄页):
""针对特定来源使用预定义配置进行抓取"""
config = SCRAPER_CONFIGS.get(source_type)
if not 配置:
raise ValueError(f "未知信号源类型: {资源类型}")
# 使用配置选择器进行刮擦
# 在此实施...
pass
步骤 4:使用粘土进行无代码触点刮擦
如果您不想编写代码,可以使用无代码平台,如 粘土 来自动执行搜索过程。Clay 与 Bright Data 集成,无需编码即可提供强大的搜索功能。
步骤 4.1:设置粘土工作流程
- 创建新表:在以下网址注册 Clay 账户 clay.com 并为 B2B 潜在客户创建一个新表。
- 添加栏目:在表格中设置以下列:
- 公司网址
- 公司名称
- 电子邮件
- 电话号码
- 地址
- 行业(可选)
- 备注(可选)
导入初始数据:您可以手动添加公司 URL、从 CSV 中导入,或使用 Clay 的 "查找公司 "功能,根据行业、地点或公司规模等标准发现线索。
步骤 4.2:将明亮数据与 Clay 整合
- 添加 "HTTP API "操作:在你的 Clay 表格中,点击“Add enrichment”,并搜索“HTTP API”,或者查找 Bright Data 专属集成。
- 配置刮擦请求:
- 将方法设置为 GET
- 添加栏中的公司 URL 作为目标
- 如果使用 HTTP API 操作,请配置 Bright Data 代理设置
替代方案:使用 Clay 的内置网页抓取器:
- 在 Clay 的增益中搜索 "抓取网站
- 选择包含目标 URL 的列
- Clay 会自动使用代理来抓取数据
步骤 4.3:使用克雷人工智能提取数据
- 使用 "从网站提取 "功能:这项人工智能功能可以自动识别和提取网页中的联系人信息。
- 确定要提取的内容:告诉 Clay 你需要什么信息:
- "查找主电子邮件地址"
- "提取电话号码"
- "获取公司的实际地址"
运行增益:Clay 会处理每个 URL 并自动提取所需的信息。
步骤 4.4:验证和丰富数据
- 电子邮件验证:使用 Clay 的电子邮件验证强化功能来验证电子邮件地址是否有效并可送达。
- 电话验证:增加电话验证功能,确保电话号码格式正确。
- 额外的丰富内容:利用 Clay 的集成功能添加更多数据:
- 来自 Clearbit 或类似网站的公司信息
- 来自 LinkedIn 的社交资料
- 技术数据
步骤 4.5:导出并使用数据
- 审查结果:检查粘土表中的丰富数据。
- 出口选项:
- 下载为 CSV,以便在 Excel 或 Google Sheets 中使用
- 直接与 CRM(Salesforce、HubSpot 等)集成
- 连接到电子邮件推广工具(Lemlist、Instantly 等)
工作流程自动化:设置 Clay,以便在新线索添加到您的表格时自动进行处理。
步骤 5:存储和使用搜索到的数据
成功获取联系人数据后,您需要有效地存储和使用这些数据。以下是最佳做法和选项:
选项 1:CSV/Excel 文件
最适合中小型数据集(最多 10,000 条记录)。
import pandas as pd
# 加载刮擦数据
df = pd.DataFrame(contacts)
# 清理和复制
df = df.drop_duplicates(subset=[)电子邮件])
df = df.dropna(subset=[电子邮件]) # 删除不带电子邮件的条目
# 保存为 Excel 格式
df.to_excel(b2b_leads.xlsx, index=False, engine=openpyxl)
方案 2:数据库存储
最适合大型数据集以及需要频繁查询和更新数据的情况。
import sqlite3
import pandas as pd
def 保存到数据库(contacts, db_name=b2b_leads.db):
""将联系人保存到 SQLite 数据库"""
conn = sqlite3.connect(db_name)
df = pd.DataFrame(contacts)
# 创建或替换表格
df.to_sql(联系人, conn, if_exists=替换, index=False)
# 创建电子邮件索引,加快查询速度
cursor = conn.cursor()
cursor.execute(在 contacts(email) 上创建 INDEX IF NOT EXISTS idx_email)
conn.commit()
conn.close()
print(保存 {len(联系人)} 联系人到数据库: {db_name}")
def 查询联系人(db_name=b2b_leads.db城市=None):
""从数据库中查询联系人"""
conn = sqlite3.connect(db_name)
if 城市:
查询 = f"SELECT * FROM contacts WHERE address LIKE '%{城市}%'"
else:
查询 = "SELECT * FROM contacts"
df = pd.read_sql_query(query, conn)
conn.close()
return df
方案 3:直接集成 CRM
最适合在销售工作流程中立即使用。
import requests
def export_too_hubspot(联系人, api_key):
""将联系人直接导出到 HubSpot CRM""
url = "https://api.hubapi.com/contacts/v1/contact/batch/"
headers = {
"内容类型": "application/json",
"Authorization": f "承载器 {api_key}"
}
# HubSpot 格式联系人
格式化的联系人 = []
for 联系 in 联系:
if contact.get(电子邮件): # 仅在电子邮件存在时导出
formatted_contacts.append({
"电子邮件"联系人[电子邮件],
"属性": [
{"财产": "公司", "值": contact.get(`名称`, '')},
{"财产": "电话", "值": contact.get(电话, '')},
{"财产": "address", "值": contact.get('address', '')},
{"财产": "网站", "值": contact.get('url'(网址, '')}
]
})
# 以 100 为一批发送
批量大小 = 100
for i in range(0, len(formatted_contacts), batch_size):
batch = formatted_contacts[i:i批量大小]
response = requests.post(url, headers=headers, json=batch)
if response.status_code == 200:
print(f "成功导出批次 {i//batch_size 1}")
else:
print(f "批量导出出错: {response.text}")
最佳实践和法律考虑
1.尊重 Robots.txt
经常检查网站的 robots.txt 文件,查看允许的内容:
import requests
from urllib.parse import URLjoin
def 检查机器人文本(base_url, user_agent='*'):
""检查 robots.txt 是否允许刮擦"""
robots_url = urljoin(base_url、 /robots.txt)
try:
response = requests.get(robots_url, timeout=5)
if response.status_code == 200:
print(f "Robots.txt内容:n{response.text}")
return response.text
except:
print("未找到 robots.txt 或无法获取")
return None
2.实施速率限制
不要让目标服务器超负荷运行:
import time
from datetime import datetime
class 速率限制器:
def __init__(self, max_requests_per_minute=30):
self.max_requests = max_requests_per_minute
self.requests = []
def 需要时等待(self):
now = datetime.now()
# 删除超过 1 分钟的请求
self.requests = [req_time for 请求时间 in self.requests
if (now - req_time).seconds < 60]
if len(self.requests) >= self.max_requests:
sleep_time = 60 - (now - self.requests[0]).seconds
print(f "达到速率限制。等待 {睡眠时间} 秒......")
time.sleep(sleep_time)
self.requests.append(now)
# 使用方法
limiter = RateLimiter(max_requests_per_minute=30)
for url in urls:
limiter.wait_if_needed()
scrape_contact_data(url)
3.数据隐私与合规
- 遵守 GDPR:如果扫描欧盟公民的数据,请确保遵守 GDPR
- CAN-SPAM 法案:在营销过程中使用剪贴邮件时应遵守相关规定
- 服务条款:经常查看并遵守网站服务条款
- 数据最小化:只收集实际需要的数据
- 安全存储:加密敏感的联系信息
4.错误处理和日志记录
import 伐木
from datetime import datetime
# 设置日志记录
logging.basicConfig(
level=logging.INFO、
格式=%(时间)s - %(级别名)s - %(信息)s,
handlers=[
logging.FileHandler(f'scraper_{datetime.now().strftime("%Y%m%d")}.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
def 有日志记录的搜刮(url):
""带有全面日志记录的扫描"""
try:
logger.info(f "开始刮削 {url}")
data = scrape_contact_data(url)
if data 和 data.get(电子邮件):
logger.info(f "成功刮除 {url} - 找到电子邮件 {data['email']}")
else:
logger.warning(f "未找到 {url}")
return data
except Exception as e:
logger.error(f "刮擦错误 {url}: {str(e)}", exc_info=True)
return 无结论
结论
为 B2B 潜在客户生成创建一个可靠的联系人搜索器,可以大大提高收集潜在客户和促进销售的效率。通过遵循本指南中概述的最佳实践,您可以
- 选择正确的数据源 以产生高质量的销售线索
- 克服反机器人措施 使用 Bright Data 的代理网络
- 制造坚固耐用的铲运机 适当的错误处理和验证
- 尊重法律和道德界限 在刮削的同时
- 有效存储和利用数据 在您的销售工作流程中
无论您是选择基于代码的方法以获得最大灵活性,还是选择无代码的 Clay 解决方案以获得易用性,联系人搜索都将成为支持您的营销和销售目标的强大工具。将这一过程自动化不仅可以节省时间,还能为您的企业提供持续不断的宝贵线索。
记住:
- 尊重网站服务条款和 robots.txt 文件
- 实施适当的速率限制
- 验证和清理数据
- 确保遵守数据隐私法规
- 以合乎道德和负责任的方式使用搜索到的数据
今天就开始创建您的联系人搜索器,改变您的 B2B 潜在客户生成流程!

