programadores Python rastreamento de dados cerca de cem mil postos de trabalho, dizer-lhe que tipo de talento e habilidades na mais favorável! | Planos Força ...

Autor | Huang supremo, Zebian | Guo Rui

Produzido | CSDN blogue

Foto da capa | CSDN baixar o China visuais

Com o rápido desenvolvimento da tecnologia, os dados mostram um crescimento explosivo, ninguém não pode escapar lidar com dados, para a sociedade "dados" aspectos da procura de talentos também está aumentando. Portanto, a compreensão do negócio atual que tipo de recrutamento de talentos? Que tipo de habilidades necessárias? Seja para estudantes ou para quem procura emprego, parecia necessário.

Com base nisso, para o site de recrutamento 51job rastejando uma grande dados nacionais, análise de dados, mineração de dados, aprendizado de máquina, inteligência artificial e outros trabalhos trabalhos relacionados. Análise e comparação de salários, requisitos académicos de diferentes posições, análise e comparação das diferentes regiões, a demanda da indústria para os casos relacionados com o talento, análise e comparação das diferentes posições do conhecimento, requisitos de habilidade.

O projeto final resulta no futuro, como segue:

efeitos dinâmicos são os seguintes:

Informações Crawling (com base em dados 51job site de recrutamento crawling)

  • Rastejando Post: grandes volumes de dados, análise de dados, aprendizado de máquina e posições relacionadas inteligência artificial;

  • campos rastejando: nome da empresa, nome do trabalho, endereço de trabalho, folha de pagamento, Tempo, descrições de trabalho, tipo de empresa, número de empregados, a indústria;

  • Descrição: Baseado no site de recrutamento 51job, exigimos pesquisa nacional para as posições "dados", cerca de 2000. Nós rastejando campo, tanto uma página de informações, há cerca de duas páginas da informação;

  • Rastejando idéias: primeiro fazer uma página para uma determinada página de dados analíticos e, em seguida, as duas páginas para fazer uma resolução, então, finalmente, virar a página;

  • Use ferramentas: Python + solicitações + lxml + pandas + tempo

  • modo de análise site: XPath

1) biblioteca relacionados com a importação

import requests
import pandas as pd
from pprint import pprint
from lxml import etree
import time
import warnings
warnings.filterwarnings("ignore")

2) descrição da página

# 第一页的特点
https://search.51job.com/list/000000,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE,2,1.html?
# 第二页的特点
https://search.51job.com/list/000000,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE,2,2.html?
# 第三页的特点
https://search.51job.com/list/000000,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE,2,3.html?

Nota: Para a observação através da página, pode ser visto em uma série de mudanças no lugar, então apenas fazer concatenação, então se arrastou até o ciclo.

3) o código completo de rastreamento

import requests
import pandas as pd
from pprint import pprint
from lxml import etree
import time
import warnings
warnings.filterwarnings("ignore")


for i in range(1,1501):
    print("正在爬取第" + str(i) + "页的数据")
    url_pre = "https://search.51job.com/list/000000,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE,2,"
    url_end = ".html?"
    url = url_pre + str(i) + url_end
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }
    web = requests.get(url, headers=headers)
    web.encoding = "gbk"
    dom = etree.HTML(web.text)
    # 1、岗位名称
    job_name = dom.xpath('//div[@class="dw_table"]/div[@class="el"]//p/span/a[@target="_blank"]/@title')
    # 2、公司名称
    company_name = dom.xpath('//div[@class="dw_table"]/div[@class="el"]/span[@class="t2"]/a[@target="_blank"]/@title')
    # 3、工作地点
    address = dom.xpath('//div[@class="dw_table"]/div[@class="el"]/span[@class="t3"]/text()')
    # 4、工资
    salary_mid = dom.xpath('//div[@class="dw_table"]/div[@class="el"]/span[@class="t4"]')
    salary = [i.text for i in salary_mid]
    # 5、发布日期
    release_time = dom.xpath('//div[@class="dw_table"]/div[@class="el"]/span[@class="t5"]/text()')
    # 6、获取二级网址url
    deep_url = dom.xpath('//div[@class="dw_table"]/div[@class="el"]//p/span/a[@target="_blank"]/@href')
    RandomAll = []
    JobDescribe = []
    CompanyType = []
    CompanySize = []
    Industry = []
    for i in range(len(deep_url)):
        web_test = requests.get(deep_url[i], headers=headers)
        web_test.encoding = "gbk"
        dom_test = etree.HTML(web_test.text)
        # 7、爬取经验、学历信息,先合在一个字段里面,以后再做数据清洗。命名为random_all
        random_all = dom_test.xpath('//div[@class="tHeader tHjob"]//div[@class="cn"]/p[@class="msg ltype"]/text()')
        # 8、岗位描述性息
        job_describe = dom_test.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]/p/text()')
        # 9、公司类型
        company_type = dom_test.xpath('//div[@class="tCompany_sidebar"]//div[@class="com_tag"]/p[1]/@title')
        # 10、公司规模(人数)
        company_size = dom_test.xpath('//div[@class="tCompany_sidebar"]//div[@class="com_tag"]/p[2]/@title')
        # 11、所属行业(公司)
        industry = dom_test.xpath('//div[@class="tCompany_sidebar"]//div[@class="com_tag"]/p[3]/@title')
        # 将上述信息保存到各自的列表中
        RandomAll.append(random_all)
        JobDescribe.append(job_describe)
        CompanyType.append(company_type)
        CompanySize.append(company_size)
        Industry.append(industry)
        # 为了反爬,设置睡眠时间
        time.sleep(1)
    # 由于我们需要爬取很多页,为了防止最后一次性保存所有数据出现的错误,因此,我们每获取一夜的数据,就进行一次数据存取。
    df = pd.DataFrame()
    df["岗位名称"] = job_name
    df["公司名称"] = company_name
    df["工作地点"] = address
    df["工资"] = salary
    df["发布日期"] = release_time
    df["经验、学历"] = RandomAll
    df["公司类型"] = CompanyType
    df["公司规模"] = CompanySize
    df["所属行业"] = Industry
    df["岗位描述"] = JobDescribe
    # 这里在写出过程中,有可能会写入失败,为了解决这个问题,我们使用异常处理。
    try:
        df.to_csv("job_info.csv", mode="a+", header=None, index=None, encoding="gbk")
    except:
        print("当页数据写入失败")
    time.sleep(1)
print("数据爬取完毕,是不是很开心!!!")

Aqui você pode ver, estamos rastreando os mais de 1.000 páginas de dados para a análise final. Portanto, cada um leva uma subida de dados, não um armazenamento de dados, um armazenamento de uma só vez para evitar, eventualmente, levar ao fracasso. Ao mesmo tempo, de acordo com os testes, há algumas páginas para armazenamento de dados, vai levar ao fracasso, de modo a não afectar a execução do código por trás, usamos a manipulação "try-exceto" exceção.

Em uma página, que arrastou o "nome do trabalho", "nome da empresa", "local de trabalho", "salários", "Date", "URL url secundário" nestes domínios.

Em duas páginas, que se arrastou até "experiência, informação sobre a educação", "descrição do trabalho", "tipos de empresa", "tamanho da empresa", "Indústria" nestes domínios.

pré-processamento de dados

Rastejando tirada da secção de dados para fazer uma exposição, ele pode ser visto a partir da confusão de dados. dados desarrumado não é propício para a nossa análise, é necessário fazer um estudo dos dados alvo de pré-processamento, nós finalmente obter os dados podem ser usados ​​para a exibição visual.

1) e leitura de dados relacionados ao banco de dados de importação

df = pd.read_csv(r"G:\8泰迪\python_project\51_job\job_info1.csv",engine="python",header=None)
# 为数据框指定行索引
df.index = range(len(df))
# 为数据框指定列索引
df.columns = ["岗位名","公司名","工作地点","工资","发布日期","经验与学历","公司类型","公司规模","行业","工作描述"]

2) de duplicação de dados

Acreditamos que uma empresa com o mesmo nome eo nome da empresa e liberação trabalho, ele é considerado como duplicatas. Portanto, a função drop_duplicates (subconjunto = []), baseado no "nome do trabalho" e "nome da empresa" fazer rejeitar uma valores duplicados.

# 去重之前的记录数
print("去重之前的记录数",df.shape)
# 记录去重
df.drop_duplicates(subset=["公司名","岗位名"],inplace=True)
# 去重之后的记录数
print("去重之后的记录数",df.shape)

Tratamento 3) campo nome do trabalho

① explorar campo de nome do trabalho

df["岗位名"].value_counts()
df["岗位名"] = df["岗位名"].apply(lambda x:x.lower())

Descrição: Primeiro, fazemos uma frequência estatística de ocorrência de cada post, você pode ver que "o campo nome do trabalho" muito confuso, não para nós para fazer a análise estatística. Então, vamos colocar o nome das letras maiúsculas unificados em letras minúsculas, que significa "AI" e "Ai" pertencem à mesma coisa.

Postes ② estrutura que você deseja analisar, fazer uma filtragem de dados

job_info.shape
target_job = ['算法', '开发', '分析', '工程师', '数据', '运营', '运维']
index = [df["岗位名"].str.count(i) for i in target_job]
index = np.array(index).sum(axis=0) > 0
job_info = df[index]
job_info.shape

Descrição: Primeiro, nós construímos a palavra chave acima posições de destino sete. Em seguida, usando a contagem () função cada registro estatístico, contém sete palavras-chave, se você deixar este campo inclui, mas não está incluído para apagar este campo. Depois de ver a triagem final, quantos registros ainda restante.

③ postes da baliza normalizada (porque o alvo é o trabalho muito confuso, precisamos unificar-lo)

job_list = ['数据分析', "数据统计","数据专员",'数据挖掘', '算法', 
            '大数据','开发工程师', '运营', '软件工程', '前端开发',
            '深度学习', 'ai', '数据库', '数据库', '数据产品',
            '客服', 'java', '.net', 'andrio', '人工智能', 'c++',
            '数据管理',"测试","运维"]
job_list = np.array(job_list)
def rename(x=None,job_list=job_list):
    index = [i in x for i in job_list]
    if sum(index) > 0:
        return job_list[index][0]
    else:
        return x
job_info["岗位名"] = job_info["岗位名"].apply(rename)
job_info["岗位名"].value_counts()
# 数据统计、数据专员、数据分析统一归为数据分析
job_info["岗位名"] = job_info["岗位名"].apply(lambda x:re.sub("数据专员","数据分析",x))
job_info["岗位名"] = job_info["岗位名"].apply(lambda x:re.sub("数据统计","数据分析",x))

Descrição: Primeiro, definimos um poste da baliza job_list deseja substituir, convertê-lo em conjunto ndarray. Em seguida, definir uma função, se um registro contém uma matriz job_list palavra-chave, então este registro será substituída por esta palavra-chave, se um registro contém uma pluralidade de gama palavras-chave job_list, nós tomamos somente um primeiro palavras-chave substituir este recorde. Em seguida, use value_counts () estatísticas de função sobre a freqüência das mensagens após a substituição. Finalmente, "Dados Comissário", "estatísticas" são agrupados como "análise de dados."

4) área de processamento de salários

Campos de dados salários semelhantes a "200.000-300.000 / ano", "2,5-3 Wan / mês" ea forma "3,5-4500 / mês." Precisamos fazer uma única alteração, converte o formato de dados é "yuan / mês", e em seguida, remova as duas figuras, encontrar uma média.

job_info["工资"].str[-1].value_counts()
job_info["工资"].str[-3].value_counts()


index1 = job_info["工资"].str[-1].isin(["年","月"])
index2 = job_info["工资"].str[-3].isin(["万","千"])
job_info = job_info[index1 & index2]


def get_money_max_min(x):
    try:
        if x[-3] == "万":
            z = [float(i)*10000 for i in re.findall("[0-9]+\.?[0-9]*",x)]
        elif x[-3] == "千":
            z = [float(i) * 1000 for i in re.findall("[0-9]+\.?[0-9]*", x)]
        if x[-1] == "年":
            z = [i/12 for i in z]
        return z
    except:
        return x


salary = job_info["工资"].apply(get_money_max_min)
job_info["最低工资"] = salary.str[0]
job_info["最高工资"] = salary.str[1]
job_info["工资水平"] = job_info[["最低工资","最高工资"]].mean(axis=1)

Descrição: Em primeiro lugar, fizemos uma dados de rastreio, específico para cada registro, se a última palavra no "ano" e "mês", enquanto a terceira palavra nas "milhões" e "milhares", em seguida, manter este artigo gravar ou excluir. Em seguida, definir uma função que será convertido para um formato unificado "Yuan / mês." Finalmente, o salário mínimo e salário máximo em média, para dar o campo final "nível salarial".

5) campo Work Place

Como os dados inteiro é dados sobre o país, a cidade também está envolvida na particularmente elevado. Precisamos de um lugar field goal costume comum de trabalho, para fazer um processamento de dados unificado.

#job_info["工作地点"].value_counts()
address_list = ['北京', '上海', '广州', '深圳', '杭州', '苏州', '长沙',
                '武汉', '天津', '成都', '西安', '东莞', '合肥', '佛山',
                '宁波', '南京', '重庆', '长春', '郑州', '常州', '福州',
                '沈阳', '济南', '宁波', '厦门', '贵州', '珠海', '青岛',
                '中山', '大连','昆山',"惠州","哈尔滨","昆明","南昌","无锡"]
address_list = np.array(address_list)


def rename(x=None,address_list=address_list):
    index = [i in x for i in address_list]
    if sum(index) > 0:
        return address_list[index][0]
    else:
        return x
job_info["工作地点"] = job_info["工作地点"].apply(rename)

Descrição: Primeiro, nós definimos uma lista de alvos de locais de trabalho, para convertê-lo em conjunto ndarray. Em seguida, definir uma função que irá gravar o lugar original de trabalho, local de trabalho é substituído com o alvo na cidade.

Processamento de campo de tipo 6) empresa

Isto é muito fácil, não descrito em detalhe.

job_info.loc[job_info["公司类型"].apply(lambda x:len(x)<6),"公司类型"] = np.nan
job_info["公司类型"] = job_info["公司类型"].str[2:-2]

7) no campo da indústria de tratamento

Cada empresa pode ter vários domínios da indústria, rótulos de comércio, mas o padrão é o primeiro da indústria da empresa como um rótulo.

# job_info["行业"].value_counts()
job_info["行业"] = job_info["行业"].apply(lambda x:re.sub(",","/",x))
job_info.loc[job_info["行业"].apply(lambda x:len(x)<6),"行业"] = np.nan
job_info["行业"] = job_info["行业"].str[2:-2].str.split("/").str[0]

8) experiência em lidar com o campo da educação

Sobre os dados de campo de processamento, eu estava pensando por um momento, não é uma boa descrição, colocar o seu próprio código para ir experiência.

job_info["学历"] = job_info["经验与学历"].apply(lambda x:re.findall("本科|大专|应届生|在校生|硕士",x))
def func(x):
    if len(x) == 0:
        return np.nan
    elif len(x) == 1 or len(x) == 2:
        return x[0]
    else:
        return x[2]
job_info["学历"] = job_info["学历"].apply(func)

Processamento de campo de descrição 9) trabalho

Para cada linha, depois de remover palavras de parada, fazer uma palavra jieba.

with open(r"G:\8泰迪\python_project\51_job\stopword.txt","r") as f:
    stopword = f.read()
stopword = stopword.split()
stopword = stopword + ["任职","职位"," "]


job_info["工作描述"] = job_info["工作描述"].str[2:-2].apply(lambda x:x.lower()).apply(lambda x:"".join(x))\
    .apply(jieba.lcut).apply(lambda x:[i for i in x if i not in stopword])
job_info.loc[job_info["工作描述"].apply(lambda x:len(x) < 6),"工作描述"] = np.nan

Por 10) campo tamanho da empresa

#job_info["公司规模"].value_counts()
def func(x):
    if x == "['少于50人']":
        return "<50"
    elif x == "['50-150人']":
        return "50-150"
    elif x == "['150-500人']":
        return '150-500'
    elif x == "['500-1000人']":
        return '500-1000'
    elif x == "['1000-5000人']":
        return '1000-5000'
    elif x == "['5000-10000人']":
        return '5000-10000'
    elif x == "['10000人以上']":
        return ">10000"
    else:
        return np.nan
job_info["公司规模"] = job_info["公司规模"].apply(func)

11) a nova estrutura de dados

Nós limpar os dados para o final, selecione o campo a ser analisado, fazer um armazenamento de dados.

feature = ["公司名","岗位名","工作地点","工资水平","发布日期","学历","公司类型","公司规模","行业","工作描述"]
final_df = job_info[feature]
final_df.to_excel(r"G:\8泰迪\python_project\51_job\词云图.xlsx",encoding="gbk",index=None)

tratamento especial no campo "descrição do trabalho"

Desde então, o que precisamos fazer para diferentes posições foram diferentes palavras cloud processamento e exibição visual é feito no quadro, por isso precisamos ser classificados de acordo com o nome do trabalho, obtidas em diferentes posições cada palavra-chave estatísticas de freqüência de palavra.

import numpy as np
import pandas as pd
import re
import jieba
import warnings
warnings.filterwarnings("ignore")


df = pd.read_excel(r"G:\8泰迪\python_project\51_job\new_job_info1.xlsx",encoding="gbk")
df


def get_word_cloud(data=None, job_name=None):
    words = []
    describe = data['工作描述'][data['岗位名'] == job_name].str[1:-1]
    describe.dropna(inplace=True)
    [words.extend(i.split(',')) for i in describe]
    words = pd.Series(words)
    word_fre = words.value_counts()
    return word_fre


zz = ['数据分析', '算法', '大数据','开发工程师', '运营', '软件工程','运维', '数据库','java',"测试"]
for i in zz:
    word_fre = get_word_cloud(data=df, job_name='{}'.format(i))
    word_fre = word_fre[1:].reset_index()[:100]
    word_fre["岗位名"] = pd.Series("{}".format(i),index=range(len(word_fre)))
    word_fre.to_csv(r"G:\8泰迪\python_project\51_job\词云图\bb.csv", mode='a',index=False, header=None,encoding="gbk")

exibição visual tableau

necessidades de emprego de 1) Popular cidades TOP10

O número de TOP10 2) Cidades Populares pós

Número 3) posições diferentes no local de trabalho da bolha FIG

4) salário trabalho Hot

5) salário indústria quente

6) de visualização em ecrã grande do último show

"Dynamic" 7) a visualização do ecrã de grandes dimensões

Descrição: Esta é a conclusão final da análise não é feito, porque a conclusão pela figura, que pode ser visto claramente.

Aviso: Este artigo é CSDN blogger "Huang supremo" no artigo original, lançamento oficial CSDN autorizado.

link original: https: //blog.csdn.net/weixin_41261833/article/details/104924038

【Fim】

Leitura recomendada 

GitHub projeto de código aberto após o outro ultraje provocam bloqueado, CEO pessoalmente pedir desculpas!

360 em resposta ao disco nuvem de segurança aparece transações incomuns; site oficial da Apple após a outra restrição iPhone; projeto GitHub open source blindado engenheiros da Microsoft | Geeks manchetes

2020 anos, os cinco tipos de linguagem de programação vai morrer

resistiu milhões de pessoas vivem, recomendado pelas Nações Unidas desde o fim da tecnologia de caminho de migração livro mosca!

não sei o AWS isso? Esta chave 11 com você sabe AWS!

escrito Solidez contrato de padrões de projeto inteligentes

Você olha para todos os pontos, eu seriamente como favorita

Lançado 1864 artigos originais · ganhou elogios 40000 + · Visualizações 16,920,000 +

Acho que você gosta

Origin blog.csdn.net/csdnnews/article/details/105039890
Recomendado
Clasificación