
Deseja saber qual é a situação no mercado de trabalho, especialmente no campo da ciência de dados?
Se você conhece Python e Pandas, a análise de headhunter parece uma das maneiras mais confiáveis e fáceis.
O código funciona em Python3.6 e Pandas 0.24.2
O Ipython pode ser baixado aqui .
Para verificar a versão do console do Pandas (Linux / MacOS):
ipython
E então na linha de comando
#ipython import pandas as pd pd.__version__
# () pip install pandas==0.24.2
Já configurou tudo? Vamos lá!
Parsim em Python
HH permite que você encontre trabalho na Rússia. Esse recurso de recrutamento possui o maior banco de dados de vagas. HH compartilha uma API conveniente.
Pesquisou um pouco no Google e acabou escrevendo um analisador.
# 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)
Como resultado, obtivemos um arquivo csv com o nome especificado em job_title.
No arquivo especificado com vagas com a frase será baixado
"Analista de dados" e "cientista de dados". Se você deseja alterar separadamente a linha para
job_title=['Data Analyst', 'Data Scientist']
Então você recebe 2 arquivos com esses nomes.
Curiosamente, existem outros operadores além de "e". Com a ajuda deles, você pode procurar correspondências exatas. Mais detalhes aqui.
https://hh.ru/article/309400
Que horas são? É hora dos pandas!
Os anúncios coletados dessa maneira serão divididos em grupos de acordo com as informações contidas neles ou com uma descrição de seus metadados. Por exemplo: cidade; posição ficha de pagamento; categoria de trabalho. Nesse caso, um único anúncio pode pertencer a várias categorias.
Cuidarei dos dados relacionados à posição de "cientista de dados" usando o jupyter-notebook. https://jupyter.org/

O que fazer para alterar o nome da coluna "Sem nome"?

A questão mais importante - ZP
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']
Acabou por dividir os salários em moedas, você pode tentar fazer a análise sozinho, por exemplo, apenas para o euro. Agora só vou lidar com salários em rublos
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")
Finalmente, aprendemos cerca de 150 mil rublos, conforme o esperado .
Para o salário médio, eu tinha as seguintes condições:
- não considerou vagas nas quais não há salário especificado (df.salary.dropna)
- levou apenas salários em rublos
- se houvesse um plugue, assumia um valor médio (por exemplo, um plugue de 10.000 a 20.000 → 15.000).
Eu direi o seguinte aos trolls, pessoas de mente fraca e amantes de procurar um significado secreto: Eu não sou um funcionário do hh.ru; Este artigo não é um anúncio publicitário; Eu não recebi um centavo por ela. Boa sorte a todos.
Bônus
Como é a demanda de junho no campo Ciência de Dados?

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 )
EDIT:
Zoldaten User Version
Analisador hh
O código não é protegido por direitos autorais, exceto por algumas muletas.
# !/usr/bin/python3 # -*- coding: utf-8 -*- import sys import xlsxwriter # pip install XlsxWriter import requests # pip install requests from bs4 import BeautifulSoup as bs # pip install beautifulsoup4 headers = {'accept': '*/*', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'} vacancy = input(' : ') base_url = f'https://hh.ru/search/vacancy?area=1&search_period=30&text={vacancy}&page=' # area=1 - , search_period=3 - 30 pages = int(input(' - : ')) #+ jobs =[] def hh_parse(base_url, headers): zero = 0 while pages > zero: zero = str(zero) session = requests.Session() request = session.get(base_url + zero, headers = headers) if request.status_code == 200: soup = bs(request.content, 'html.parser') divs = soup.find_all('div', attrs = {'data-qa': 'vacancy-serp__vacancy'}) for div in divs: title = div.find('a', attrs = {'data-qa': 'vacancy-serp__vacancy-title'}).text compensation = div.find('div', attrs={'data-qa': 'vacancy-serp__vacancy-compensation'}) if compensation == None: # compensation = 'None' else: compensation = div.find('div', attrs={'data-qa': 'vacancy-serp__vacancy-compensation'}).text href = div.find('a', attrs = {'data-qa': 'vacancy-serp__vacancy-title'})['href'] try: company = div.find('a', attrs = {'data-qa': 'vacancy-serp__vacancy-employer'}).text except: company = 'None' text1 = div.find('div', attrs = {'data-qa': 'vacancy-serp__vacancy_snippet_responsibility'}).text text2 = div.find('div', attrs = {'data-qa': 'vacancy-serp__vacancy_snippet_requirement'}).text content = text1 + ' ' + text2 all_txt = [title, compensation, company, content, href] jobs.append(all_txt) zero = int(zero) zero += 1 else: print('error') # Excel workbook = xlsxwriter.Workbook('Vacancy.xlsx') worksheet = workbook.add_worksheet() # bold = workbook.add_format({'bold': 1}) bold.set_align('center') center_H_V = workbook.add_format() center_H_V.set_align('center') center_H_V.set_align('vcenter') center_V = workbook.add_format() center_V.set_align('vcenter') cell_wrap = workbook.add_format() cell_wrap.set_text_wrap() # worksheet.set_column(0, 0, 35) # A https://xlsxwriter.readthedocs.io/worksheet.html#set_column worksheet.set_column(1, 1, 20) # B worksheet.set_column(2, 2, 40) # C worksheet.set_column(3, 3, 135) # D worksheet.set_column(4, 4, 45) # E worksheet.write('A1', '', bold) worksheet.write('B1', '', bold) worksheet.write('C1', '', bold) worksheet.write('D1', '', bold) worksheet.write('E1', '', bold) row = 1 col = 0 for i in jobs: worksheet.write_string (row, col, i[0], center_V) worksheet.write_string (row, col + 1, i[1], center_H_V) worksheet.write_string (row, col + 2, i[2], center_H_V) worksheet.write_string (row, col + 3, i[3], cell_wrap) # worksheet.write_url (row, col + 4, i[4], center_H_V) worksheet.write_url (row, col + 4, i[4]) row += 1 print('OK') workbook.close() hh_parse(base_url, headers)