habrahabr

Считаем среднюю ЗП «дата-саентолога». Парсим hh.ru с помощью pandas/python

  • воскресенье, 25 августа 2019 г. в 00:19:49
https://habr.com/ru/post/464823/
  • Python
  • Data Mining
  • Открытые данные



Хочешь узнать, какая ситуация на рынке труда, особенно в области "дата-сайенс"?
Если знаешь Python и Pandas, парсинг Хедхантера это самый надежный и легкий способ.
Код работает на Python3.6 и Pandas 0.24.2
Ipython можно скачать здесь.
Чтобы проверить версию Pandas(Linux/MacOS) console:


ipython

И потом в командной строке


#ipython
import pandas as pd
pd.__version__

#Если нет подходящей версии(консоль)

pip install pandas==0.24.2

Уже все настроили? Поехали!


Парсим на Python


HH позволяет найти работу в России. Данный рекрутинговый ресурс обладает самой большой базой данных вакансий. HH делиться удобным api.


Немного погуглил и вот получилось написать парсер.


#код в ссылке https://gist.github.com/fuwiak/9c695b51c33b2e052c5a721383705a9c
#код с ссылки запускаем так(BASH) python3 hh_parser.py
import requests
import pandas as pd

number_of_pages = 100
#number_of_ads = number_of_pages * per_page

job_title = ["'Data Analyst' and 'data scientist'"]
for job in job_title:
    data=[]
    for i in range(number_of_pages):
        url = 'https://api.hh.ru/vacancies'
        par = {'text': job, 'area':'113','per_page':'10', 'page':i}
        r = requests.get(url, params=par)
        e=r.json()
        data.append(e)
        vacancy_details = data[0]['items'][0].keys()
        df = pd.DataFrame(columns= list(vacancy_details))
        ind = 0
        for i in range(len(data)):
            for j in range(len(data[i]['items'])):
                df.loc[ind] = data[i]['items'][j]
                ind+=1
    csv_name = job+".csv"
    df.to_csv(csv_name)

В итоге мы получили файл csv с названием указанным в job_title.
В указанном будет загружен один файл с вакансиями с фразой
«Data Analyst» и «data scientist». Если хотите отдельно поменяйте строку на


job_title=['Data Analyst', 'Data Scientist']

Тогда вы получаете 2 файла с этими названиями.


Что интересно, есть и другие операторы кроме «and». С их помощью можно искать точные совпадения. Подробнее по ссылке.


https://hh.ru/article/309400


What time is it? Its Pandas Time!


Собранные таким образом объявления будут разделены на группы в соответствии с информацией содержащейся в них или описанием их метаданных. Например: город; позиция; вилка зарплаты; категория вакансии. В этом случае одно объявление может принадлежать нескольким категориям.
Сейчас займусь данным, которые связанны с позицией "data scientist", используя jupyter-notebook. https://jupyter.org/



Что делать чтобы поменять название колонки “Unnamed”?



Самый главный вопрос — ЗП


import ast # run code from string for example ast.literal_eval("1+1") 

salaries = df.salary.dropna() # remove all NA's from dataframe
currencies = [ast.literal_eval(salaries.iloc[i])['currency'] for i in range(len(salaries))]
curr = set(currencies) #{'EUR', 'RUR', 'USD'}

#divide dataframe salararies by currency
rur = [ast.literal_eval(salaries.iloc[i]) for i in range(len(salaries)) if ast.literal_eval(salaries.iloc[i])['currency']=='RUR']
eur = [ast.literal_eval(salaries.iloc[i]) for i in range(len(salaries)) if ast.literal_eval(salaries.iloc[i])['currency']=='EUR']
usd = [ast.literal_eval(salaries.iloc[i]) for i in range(len(salaries)) if ast.literal_eval(salaries.iloc[i])['currency']=='USD']

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


fr = [x['from'] for x in rur] # lower range of salary
fr = list(filter(lambda x: x is not None, fr)) # remove NA's from lower range [0, 100, 200,...]

to = [x['to'] for x in rur] #upper range of salary
to = list(filter(lambda x: x is not None, to)) #remove NA's from upper range [100, 200, 300,...]

import numpy as np
salary_range = list(zip(fr, to)) # concatenate upper and lower range  [(0,100), (100, 200), (200, 300)...]
av = map(np.mean, salary_range) # convert [(0,100), (100, 200), (200, 300)...] to [50, 150, 250,...]
av = round(np.mean(list(av)),1) # average value from [50, 150, 250,...]

print("average salary as Data Scientist ", av, "rubles")

Наконец-то узнали, около 150 тыс рублей, как ожидаемо.


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


  • не считал вакансии, в которых нет указанной зарплаты (df.salary.dropna)
  • взял только зарплаты в рублях
  • если была вилка, тогда взял среднее значение (например, вилка от 10000 rub до 20000 rub → 15000 rub).

Троллям, слабоумным и любителям искать тайный смысл скажу следующее: я не являюсь сотрудником компании hh.ru; эта статья не является рекламой; я не получил за неё ни копейки. Всем удачи.


Бонус


Как востребованы в области "Data Science" джуны?


from collections import Counter

vacancy_names = df.name # change here to change source of data/words etc
cloud = Counter(vacancy_names)
from wordcloud import WordCloud, STOPWORDS
stopwords = set(STOPWORDS)
cloud = ''
for x in list(vacancy_names):
    cloud+=x+' '
wordcloud = WordCloud(width = 800, height = 800, 

                stopwords = stopwords, 
                min_font_size = 8,background_color='white'
                     ).generate(cloud)

import matplotlib.pylab as plt
plt.figure(figsize = (16, 16)) 
plt.imshow(wordcloud)
plt.savefig('vacancy_cloud.png')

[REPO] (https://github.com/fuwiak/HH)