Лучшие практики парсинга веб-сайтов с использованием пагинации на примере indeed.com
Table Of Content
В этой статье я расскажу, как собирать данные с сайта поиска работы indeed.com. Indeed - это бесплатный сервис для соискателей, где вы можете загрузить свое резюме, создать уведомления о вакансиях, искать работу, сохранять ее и подавать заявки лично.
Давайте начнем, сначала посетите сайт indeed.com, там есть две колонки: "Что" и "Где". В колонке "Что" введите тип работы, а в колонке "Где" укажите местоположение. Например, я заполнил его типом работы "python developer" и местоположением "New York". Нажмите "Найти вакансии".
В этом случае я ограничиваюсь только типом работы, названием компании, веб-сайтом компании и местоположением. Если вы хотите добавить что-то еще, конечно, это лучше, потому что это может помочь развить навыки.
Хорошо, сначала подготовьте инструменты, которые я использую:
- Веб-браузер (Chrome)
- IDE (Pycharm)
- Я использую язык программирования Python
- Интернет-соединение, конечно
Откройте IDE, затем установите необходимые пакеты. Первый пакет - Requests, а второй - Beautifulsoup. В терминале введите и нажмите Enter:
pip install requests beautifulsoup4
Откройте браузер снова, щелкните правой кнопкой мыши и выберите "Инспектировать". Во вкладке выберите "Сеть", затем перезагрузите страницу. Щелкните на одном из элементов во вкладке "Имя", затем во вкладке "Заголовки" прокрутите вниз, пока не найдете "user-agent", скопируйте его и вставьте в IDE, поместив его в переменную. Введите URL веб-сайта и поместите его в переменную. Не забудьте импортировать requests и BeautifulSoup. Попробуйте проверить, ответит ли страница веб-сайта или нет. Если код состояния равен 200, это означает, что запрос выполнен успешно.
import requests
from bs4 import BeautifulSoup
header = {'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'}
url = 'https://www.indeed.com/jobs?'
req = requests.get(url)
print(req.status_code)
Создание функции для получения общего количества страниц
Чтобы отделить основную программу от других программ, создается функция, которая делает код более аккуратным и профессиональным, и, что не менее важно, функцию можно использовать в других случаях, импортируя ее.
def get_total_pages(query, location):
params = {
'q': query,
'l': location
}
req = requests.get(url, params=params, headers=header)
Получение общего количества элементов
Внутри функции я создал новую переменную для объекта soup, затем внутри переменной я вызвал функцию из пакета BeautifulSoup с указанием html.parser.
Вернитесь в браузер, щелкните правой кнопкой мыши, затем выберите "Инспектировать", прокрутите вниз, пока не найдете раздел "pagination". Найдите класс, содержащий пагинацию, затем скопируйте класс и не забудьте тег. Затем загрузите его в новую переменную. Перед циклом добавьте пустую переменную списка, чтобы хранить результат. Результатом цикла является целое число, поэтому его можно обработать, чтобы получить наибольшее число с помощью функции max, а затем вернуть результат.
total_pages = []
soup = BeautifulSoup(req.text, 'html.parser')
pagination = soup.find('ul', "pagination-list")
pages = pagination.find_all('li')
for page in pages:
total_pages.append(page.text)
total = int(max(total_pages))
return total
Создание функции для получения нескольких элементов
Чтобы получить необходимые элементы, осмотрите страницу веб-сайта и выделите раздел, содержащий тип работы, местоположение и название компании, затем выполните цикл для получения нужных данных, здесь я беру тип работы, местоположение и название компании. Добавьте пустую переменную списка перед циклом.
def get_all_item(query, location, start, page):
params = {
'q': query,
'l': location,
'start': start
}
req = requests.get(url, params=params, headers=header)
with open('temp/req.html', 'w+') as outfile:
outfile.write(req.text)
outfile.close()
soup = BeautifulSoup(req.text, 'html.parser')
# scrape
details = soup.find_all('table', 'jobCard_mainContent big6_visualChanges')
new_list = []
for detail in details:
job_title = detail.find('h2', 'jobTitle').text
company = detail.find('span', 'companyName')
location = detail.find('div', 'companyLocation').text
company_name = company.text
try:
company_link = site + company.find('a')['href']
except:
company_link = 'Ссылка недоступна'
# sorting
data_dict = {
'Название вакансии': job_title,
'Название компании': company_name,
'Веб-сайт компании': company_link
}
new_list.append(data_dict)
# json
try:
os.mkdir('json_result')
except FileExistsError:
pass
with open(f'json_result/{query}_in_{location}_page_{page}.json', 'w+') as json_data:
json.dump(new_list, json_data)
print('JSON создан')
return new_list
В приведенной выше функции я создал скрипт для создания папки и скрипта в формате JSON.
Создание функции для создания документа
def create_document(dataFrame, filename):
try:
os.mkdir('data_result')
except FileExistsError:
pass
df = pd.DataFrame(dataFrame)
df.to_csv(f'data_result/{filename}.csv', index=False)
df.to_excel(f'data_result/{filename}.xlsx', index=False)
# generate
print(f'{filename}.csv и {filename}.xlsx созданы')
Эта функция используется для создания файлов в формате CSV и Excel.
Создание функции для запуска программы
def run():
query = input('Введите ваш запрос: ')
location = input('Введите ваше местоположение: ')
total = get_total_pages(query, location)
counter = 0
final_result = []
for page in range(total):
page += 1
counter += 10
final_result += get_all_item(query, location, counter, page)
# formatting data
try:
os.mkdir('reports')
except FileExistsError:
pass
with open('reports/{}.json'.format(query), 'w+') as final_data:
json.dump(final_result, final_data)
print('Данные созданы')
# created document
create_document(final_result, query)
В этой функции я объединяю созданные функции. В этой функции я выполняю цикл для работы с пагинацией, затем добавляю его в пустой список. После получения данных я генерирую данные на основе содержимого списка. Увидимся в следующей статье.