CoderCastrov logo
CoderCastrov
Программирование

Как создать инструмент для парсинга Indeed за 9 минут

Как создать инструмент для парсинга Indeed за 9 минут
просмотров
9 мин чтение
#Программирование
Table Of Content

Использование Python и Selenium для сбора данных о вакансиях на Indeed

Self-made image.

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

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

Поэтому у меня возникла идея: почему бы мне не попробовать парсить списки вакансий на Indeed, чтобы получить всю ключевую информацию непосредственно в базе данных?

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

Давайте вместе научимся создавать такой инструмент! 👇🏻


#1. Настройка нашей среды.

Для разработки такого проекта требуется одна основная библиотека:

  • Selenium** **используется для автоматизации веб-приложений. Она позволяет открывать браузер и выполнять задачи, как это делал бы человек, например, нажимать кнопки и искать определенную информацию на веб-сайтах.

Кроме того, нам нужен драйвер для взаимодействия с нашим браузером. Чтобы настроить нашу среду, сначала нам нужно:

⚠️ Поскольку я являюсь обычным пользователем Google Chrome, я буду использовать его в качестве моего браузера по умолчанию. Просто убедитесь, что вы найдете правильный драйвер для вашего типа и версии браузера!

_Чтобы понять основы Selenium и HTML, рекомендую следующую статью! _:D

Понимание искусства парсинга веб-страниц с использованием Selenium и BeautifulSoup

Основы структуры HTML для извлечения данных с использованием Python

medium.com

#2. Загрузка библиотек

После установки всех необходимых библиотек в нашей среде мы начинаем наш код с загрузки всех них. Кроме selenium, нам понадобятся библиотеки pandas и time, среди других.

#3. Понимание URL-адресов Indeed и определение интересующей нас должности и местоположения.

Если мы перейдем на веб-сайт Indeed, можно легко заметить, что есть два поля для определения интересующей нас должности и местоположения.

Самостоятельно созданное изображение. Главная страница Indeed.

В данном случае я начну искать работу в качестве аналитика данных в США.

Самостоятельно созданное изображение. Показаны поля для ввода ключевых слов для работы и местоположения на Indeed.

Если мы ищем такую работу и местоположение, то можно заметить, что оба ключевых слова отражены в соответствующем URL-адресе.

У нас есть keywords=Data+Scientist&l=USA.

Вот почему мы можем просто изменить URL-адрес напрямую, чтобы выбрать любую работу и местоположение, которые мы хотим - что делает нашу жизнь намного проще! ;)

Мы уверены в этом...?

Indeed работает с национальными страницами - это означает, что он представляет веб-сайт со всеми предложениями работы, специфическими для каждой страны. Поэтому, если вы попытаетесь проверить испанские вакансии на веб-сайте США, результат будет пустым, как вы можете видеть ниже.

Снимок экрана пользовательского интерфейса Indeed. Нет результатов при поиске испанских вакансий в

Поскольку мы хотим иметь возможность переключаться между странами при необходимости, нам нужно это учесть. Самый быстрый и простой способ сделать это?

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

Снимок экрана пользовательского интерфейса Indeed по всему миру. Список URL-адресов по странам.

Прежде чем начать парсинг, нам все еще нужно учесть одну последнюю вещь! Когда мы используем более одного слова, соответствующий URL-адрес поиска будет разделять каждое из слов с помощью “+”.

Таким образом, мы легко можем сгенерировать желаемый URL следующим образом:

  • Определение функции, которая разделяет ввод и добавляет “+” между всеми разными словами.
  • Определение должности и местоположения, которые мы хотим искать.
  • Определение соответствующего URL-адреса

#4. Загрузка драйвера и создание экземпляра

Основная идея здесь заключается в управлении веб-браузером с помощью нашего кода на Python. Для этого нам нужно создать мост между Python и нашим браузером. Вот почему мы создали экземпляр нашего веб-драйвера, используя файл, который мы скачали на шаге 1 - Запомните путь!

После создания экземпляра достаточно просто открыть URL списка вакансий с помощью команды driver.get(). Предыдущий код откроет окно Chrome с нашей веб-страницей Indeed.

Самодельная гифка. Показывает, как с помощью Python мы можем открыть окно Linkedin в нашем браузере.

⚠️ Если вы хотите использовать этот код на длительное время, ваш браузер может получить обновление, и поэтому вам следует также обновить драйвер. Чтобы избежать этого, мы можем легко обновить ChromeDriver непосредственно из Python с помощью следующего кода.

#5. Создание словаря стран и URL-адресов

Если вы не знакомы с парсингом веб-страниц, вы можете щелкнуть правой кнопкой мыши, выбрать "Инспектировать" или нажать "F12". Должно появиться следующее всплывающее окно:

Screenshot of Indeed inspecting elements pop-up.

Если мы проанализируем элементы, мы легко заметим, что все страны содержатся в элементе, называемом "page". Каждая запись о стране содержится в элементе <li>, состоящем из элемента <a>, который содержит ссылку, и элемента <span>, который содержит название страны.

Screenshot of Indeed worldwide UI. Inspecting the elements.

Чтобы получить оба элемента, достаточно получить все элементы <a>, содержащиеся в элементе "page".

  • Название страны можно найти с помощью команды .text - также можно использовать .get_attribute("text")
  • Ссылку можно найти с помощью команды .get_attribute("href")

#6. Определение количества доступных вакансий.

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

Скриншот, показывающий количество доступных вакансий для нашего конкретного поиска.

Для этого мы можем легко найти элемент по его классу с помощью следующей команды: driver.find_element(By.CLASS_NAME,"jobsearch-JobCountAndSortPane-jobCount").get_attribute("Text).

После получения строки нам нужно убедиться, что она преобразуется в целое число. И все! :)

#7. Просмотр вакансий

Результаты поиска на Indeed обычно содержат 15 результатов на странице, отображаемой слева. Каждая вакансия отображается на карточке вакансии.

Screenshot of Indeed inspecting elements pop-up.

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

Чтобы загрузить больше предложений о работе, важно учесть, что вакансии на Indeed работают с помощью числа пагинации в конце страницы.

Screenshot that shows the pagination system of Indeed’s UI.

Это так просто, как нажать кнопку следующей страницы... верно?

Хм... есть еще одна важная вещь, которую нужно учесть. Первый раз, когда мы открываем Indeed, там будет 6 кнопок пагинации, причем 6-я кнопка перейдет на следующую страницу. Однако, начиная со второй страницы, появится дополнительная кнопка для возврата, что делает нашу интересующую кнопку 7-й.

Pagination of the Indeed UI.

Чтобы учесть оба сценария, мы добавляем процедуру 'try — except'. Чтобы найти кнопку, мы будем использовать Xpath для ее поиска.

Locating the next page button using the Xpath option of the inspect elements.

Таким образом, мы можем легко нажать на кнопку следующей страницы с помощью следующей команды!

.find_element(By.XPATH,"next_page_button_xpath").click()

#8. Обнаружение всех элементов.

Если мы снова проинспектируем веб-сайт, мы легко заметим, что каждая карточка работы находится в элементе <li>.

Самостоятельно созданное изображение. Вы можете наблюдать все элементы `<li>` для каждой карточки работы, отображаемой на странице.

В каждой карточке работы мы можем найти элемент <div> с class=cardOutline, который содержит всю сокращенную информацию, которую мы хотим сохранить:

Карточка предложения работы Indeed.
  • Название работы хранится в заголовке <h2> с классом 'jobTitle'.
  • Название компании находится в контейнере тега <span> с классом 'companyName'.
  • Местоположение компании находится в разделе <div> с классом 'company location'.
  • Зарплата находится в разделе <div> с классом 'salary-snippet-container'.
  • Дата публикации находится в разделе <spain> с классом 'date'.
Самостоятельно созданное изображение. Вы можете наблюдать все подэлементы, содержащиеся для каждой карточки работы.

⚠️ Важно знать, что структура веб-страницы может измениться в любое время. Поэтому вам следует попытаться понять, как она работает, проверив элементы самостоятельно.

Чтобы сохранить все эти данные, мы сначала получаем список всех полученных работ на предыдущем шаге, используя driver.find_element.(By.ID,"mosaic-jobResults"). Этот элемент будет содержать все 15 карточек работы.

Поскольку все элементы имеют разные имена классов, мы легко можем использовать driver.find_element(By.CLASS_NAME,"element"), чтобы найти наш элемент, а затем использовать команду .text

  • **Название работы: **.find_element(By.CLASS_NAME,"jobTitle").text
  • Название компании .find_element(By.CLASS_NAME,"companyName").text
  • Местоположение .find_element(By.CLASS_NAME,"companyLocation").text
  • Дата публикации .find_element(By.CLASS_NAME,"date").text

Мы получим дополнительные значения.

  • **Ссылка на работу: **.find_element(By.CLASS_NAME,"jobTitle").find_element(BY.CSS_SELECTOR,"a").get_attribute("href")
  • **Идентификатор работы: **.find_element(By.CLASS_NAME,"jobTitle").find_element(BY.CSS_SELECTOR,"a").get_attribute("id")

Для зарплаты я столкнулся с проблемой. Многие предложения о работе вообще не содержали зарплаты, а у многих других был другой элемент с названием estimated salary.

Поскольку может случиться, что мы попытаемся найти элемент и его вообще не существует, код может вызвать ошибку и остановить наш парсинг. Поэтому я решил снова использовать конструкцию try-except.

        try: 
            job_salary_list.append(ii.find_element(By.CLASS_NAME,"salary-snippet-container").text)
            
        except: 
            try: 
                job_salary_list.append(ii.find_element(By.CLASS_NAME,"estimated-salary").text)
            except: 
                job_salary_list.append(None)

Наконец, нам нужно получить полное описание работы. Для этого потребуется два действия:

  • Нажатие на элемент JobTitle для открытия полного описания работы.
  • Нам нужно использовать команду time.sleep(), чтобы убедиться, что новая страница полностью загружена. ⚠️ Я обычно жду случайное количество секунд, чтобы "имитировать" человеческое поведение.
  • Поиск элемента с описанием с помощью следующей команды: driver.find_element/By.ID, "jobDescriptionText")
  • На всякий случай, если на описание не хватает времени для загрузки, я добавляю конструкцию try-except, чтобы вернуть пустое описание, когда элемент не найден.

Весь код для шагов #7 и #8 можно найти в следующем Gist:

Теперь наш браузер будет прокручивать все доступные работы, щелкая по ним.

#9. Создание нашего pandas dataframe и сохранение его.

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

После этого мы должны получить dataframe, который выглядит следующим образом:

Последним шагом будет сохранение нашего dataframe в виде CSV-файла.

Теперь у нас есть все спарсенные данные, сохраненные на наших компьютерах! :)

Вы можете найти мой код в моем репозитории GitHub webscraping. Вы можете найти как JupyterNotebook, так и проект на Python. Вы можете использовать любой из них. Надеюсь, вам понравится этот материал и вы сможете понять, как парсить информацию с Indeed!

Не стесняйтесь задавать мне любые дополнительные вопросы! :D

Не стесняйтесь обратиться ко мне, если в моем руководстве есть какие-либо недостающие инструкции!


Вы можете подписаться на мою рассылку Medium, чтобы быть в курсе и получать мой контент. Обещаю, он будет уникальным!

Если вы еще не являетесь полным участником Medium, **просто проверьте это здесь, чтобы поддержать меня и многих других авторов. **_Это действительно помогает _:D

Вы также можете найти меня в Twitter и LinkedIn!


Некоторые другие интересные статьи на Medium, которые вам стоит прочитать! :D


Веб-парсинг в 2023 году - разбираемся с основами

И как собирать данные онлайн в 5 простых шагах

blog.devgenius.io

Создание самого большого набора данных о климате

Используя данные Berkeley Earth, python и beautifulsoup

medium.com

Парсинг профиля Linkedin с использованием Python & Selenium

Эта статья написана в январе 2020 года, а текущий макет Linkedin выглядит следующим образом:

gerrysabar.medium.com