Узнайте, как создать готовый к использованию сервер веб-перехватов Flask, который асинхронно извлекает профили LinkedIn, используя Crawlbase API и хранение данных в MySQL. В этом руководстве рассматриваются настройка среды, проектирование базы данных, реализация сервера обратного вызова и мониторинг в режиме реального времени.

Что вы построите

Масштабируемая система сбора данных LinkedIn с:

  • Сервер веб-перехвата Flask для получения извлеченных данных
  • базы данных MySQL для структурированного хранения данных
  • Асинхронная обработка для очистки больших объемов
  • Мониторинг в режиме реального времени приборная панель

Случаи использования

  • Поиск талантов: Автоматизация поиска кандидатов и анализа профилей
  • Исследование рынка: Отслеживайте тенденции отрасли и информацию о конкурентах
  • Лидогенерация: Создание целевых баз данных потенциальных клиентов B2B
  • HR аналитика: Анализ моделей рабочей силы и траекторий карьерного роста
  • Данные обучения искусственного интеллекта: Создание наборов данных для моделей машинного обучения

В этом руководстве демонстрируется сбор только общедоступных данных LinkedIn. Всегда соблюдайте Условия обслуживания LinkedIn и законы о защите данных. Crawlbase запрещает извлечение личных данных.

Часть I: Подготовка среды

А. Создание Crawlbase Учетная запись и активация сканирования LinkedIn

  1. Начните с посещения Crawlbase сайт и зарегистрировать аккаунт.
  2. Перейдите на сайт Страница соглашения LinkedIn прочитать и принять условия.
  3. Добавьте свои платежные реквизиты, перейдя по ссылке настройки платежной информации.

Б. Настройка базы данных MySQL

Мы будем использовать MySQL, поскольку это популярная система управления реляционными базами данных, которая широко используется для различных приложений. В этом примере я буду использовать MySQL версии 8. Если она еще не установлена ​​на вашем компьютере, перейдите на страницу официальное руководство по установке MySQL.

После установки откройте клиент командной строки MySQL. Вам будет предложено ввести пароль для пользователя root MySQL. После ввода пароля вы попадете в интерфейс командной строки MySQL. Затем вы можете выполнить следующие командные строки.

  1. Создать нового пользователя
1
СОЗДАТЬ USER 'linkedincrawler'@'локальный хост' ИДЕНТИФИЦИРОВАННЫЕ BY 'linked1nS3cret';

Код создает нового пользователя MySQL с именем linkedincrawler с паролем linked1nS3cret, ограничено подключением с одной и той же машины (localhost).

  1. Создать базу данных
1
СОЗДАТЬ БАЗА ДАННЫХ linkedin_crawler_db;

Эта база данных будет представлять собой пустой контейнер, в котором можно хранить таблицы, данные и другие объекты.

  1. Предоставить разрешение
1
ГРАНТ BCE ПРИВИЛЕГИИ ON linkedin_crawler_db.* К 'linkedincrawler'@'локальный хост';

Это предоставит нашему пользователю полные привилегии и разрешения для вновь созданной базы данных.

  1. Установить текущую базу данных
1
ИСПОЛЬЗУЙТЕ linkedin_crawler_db;

Это позволит выбрать нашу базу данных и направить все наши инструкции в нее.

  1. Теперь давайте создадим три таблицы в текущей выбранной базе данных: crawl_requests, linkedin_profiles и linkedin_profile_experiences.

The crawl_requests будет основной таблицей, которая будет служить механизмом для отслеживания всего процесса асинхронного сканирования.

В этой таблице у нас будет 3 столбца: url, status, crawlbase_rid.

The status столбец может иметь одно из этих трех значений - waiting, receiving и processed. Назначение этих статусов будет подробно рассмотрено позже.

1
2
3
4
5
6
СОЗДАТЬ ТАБЛИЦУ IF НЕ СУЩЕСТВУЕТ `crawl_requests` (
`id` INT АВТОМАТИЧЕСКОЕ ПРИРАЩЕНИЕ ПЕРВИЧНЫЙ КЛЮЧ,
`url` ТЕКСТ НЕНУЛЕВОЙ,
`статус` ВАРЧАР(30) НЕНУЛЕВОЙ,
`crawlbase_rid` ВАРЧАР(255) НЕНУЛЕВОЙ
);

Затем мы создаем индексы базы данных для производительности нашего запроса.

1
2
3
СОЗДАТЬ ИНДЕКС `idx_crawl_requests_status` ON `crawl_requests` (`status`);
СОЗДАТЬ ИНДЕКС `idx_crawl_requests_crawlbase_rid` ON `crawl_requests` (`crawlbase_rid`);
СОЗДАТЬ ИНДЕКС `idx_crawl_requests_status_crawlbase_rid` ON `crawl_requests` (`status`, `crawlbase_rid`);

Для последних двух таблиц это позволит вам хранить структурированную информацию о просканированных профилях LinkedIn и связанных с ними данных.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
СОЗДАТЬ ТАБЛИЦУ IF НЕ СУЩЕСТВУЕТ `linkedin_profiles` (
`id` INT АВТОМАТИЧЕСКОЕ ПРИРАЩЕНИЕ ПЕРВИЧНЫЙ КЛЮЧ,
`crawl_request_id` INT НЕНУЛЕВОЙ,
`название` ВАРЧАР(255),
`заголовок` ВАРЧАР(255),
`резюме` ТЕКСТ,

ИНОСТРАННЫЙ КЛЮЧ (`crawl_request_id`) Ссылки `crawl_requests`(`id`)
);

СОЗДАТЬ ТАБЛИЦУ IF НЕ СУЩЕСТВУЕТ `linkedin_profile_experiences` (
`id` INT АВТОМАТИЧЕСКОЕ ПРИРАЩЕНИЕ ПЕРВИЧНЫЙ КЛЮЧ,
`linkedin_profile_id` INT НЕНУЛЕВОЙ,
`название` ВАРЧАР(255),
`название_компании` ВАРЧАР(255),
`описание` ТЕКСТ,
`is_current` БИТ НЕНУЛЕВОЙ DEFAULT 0,

ИНОСТРАННЫЙ КЛЮЧ (`linkedin_profile_id`) Ссылки `linkedin_profiles`(`id`)
);

Чтобы просмотреть таблицы, созданные в базе данных MySQL, используйте SQL-запросы в интерфейсе командной строки MySQL или клиентский инструмент MySQL.

Интерфейс командной строки MySQL

C. Структура файлов и каталогов

Важно организовать файлы при настройке среды в Python. Убедитесь, что каждый из них будет сохранен в одном и том же каталоге проекта, как показано ниже:

Структура файлов и каталогов

D. Создание виртуальной среды на Python

Виртуальная среда — это изолированное пространство, в котором можно устанавливать пакеты Python, не затрагивая общесистемную установку Python. Это полезно для управления зависимостями для разных проектов.

В этом проекте мы будем использовать Python 3. Обязательно загрузите и установите соответствующую версию.

Открыто Git bash или терминал для выполнения следующей команды.

1
ПАПКА_ПРОЕКТА$ python3 -m venv .venv

После создания виртуальной среды ее необходимо активировать.

1
ПАПКА_ПРОЕКТА$ . .venv/bin/activate

Создайте текстовый файл в папке вашего проекта и сохраните его как PROJECT_FOLDER/requirements.txt. Этот файл должен содержать следующие пакеты Python, от которых будет зависеть наш проект.

1
2
3
4
5
Flask

MySQL-коннектор-Python
Pyyaml
Запросы
SQLAlchemy

Установите зависимости с помощью pip команда.

1
ПАПКА_ПРОЕКТА$ pip install -r requirements.txt

В том же каталоге создайте файл с именем PROJECT_FOLDER/settings.yml который будет служить заполнителем для вашего Crawlbase (TCP) токен и Crawler имя.

1
2
маркер: < >
гусеничный трактор: mycrawlername

E. Как получить список профилей LinkedIn

Чтобы получить список URL-адресов профилей LinkedIn, вам обычно нужно собрать эти URL-адреса из разных источников, таких как результаты поиска, связи или публичные профили. Вот несколько способов, которыми вы можете получить URL-адреса профилей LinkedIn:

  1. Сбор вручную:
  • Вы можете вручную посетить профили LinkedIn и скопировать URL-адреса из адресной строки вашего веб-браузера. Этот метод подходит для небольшого количества профилей.
  1. Результаты поиска LinkedIn:
  • Используйте функцию поиска LinkedIn, чтобы находить профили по определенным критериям (например, должность, местоположение, отрасль).
  • Скопируйте URL-адреса профилей, указанные в результатах поиска.
  1. Профили подключений:
  • Если вы связаны с кем-то в LinkedIn, вы можете посетить список его контактов и извлечь оттуда URL-адреса профилей.
  1. Сторонний API:
  • Вы можете построить отдельный скребок, используя Crawlbase для автоматизации сбора URL-адресов LinkedIn. Мы можем рассказать об этом в статье в будущем, так что будьте осторожны.

Для целей этой статьи мы предоставили список URL-адресов LinkedIn для скрапинга. По умолчанию мы настроили текстовый файл с 5 самых популярных личностей на LinkedIn.

Этот файл находится в PROJECT_FOLDER/urls.txt.

Примечание: что каждая строка соответствует действительному URL. Если у вас есть готовые URL, вы можете отредактировать этот текстовый файл и добавить их в список.

Часть II: Написание сценариев для проекта

A. Создайте определение ORM с помощью SQLAlchemy для взаимодействия с вашей базой данных.

Теперь нам нужно создать скрипт для работы с данными LinkedIn в базе данных MySQL. Этот скрипт начнется с импорта необходимых модулей из SQLAlchemy и модуля типизации для подсказок типов.

Для демонстрационных целей мы сохраним этот скрипт в PROJECT_FOLDER/lib/database.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
от ввод         Импортировать Список
от алхимия Импортировать Внешний ключ
от алхимия Импортировать create_engine
от sqlalchemy.orm Импортировать DeclarativeBase
от sqlalchemy.orm Импортировать Сессия
от sqlalchemy.orm Импортировать Подключенные
от sqlalchemy.orm Импортировать сопоставленный_столбец
от sqlalchemy.orm Импортировать отношения

класс Система исчисления(DeclarativeBase):
pass

класс CrawlRequest(Система исчисления):
__имя_таблицы__ = 'crawl_requests'

id: Нанесено на карту[Int] = сопоставленный_столбец(первичный_ключ=Правда)
URL: Отображено[ул]
статус: Нанесено на карту[ул]
crawlbase_rid: Сопоставлено[ул]
linkedin_profile: Сопоставлено[«Профиль Linkedin»] = отношение(back_populates='crawl_request')

класс Профиль Linkedin(Система исчисления):
__имя_таблицы__ = 'linkedin_profiles'

id: Нанесено на карту[Int] = сопоставленный_столбец(первичный_ключ=Правда)
название: Нанесено на карту[ул]
заголовок: Нанесено на карту[ул]
резюме: Нанесено на карту[ул]
crawl_request_id: Сопоставлено[Int] = сопоставленный_столбец(ForeignKey('crawl_requests.id'))
crawl_request: Сопоставлено[«CrawlRequest»] = отношение(back_populates='linkedin_profile')
опыт: Нанесено на карту[Список[«Опыт LinkedinProfile»]] = отношение(back_populates='linkedin_profile')

класс LinkedinПрофильОпыт(Система исчисления):
__имя_таблицы__ = 'linkedin_profile_опыты'

id: Нанесено на карту[Int] = сопоставленный_столбец(первичный_ключ=Правда)
название: Нанесено на карту[ул]
company_name: Сопоставлено[ул]
описание: Нанесено на карту[ул]
is_current: Отображено[BOOL]
linkedin_profile_id: Сопоставлено[Int] = сопоставленный_столбец(ForeignKey('linkedin_profiles.id'))
linkedin_profile: Сопоставлено[«Профиль Linkedin»] = отношение(back_populates=«опыты»)

защиту создать_сеанс_базы_данных():
строка_подключения = 'mysql+mysqlconnector://linkedincrawler:linked1nS3cret@localhost:3306/linkedin_crawler_db'
движок = create_engine(строка_подключения, echo=Правда)
возвращают Сессия(движок)

Этот код предоставляет функцию для создания сеанса для взаимодействия с базой данных. Обратите внимание, что скрипт, который мы предоставим, предполагает, что у вас установлены необходимые библиотеки и запущен сервер MySQL с указанными данными подключения.

Б. Скрипт для отправки запросов на Crawlbase Crawler

The Crawlbase Crawler работает асинхронно в системе push-pull, которая использует URL-адреса обратного вызова. Когда вы отправляете запросы в Crawler, он назначает уникальный RID на каждый запрос. Crawler внутренне выполняет сканирование до тех пор, пока успешный ответ получен. Впоследствии этот ответ передается обратно на ваш назначенный вебхук, что позволяет вам обрабатывать и впоследствии сохранять данные в вашей базе данных.

Для получения более подробной информации вы можете проверить полная документация Crawlbase Crawler.

Скрипт начинается с импорта необходимых модулей, включая запросы для выполнения HTTP-запросов, urllib.parse для кодирования URL, json для обработки данных JSON и JSONDecodeError для обработки ошибок декодирования JSON.

Для демонстрационных целей мы сохраним этот скрипт в PROJECT_FOLDER/crawl.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Импортировать Запросы
Импортировать urllib.parse
Импортировать JSON
от JSON Импортировать JSONDecodeError
от lib.utils Импортировать журнал
от lib.utils Импортировать загрузка_настроек
от lib.database Импортировать CrawlRequest
от lib.database Импортировать создать_сеанс_базы_данных

crawlbase_settings = load_settings()

crawlbase_token = crawlbase_settings.get(токен)
crawlbase_crawler = crawlbase_settings.get(«гусеничный»)

if crawlbase_token is Ничто or crawlbase_token.strip() == '':
Распечатать('--------------------------------------------------')
Распечатать(«Пожалуйста, установите ваш Crawlbase токен в settings.yml')
Распечатать('--------------------------------------------------')
Выход()

if crawlbase_crawler is Ничто or crawlbase_crawler.strip() == '':
Распечатать('----------------------------------------------------')
Распечатать(«Пожалуйста, установите ваш Crawlbase краулер в settings.yml')
Распечатать('----------------------------------------------------')
Выход()

linked_in_profile_urls = открытый('urls.txt', 'R').readlines()

if только(ссылки_в_профиле_urls) == 0:
Распечатать('-------------------------------------------------------------------------------------')
Распечатать(«Нет доступных URL-адресов. Пожалуйста, введите URL-адреса в `urls.txt`, разделив их новой строкой».)
Распечатать('-------------------------------------------------------------------------------------')
Выход()

журнал(«Начинаю ползать...»)

crawlbase_api_url = 'https://api.crawlbase.com?token={0}&callback=true&crawler={1}&url={2}&autoparse=true'

сеанс = create_database_session()

для URL in URL-адреса_linked_in_profile:
url = url.strip()
encoded_url = urllib.parse.quote(url, safe='')
api_url = crawlbase_api_url.формат(crawlbase_token, crawlbase_crawler, encoded_url)

журнал(f'Запрос на сканирование {URL}')

стараться:
ответ = запросы.получить(api_url)
json_response = json.loads(response.text)
crawlbase_rid = json_response['избавлять']
crawl_request = CrawlRequest(url=url, crawlbase_rid=crawlbase_rid, status='ожидающий')
session.add(crawl_request)
сеанс.коммит()
кроме JSONDecodeError:
журнал(f'Произошла ошибка при декодировании ответа json\n{ответ.текст}')
кроме:
журнал(f'Произошла неизвестная ошибка при сканировании {URL}')

журнал(«Хватит ползать».)

Код будет считывать URL-адреса из PROJECT_FOLDER/urls.txt и отправляет каждый URL-адрес на Crawlbase API для сканирования, который затем отвечает идентификатором запроса, например {”rid”: 12341234}. Код создаст новую запись строки для сохранения RID в нашем crawl_requests таблица со статусом waiting.

Обратите внимание, что нам придется вставить соответствующий crawlbase_token и crawlbase_crawler имя в этом скрипте, который мы рассмотрим в руководстве позже.

C. Создание сервера обратного вызова Flask

Flask — это микровеб-фреймворк, написанный на Python, который мы будем использовать для создания сервера обратного вызова.

Убедитесь, что ваш обратный вызов оснащен для выполнения декодирования base64 и распаковки gzip. Это важно, поскольку Crawler Движок передаст данные в конечную точку обратного вызова, используя метод POST со сжатием gzip и кодировкой base64.

Для демонстрационных целей мы сохраним этот скрипт в PROJECT_FOLDER/callback_server.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
Импортировать GZIP
от колба Импортировать Flask
от колба Импортировать jsonify
от колба Импортировать запросить
от lib.utils Импортировать журнал
от lib.database Импортировать CrawlRequest
от lib.database Импортировать создать_сеанс_базы_данных

app = Flask (__name__)
сеанс = create_database_session()

@app.route('/crawlbase_crawler_callback', методы=['ПОЧТА'])
защиту crawlbase_crawler_callback():
crawlbase_rid = запрос.заголовки.получить('избавлять')
content_encoding = запрос.заголовки.получить(«Контент-кодирование»)
оригинальный_статус = запрос.заголовки.получить(«Оригинальный статус»)
if ( оригинальный_статус is Ничто):
оригинальный_статус = Int(исходный_статус.разделить('')[0])
crawlbase_status = запрос.заголовки.получить(«Статус ПК»)
if ( crawlbase_status is Ничто):
crawlbase_status = Int(crawlbase_status.split('')[0])

if crawlbase_rid is Ничто:
журнал(f'Crawlbase рид не установлен.)
возвращают ('', 204)

if crawlbase_rid == 'dummyrequest':
журнал(«Сервер обратного вызова работает»)
возвращают ('', 204)

if crawlbase_status != 200:
журнал(f'Crawlbase статус не 200.)
возвращают ('', 204)

if оригинальный_статус != 200:
журнал(f'Исходный статус не 200.')
возвращают ('', 204)

crawl_request_does_not_exist = session.query(CrawlRequest).filter_by(crawlbase_rid=crawlbase_rid, status='ожидающий').первый() is Ничто

if запрос_на_сканирование_не_существует:
журнал(f'Нет Crawlbase избавиться {crawlbase_rid} найдено со статусом `ожидание`.)
возвращают ('', 204)

crawl_request = session.query(CrawlRequest).filter_by(crawlbase_rid=crawlbase_rid, status='ожидающий').скаляр()

тело = запрос.данные
if content_encoding == 'gzip':
стараться:
тело = gzip.decompress(тело)
кроме Ошибка ОС:
pass

открытый(ф'./данные/{crawlbase_rid}.json', 'вб') as f:
f.write(тело)

crawl_request.status = 'полученный'
сеанс.коммит()

журнал(f'Crawlbase избавиться {crawlbase_rid} был успешно получен.)

возвращают ('', 201)

if __имя__ == '__главный__':
app.run ()

Этот код настраивает приложение Flask с одним маршрутом для обработки обратных вызовов, сделанных из Crawlbase Crawler, Обратите внимание, что Crawlbase Crawler помещает информацию RID в заголовок запроса с именем rid.

Кроме того, этот код проверит наш crawl_requests таблица для того же RID с waiting статус, в противном случае запрос будет проигнорирован.

Также убедитесь, что заголовки запроса Original-Status и PC-Status имеют код ответа об успешном статусе HTTP 200 OK.

После того, как он получит просканированные данные от Crawler, он будет обработан (декодирован и распакован) и сохранен в папке данных, а затем обновит статус RID в received.

D. Скрипт для извлечения просканированных данных и сохранения их в базе данных

Этот код берет на себя задачу регулярного мониторинга статуса RID в нашей таблице crawl_requests. Когда он обнаруживает, что статус получен, он инициирует обработку данных для заполнения таблиц linkedin_profiles и linkedin_profiles_experiences. По завершении он обновляет статус RID на обработанный.

Для демонстрационных целей мы сохраним этот скрипт в PROJECT_FOLDER/process.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
Импортировать JSON
Импортировать Плановое
Импортировать время
от lib.utils Импортировать журнал
от lib.utils Импортировать is_iterable
от lib.database Импортировать CrawlRequest
от lib.database Импортировать Профиль Linkedin
от lib.database Импортировать LinkedinПрофильОпыт
от lib.database Импортировать создать_сеанс_базы_данных

ИНТЕРВАЛ_РАСПИСАНИЯ_В_СЕКУНДАХ = 60
RECORDS_COUNT_LIMIT_PER_PROCESSING = 10

защиту процесс():
сеанс = create_database_session()
received_crawl_requests = session.query(CrawlRequest).filter_by(status='полученный').limit(RECORDS_COUNT_LIMIT_PER_PROCESSING).ВСЕ()

if только(полученные_запросы_на_сканирование) == 0:
журнал(«Нет полученных запросов на сканирование для обработки».)
еще:
для запрос_на_сканирование in получено_запросов_на_сканирование:
журнал(f'Обработка Crawlbase избавиться {crawl_request.crawlbase_rid} с URL-адресом {crawl_request.url}.')

ф = открытый(ф'./данные/{crawl_request.crawlbase_rid}.json')
данные = json.load(f)

заголовок = данные.получить('заглавие')
заголовок = данные.получить('заголовок')
резюме = данные.получить('краткое содержание')
резюме = '\ n'.join(резюме) if is_iterable(резюме) еще Ничто

linkedin_profile = LinkedinProfile(title=заголовок, headline=заголовок, summary=резюме)
linkedin_profile.crawl_request_id = crawl_request.id
сессия.добавить(linkedin_profile)

опыт = (data.get('опыт') и данные.получить('опыт').получать('experienceList')) or []
для опыт in опыт:
заголовок = опыт.получить('заглавие')
название_компании = опыт.получить('компания') и опыт.получить('компания').получать('Name')
описания = опыт.получить('описание')
описание = '\ n'.join(описания) if is_iterable(описания) еще Ничто
is_current = опыт.получить(«текущая позиция») == Правда

linkedin_profile_experience = LinkedinProfileExperience(
название=название,
название_компании=название_компании,
описание=описание,
is_current=is_current
)
linkedin_profile_experience.linkedin_profile = linkedin_profile
сеанс.add(linkedin_profile_experience)

crawl_request.status = «обработано»

сеанс.коммит()

защиту процесс_и_перепланирование():
процесс()
планировщик.ввод(SCHEDULE_INTERVAL_IN_SECONDS, 1, процесс_и_перепланирование)

if __имя__ == '__главный__':
планировщик = scheduler(время.монотонный, время.сон)
процесс_и_перепланирование()
планировщик.run()

Часть III: Выполнение скриптов

A. Запуск локальной туннельной службы с использованием Ngrok

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

Создайте временный публичный URL с помощью Ngrok, который будет указывать на ваше локально размещенное приложение. Это позволит нам использовать наш сервер обратного вызова Flask в качестве веб-перехватчика для Crawlbase Crawler.

1
$ нгрок http 5000

После выполнения получите публичный URL-адрес, который мы будем использовать позже для создания нашего Crawler.

Нгрок

Примечание: нам нужно указать ngrok на порт 5000 как на наше приложение Flask. callback_server.py по умолчанию будет использоваться тот же порт.

B. Запуск сервера обратного вызова

Теперь, когда Ngrok инициализирован, мы можем запустить наш сервер обратного вызова, который будет перехватывать RID и просканированный контент из Crawlbase.

1
ПАПКА_ПРОЕКТА$ python callback_server.py

На основе нашего кода это полный маршрут, который обрабатывает обратный вызов:

https://400d-120-29-87-188.ngrok.io/crawlbase_crawler_callback

C. Тестирование сервера обратного вызова

Мы должны убедиться, что сервер обратного вызова работает так, как и ожидалось, и может передавать Crawlbase большого города, . Для этого вы можете выполнить следующий фрагмент кода и посмотреть результат:

1
$ curl -i -X ​​ПОСТ 'http://localhost:5000/crawlbase_crawler_callback' -H 'RID: фиктивный запрос' -H 'Accept: приложения / JSON' -H «Тип содержимого: gzip/json» -H «Пользовательский агент: Crawlbase Мониторинговый бот 1.0' -H «Кодирование содержимого: gzip» --data-binary '"\x1F\x8B\b\x00+\xBA\x05d\x00\x03\xABV*\xCALQ\xB2RJ)\xCD\xCD\xAD,J-,M-.Q\xD2QJ\xCAO\xA9\x04\x8A*\xD5\x02\x00L\x06\xB1\xA7 \x00\x00\x00' - сжатый

Эти curl команда выполнит POST-запрос на ваш URL обратного вызова с пользовательским заголовком HTTP 'HTTP_RID' установлен в 'test'.

После успешного выполнения вы должны получить идентичный ответ, представленный ниже:

[app][2023-08-10 17:42:16] Callback server is working

D. Настройка Crawlbase Crawler с вашим URL обратного вызова

Теперь, когда мы создали работающий сервер обратного вызова и успешно спроектировали базу данных, пришло время создать Crawler и интегрировать наш URL обратного вызова в Crawlbase.

Войти в свой Crawlbase учетную запись и перейдите к Создавай Crawler страница. Введите желаемое Crawler назовите и вставьте URL-адрес обратного вызова, который мы создали ранее.

Создавай Crawler

Примечание: Crawlbase назначил Обычный запрос (TCP) Crawler для LinkedIn, поэтому мы должны выбрать эту опцию. Несмотря на то, что выбран Обычный запрос, стоит отметить, что Crawlbase использует продвинутых ботов ИИ с алгоритмами, разработанными для имитации человеческого поведения. Кроме того, используются премиум-резидентные прокси для дальнейшего повышения успешности каждого сканирования.

E. Запустите процессор

Откройте новую консоль или терминал в том же каталоге и активируйте.

1
ПАПКА_ПРОЕКТА$ . .venv/bin/activate

Инициировать сценарий process.py

1
ПАПКА_ПРОЕКТА$ python процесс.py

Этот скрипт должен постоянно работать в фоновом режиме, так как он часто проверяет данные, которые будут поступать из Crawlbase Crawler.

F. Инициировать ползание

Перед запуском ваших запросов, пожалуйста, убедитесь, что вы установили все правильные переменные для ваших скриптов. Получите ваш обычный запрос/TCP-токен из Crawlbase счетом страница.

Перейдите в основной каталог вашего проекта, откройте PROJECT_FOLDER/settings.yml файл и добавьте значение вашего токена TCP и Crawler имя.

1
2
маркер: < >
гусеничный трактор: LinkedInCrawler

Откройте новую консоль или терминал в том же каталоге и активируйте.

1
ПАПКА_ПРОЕКТА$ . .venv/bin/activate

Инициировать сценарий crawl.py

1
ПАПКА_ПРОЕКТА$ python crawl.py

После отправки вашего запроса вы должны заметить, что ваш crawl_requests База данных будет заполнена URL-адресом, который сканируется, RID из Crawlbaseи соответствующий статус, как показано на снимке экрана ниже.

Запросы на сканирование

Часть IV: Crawler мониторинг

The Crawlbase Crawler это универсальная система, которая предлагает полезные функции, включая Live Monitoring, который будет удобен для отслеживания статуса запросов от нашего пользовательского краулера в режиме реального времени. Чтобы попасть на страницу, просто перейдите с вашего Crawler панель инструментов и нажмите на Живой монитор меню.

Crawler живой монитор

Часть V: Заключение

Вот простая блок-схема компонентов, которая суммирует объем нашего проекта:

Компоненты блок-схемы

Подводя итог, можно сказать, что это руководство помогло вам создать эффективный и легко масштабируемый профиль LinkedIn. Crawler через Crawlbase. Данное руководство посвящено решению проблем, связанных со сбором данных из LinkedIn, и предлагает стратегическое решение для получения ценной информации о профессиональном профиле.

Crawlbase, пионер в области веб-сканирования, поставляется со специализированным алгоритмом, разработанным для данных LinkedIn, что обеспечивает плавный процесс скрапинга. Цель проекта — создать сервер обратного вызова Flask, который эффективно асинхронно захватывает профили LinkedIn, сохраняя их в базе данных MySQL. Важно отметить, что в соответствии с условиями LinkedIn используются только общедоступные данные.

От настройки среды и написания скрипта до выполнения кода, это руководство охватывает каждый важный шаг. Вы плавно продвигаетесь, тестируя сервер, настраивая Crawlbase Crawlerи инициирование запросов данных.

Crawler Мониторинг предлагает информацию в реальном времени по мере продвижения вперед, обеспечивая улучшенный контроль над процессом. Вооружившись этим руководством, вы готовы использовать всю мощь Crawlbase, создание динамического профиля LinkedIn Crawler который подпитывает ваши проекты бесценной информацией LinkedIn.

Наконец, перейдите на страницу GitHub если вы хотите получить полную кодовую базу этого проекта.

Часть VI: Часто задаваемые вопросы

В: Как отправить дополнительные данные в мой асинхронный запрос и получить их обратно на моем сервере обратного вызова?

Вы можете пройти callback_headers параметр вашего запроса. Например, предположим, что мы хотим добавить дополнительные данные, например BATCH-ID и CUSTOMER-ID на каждый запрос:

1
2
3
4
идентификатор_партии = 'a-batch-id'
идентификатор_клиента = 'a-идентификатор-клиента'
raw_callback_headers = f'BATCH-ID:{token_id}|ИДЕНТИФИКАТОР КЛИЕНТА:{идентификатор_клиента}'
encoded_callback_headers = urllib.parse.quote(raw_callback_headers, safe='')

Затем добавьте encoded_callback_headers к параметру url в запросе.

Пример:

1
crawlbase_api_url = f'https://api.crawlbase.com?token=mynormaltoken&callback=true&crawler=LinkedIn-Crawler&url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Fwilliamhgates%2F&autoparse=true&callback_headers={закодированные_заголовки_обратных_вызовов}'

Вы можете получить эти значения в нашем сервере обратного вызова через заголовки HTTP-запроса. Так что в нашем примере, BATCH-ID и CUSTOMER-ID будет извлечен как:

1
2
batch_id = request.headers.get(«BATCH-ID»)
customer_id = request.headers.get(«ИДЕНТИФИКАТОР-КЛИЕНТА»)

Для получения более подробной информации посетите эту часть Crawlbase документации.

В. Как защитить свой вебхук?

Вы можете защитить конечную точку веб-перехватчика используя любую комбинацию следующих методов:

  • Прикрепите к вашему запросу пользовательский заголовок, содержащий токен, наличие которого вы будете проверять в веб-хуке.
  • Используйте параметр URL в своем URL, проверяя его существование во время запроса вебхука. Например: yourdomain.com/2340JOiow43djoqe21rjosi?token=1234.
  • Ограничить прием только POST-запросов.
  • Проверьте наличие определенных ожидаемых заголовков, таких как Pc-Status, Original-Status, rid, и т.д.

В качестве примечания: мы не рекомендуем вносить IP-адреса в белый список, поскольку наши сканеры могут иметь разные IP-адреса, и эти IP-адреса могут меняться без предварительного уведомления.

Законность веб-скрапинга, как и сбора данных LinkedIn, сложна. Дело hiQ Labs против LinkedIn Corp., Девятый округ постановил, что парсинг общедоступных данных может не нарушать Закон о компьютерном мошенничестве и злоупотреблении (CFAA). Однако это относится к данной юрисдикции и толкованию CFAA. Законность парсинга веб-данных зависит от таких факторов, как характер данных, используемые методы, соглашения и законы юрисдикции.

Копирование контента, защищенного авторским правом, или несоблюдение условий использования может привести к юридическим проблемам. Вот почему Crawlbase позволяет извлекать только общедоступные данные — данные, к которым можно получить доступ без сеанса входа в систему.

Если вам требуются дополнительные разъяснения относительно того, как это применимо к вашей ситуации, рекомендуется обратиться за консультацией к профессиональному юристу для получения точных рекомендаций.

В. Какие еще типы пользовательских данных я могу получить от Crawlbase Парсер LinkedIn?

Наиболее ценные и распространенные данные, которые можно извлечь из профилей LinkedIn, следующие:

  1. Имя: Полное имя пользователя.
  2. Заголовок/Профессия: Краткое описание профессиональной роли или опыта пользователя.
  3. Количество связей: количество связей пользователя на LinkedIn.
  4. Местоположение: Географическое местоположение пользователя.
  5. Изображение обложки: необязательное изображение баннера, отображаемое в верхней части профиля пользователя.
  6. Изображение профиля: Изображение профиля пользователя.
  7. URL-адрес профиля: уникальный веб-адрес профиля пользователя LinkedIn.
  8. Информация о должности: сведения о текущих и прошлых должностях пользователя.
  9. Информация об образовании: информация об образовании пользователя.
  10. Опыт: всесторонний обзор опыта работы и истории карьеры пользователя.
  11. Действия: Созданные пользователями посты, статьи и другие действия в LinkedIn.
  12. Квалификации: Дополнительные сертификаты или квалификации, полученные пользователем.
  13. Организации: сведения об организациях, с которыми связан пользователь.

В. Зачем использовать Flask для вебхука?

  1. Производство на заказ: Flask — это веб-фреймворк Python, позволяющий создавать высоконастраиваемую конечную точку веб-перехватчика. Вы можете определить поведение, аутентификацию и логику обработки в соответствии с вашими конкретными потребностями.
  2. Гибкость: Flask предоставляет вам гибкость в обработке различных типов входящих данных, таких как JSON, данные форм или файлы. Это важно при работе с различными типами полезных нагрузок веб-перехватчиков.
  3. Интеграция: Серверы обратного вызова Flask могут легко интегрироваться с вашими существующими приложениями или службами на основе Python. Это делает удобным включение данных веб-перехватчиков в ваши рабочие процессы.
  4. Аутентификация и безопасность: Вы можете реализовать механизмы аутентификации и меры безопасности на своем сервере веб-перехватчиков Flask, чтобы гарантировать, что только авторизованные источники смогут активировать сервер.
  5. Отладка и ведение журнала: Flask предоставляет инструменты для отладки и ведения журнала, которые могут быть невероятно полезны при мониторинге поведения вашего сервера веб-перехватчиков и диагностике любых проблем.
  6. Масштабирование и развертывание: Приложения Flask можно развертывать в различных средах хостинга, что позволяет масштабировать сервер веб-перехватчиков по мере необходимости.
  7. Сообщество и ресурсы: У Flask большое и активное сообщество, а это значит, что вы можете легко найти учебные пособия, документацию и сторонние пакеты, которые помогут вам создать и поддерживать свой сервер webhook.

В. Зачем выполнять более сложное асинхронное сканирование вместо синхронного?

Синхронное сканирование обрабатывает задачи последовательно, что может быть проще, но медленнее, особенно когда требуется ожидание. Асинхронное сканирование обрабатывает задачи одновременно, что приводит к повышению производительности и использованию ресурсов. Оно также идеально подходит для обработки большого количества задач одновременно.

Реализация сложнее, и отладка может быть более сложной, но в этом случае плюсы значительно перевешивают минусы. Вот почему Crawlbase продвигает асинхронное сканирование для LinkedIn.