Подписывайтесь:

Блог AST-SoftPro

Парсинг контактных данных: как найти клиентов через веб-скрейпинг на Python

14.06.2026 9 мин чтения
Парсинг контактных данных: как найти клиентов через веб-скрейпинг на Python

Поиск клиентов через веб-скрейпинг

Поиск потенциальных клиентов — одна из самых затратных задач для бизнеса. Менеджеры тратят часы на ручной сбор контактных данных с сайтов, каталогов и площадок объявлений. Python позволяет автоматизировать этот процесс полностью: от сбора данных до формирования готовой базы для обзвона или рассылки.

В статье рассматриваются практические приёмы парсинга контактной информации: извлечение email, телефонов и сайтов компаний из открытых источников. Примеры основаны на реальном проекте автоматизированного сбора контактов.

Инструменты для парсинга

Для задач скрейпинга существует несколько подходов в зависимости от сложности целевого сайта:

Инструмент Тип сайтов Сложность Пример использования
requests + BeautifulSoup Статические HTML-страницы Низкая Каталоги, справочники компаний
Selenium Страницы с JavaScript Средняя SPA-приложения, динамические каталоги
Playwright Современные сайты с JS Средняя Любые сайты, включая SPA
Scrapy Масштабные проекты Высокая Парсинг тысяч страниц, распределённый сбор

Для большинства задач поиска контактов достаточно requests + BeautifulSoup. Эти библиотеки покрывают 80% случаев, когда данные доступны в HTML без выполнения JavaScript.

Пример: сбор контактов из каталога компаний

Рассмотрим типичный сценарий: нужно собрать контактные данные компаний из отраслевого каталога.

import requests
from bs4 import BeautifulSoup
import csv

def parse_company_catalog(base_url, page_count=10):
    """Сбор контактов из каталога компаний."""
    contacts = []

    for page in range(1, page_count + 1):
        url = f"{base_url}/page/{page}"
        response = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'})
        soup = BeautifulSoup(response.text, 'html.parser')

        for card in soup.select('.company-card'):
            company = {
                'name': card.select_one('.company-name').text.strip(),
                'phone': card.select_one('.phone').text.strip() if card.select_one('.phone') else '',
                'email': card.select_one('.email').text.strip() if card.select_one('.email') else '',
                'website': card.select_one('.website a')['href'] if card.select_one('.website a') else '',
                'address': card.select_one('.address').text.strip() if card.select_one('.address') else '',
            }
            contacts.append(company)

    return contacts

# Использование
contacts = parse_company_catalog('https://catalog.example.com/companies')
print(f"Собрано контактов: {len(contacts)}")

Сохранение результатов в CSV и SQLite

После сбора данных важно сохранить их в удобном формате. CSV подходит для экспорта в Excel, SQLite — для дальнейшей обработки и дедупликации.

import sqlite3

def save_to_csv(contacts, filename='contacts.csv'):
    """Сохранение контактов в CSV для Excel."""
    if not contacts:
        return
    keys = contacts[0].keys()
    with open(filename, 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.DictWriter(f, fieldnames=keys)
        writer.writeheader()
        writer.writerows(contacts)
    print(f"Сохранено {len(contacts)} записей в {filename}")

def save_to_sqlite(contacts, db_path='contacts.db'):
    """Сохранение в SQLite с дедупликацией по email."""
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS contacts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT, phone TEXT, email TEXT UNIQUE,
            website TEXT, address TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    ''')
    for c in contacts:
        try:
            cursor.execute(
                'INSERT OR IGNORE INTO contacts (name, phone, email, website, address) VALUES (?, ?, ?, ?, ?)',
                (c['name'], c['phone'], c['email'], c['website'], c['address'])
            )
        except Exception:
            pass
    conn.commit()
    conn.close()
    print(f"Записи сохранены в {db_path}")

Работа с пагинацией и динамическими страницами

Не все каталоги имеют простую пагинацию. Некоторые загружают данные через AJAX или используют бесконечную прокрутку. В таких случаях пригодится Playwright:

from playwright.sync_api import sync_playwright

def parse_dynamic_catalog(url):
    """Парсинг каталога с динамической загрузкой."""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto(url, wait_until='networkidle')

        # Прокрутка для загрузки всех элементов
        for _ in range(5):
            page.evaluate('window.scrollBy(0, 500)')
            page.wait_for_timeout(500)

        contacts = []
        for card in page.query_selector_all('.company-card'):
            contacts.append({
                'name': card.inner_text().strip(),
                'phone': card.query_selector('.phone').inner_text() if card.query_selector('.phone') else '',
            })

        browser.close()
        return contacts

Извлечение email и телефонов с помощью регулярных выражений

Иногда контакты не выделены в отдельные элементы HTML — они «спрятаны» в тексте страницы. В таких случаях на помощь приходят регулярные выражения:

import re

def extract_emails(text):
    """Поиск email-адресов в тексте."""
    pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
    return re.findall(pattern, text)

def extract_phones(text):
    """Поиск российских номеров телефонов."""
    pattern = r'(?:\+7|8)[\s\-]?\(?\d{3}\)?[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}'
    return re.findall(pattern, text)

# Пример
page_text = soup.get_text()
emails = extract_emails(page_text)
phones = extract_phones(page_text)
print(f"Email: {emails}, Телефоны: {phones}")

Ответственный скрейпинг: правила и ограничения

Автоматизация сбора данных требует соблюдения этики и законодательства:

Правило Рекомендация
robots.txt Проверяйте /robots.txt целевого сайта перед парсингом
Задержки Добавляйте time.sleep(1-3) между запросами, не перегружайте сервер
User-Agent Указывайте корректный User-Agent, не скрывайте бота
Персональные данные Соблюдайте 152-ФЗ (РФ) и GDPR (ЕС) при сборе персональных данных
Коммерческое использование Проверяйте условия использования сайта — данные могут быть защищены авторским правом

Важно: собирайте только общедоступные контактные данные компаний (B2B), а не персональные данные физических лиц.

Заключение

Веб-скрейпинг на Python — мощный инструмент для автоматизации поиска клиентов. Комбинация requests + BeautifulSoup + re покрывает большинство задач сбора контактной информации. Для сложных сайтов с JavaScript используйте Playwright.

Ключевые шаги:

  • Выбор инструмента в зависимости от типа сайта;

  • Извлечение данных из HTML-структуры или текста страницы;

  • Сохранение в CSV/SQLite с дедупликацией;

  • Соблюдение правил ответственного скрейпинга.

Начните с простых каталогов, отладьте скрипт, а затем масштабируйте на более сложные источники.


AI-Помощник