Парсинг сайта вакансии на Python
![Парсинг сайта вакансии на Python](/images/articles/python-parse-vacancies.jpg)
Одно из самых популярных направлений использования языка Python является парсинг данных с веб-сайтов. Под парсингом понимают процесс разбора веб-страницы с целью извлечь из нее данные и придать им некий структурированный вид.
В данной статье я покажу Вам пример того, как собрать данные о вакансиях с сайта. Подход, который будет применяться в примере, можно будет использовать и для сбора информации с других сайтов.
Также учтите, что существуют рекомендации, которых стоит придерживаться, при использовании парсинга:
- Извлекаемое содержимое не должно быть защищен авторским правом
- Парсинг не должен замедлять или иным образом мешать работе сайта
- Парсинг не должен нарушать условия использования сайта
- Нельзя извлекать персональный данные пользователя
Проект создается в PyCharm Community.
Итак, для получения и извлечения данных мы будем использовать следующие библиотеки, которые Вам нужно будет установить:
Комманда установки
$ pip install -r requirements.txt
Файл requirements.txt
beautifulsoup4==4.10.0
certifi==2021.10.8
charset-normalizer==2.0.12
idna==3.3
lxml==4.8.0
pkg_resources==0.0.0
requests==2.27.1
soupsieve==2.3.1
urllib3==1.26.8
После того как зависимости установятся, перейдем непосредственно к коду:
import json
import time
import requests
from bs4 import BeautifulSoup
# config
URL = 'https://{ВАШ_САЙТ}/vacancies/middle_php_developer'
# заголовки запроса
headers = {
'User-Agent': 'Firefox/99.0'
}
# возвращает содержимое страницы в виде текста
def get_page_content(url):
text = ''
res = requests.get(url, headers=headers)
if res.status_code != 404:
return res.text
return text
# класс представляет одну вакансию
# аттрибуты класса - части вакансии из разметки
class Vacancy:
url: str
company: str
companyAbout: str
title: str
salary: str
requiredSkills: str
locationAndTypeOfEmployment: str
description: str
# преобразование объекта данного класса в строку возвращает отформатированный json
def __str__(self) -> str:
return json.dumps(self.__dict__, ensure_ascii=False, indent=4)
# извлечение вакансии из текстового содержимого страницы
def parse_vacancy(url: str) -> Vacancy:
vacancyObj = Vacancy()
try:
text = get_page_content(url)
bs = BeautifulSoup(text, 'lxml')
# интересующие нас данные извлекаем с помощью CSS селекторов - возможность библиотеки BeautifulSoup
company = bs.select_one('.company_name')
companyAbout = bs.select_one('.company_about')
title = bs.select_one('.page-title__title')
salary = bs.select_one(
'body > div.page-container > div > div > div > div > article > section:nth-child(1) > div '
'> div > div > div:nth-child(3)')
description = bs.select_one('.job_show_description__vacancy_description')
requiredSkills = bs.select_one('body > div.page-container > div > div > div > div > article > '
'section:nth-child(1) > div > div > div > div:nth-child(4)')
locationAndTypeOfEmployment = bs.select_one('body > div.page-container > div > div > div > div > article > '
'section:nth-child(1) > div > div > div > div:nth-child(5)')
# собираем данные в объект
vacancyObj.url = url
vacancyObj.company = company.text
vacancyObj.companyAbout = companyAbout.text if companyAbout is not None else ''
vacancyObj.title = title.text
vacancyObj.description = str(description.contents[0])
vacancyObj.salary = salary.text.replace('Зарплата', '')
vacancyObj.requiredSkills = requiredSkills.text.replace('Требуемые навыки', '')
vacancyObj.locationAndTypeOfEmployment = locationAndTypeOfEmployment.text.replace('Местоположение и тип '
'занятости', '')
# обработка ошибок
except AttributeError as ae:
print(url)
print(ae)
except requests.RequestException as e:
print(e)
return vacancyObj
# извлечение всех ссылок на вакансии со страницы
def get_all_page_links(text):
bs = BeautifulSoup(text, 'lxml')
links = bs.select('.vacancy-card__title-link')
return [link.get('href') for link in links]
# Циклично обходит все страницы собирая данные и записывает их в файл
def process_page():
vacancies = []
out_file = open(f'parsed/parsed_vacancies.json', 'a')
out_file.write('[')
out_string = ''
counter = 1
for page in range(1, 7):
try:
url = URL + '?page=' + str(page)
res = requests.get(url, headers=headers)
if res.status_code != 404:
links = get_all_page_links(res.text)
# print(links)
# останавливаем запрос на 400 мс, чтобы не нагружать сайт
time.sleep(0.4)
for link in links:
vacancyUrl = f'https://{ВАШ_САЙТ}{link}'
vacancy = parse_vacancy(vacancyUrl)
vacancyStr = str(vacancy)
out_string += vacancyStr
out_string += ',\n'
print(f'{counter}: {vacancyUrl}')
counter += 1
# vacancies.append(str(vacancy))
# останавливаем запрос на 500 мс
time.sleep(0.5)
# print(vacancyUrl)
except requests.RequestException as e:
print(e)
continue
# print(vacancies)
out_file.write(out_string)
out_file.write(']')
out_file.close()
# запускает скрипт
if __name__ == '__main__':
process_page()
Таким образом, после окончания работы данного скрипта в папке parsed Вы должны увидеть файл parsed_vacancies.json со структурированными данными о вакансиях.
-
-
Михаил Русаков
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.