• 招聘市场上 自然语言处理工程师都得会点啥


    以boss直聘https://www.zhipin.com/上面搜索nlp为例,我们抓取数据,探索一下市场上对nlp人才的需求.

    代码放在https://github.com/sdu2011/nlp.你可以稍加改造,看看自己所在地区,目标职位都要求一些什么技能.

    以南京地区的nlp岗位为例.

    • 要抓取职位列表.获取招聘方信息.抓取到职位详情页面的url。
    • 要抓取职位详情,解析详情,分词,统计,提取关键词等
    • 可视化. seaborn wordcloud等图形化展示.

    数据抓取与清洗

    这部分就不多谈了.主要要了解一些爬虫知识.html页面的解析库BeatifulSoup用法.这一步"脏活比较多",主要就是分析各种html的tag的格式,去除空格啦,提取各种tag下信息啦之类的数据清洗工作.

    current_url = "https://www.zhipin.com/job_detail/?query=nlp&scity=101190100&industry=&position="
    headers = {
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
               ,'Connection': 'keep-alive'
               }
    r=requests.get(current_url,headers=headers)
    
    def parse_job_detail(url):
        r=requests.get(url,headers=headers)
        bs = BeautifulSoup(r.text,"html.parser")
        h3=bs.find("h3",text="职位描述")
        #print(h3.find_next_sibling("div"))
        div_tag = h3.find_next_sibling("div")
        #print(div_tag.text)
        requirements = []#任职要求
        responsbility = []#岗位职责
        require_flag = False
        responsbility_flag = False
        for c in div_tag.children:
            #print(c,type(c))
            if type(c) is bs4.element.NavigableString:
                str_no_space = c.string.replace(" ","")
                #print(str_no_space)
                
                if str_no_space.find("任职要求") != -1:   #这边不能用==判断  因为前面由于中文字符的问题 replace替换不掉:后面的blank
                    responsbility_flag = False
                    require_flag = True
                    continue
                    
                if str_no_space.find("岗位职责") != -1:   #这边不能用==判断  因为前面由于中文字符的问题 replace替换不掉:后面的blank
                    require_flag = False
                    responsbility_flag = True           
                    continue
                
                if require_flag:
                    requirements.append(str_no_space)
                if responsbility_flag:
                    responsbility.append(str_no_space)
                            
        #print(requirements)  
        #print(responsbility)
        return (requirements,responsbility)
    
    #parse_job_detail("https://www.zhipin.com/job_detail/84e81e27c933269e1Xxz3dq1E1I~.html?ka=search_list_1")
    
    def  get_jobs_info(url):
        r=requests.get(url,headers=headers)
        bs = BeautifulSoup(r.text,"html.parser")
        jobs = []
        for job in bs.find_all("div",class_="job-primary"):
            #print("**************************************************************")
            one_job = []
            for child in job.descendants:   
                if child.name == 'div'and child['class'] == ['info-primary']:
                    jobdetails = parse_job_detail("https://www.zhipin.com/%s" % (child.h3.a.get('href')))
                    one_job.append(child.h3.div.text)  #title
                    #print(one_job)
                    one_job.append(child.h3.span.text) #salary  
                    #one_job.append(child.h3.a.get('href')) #link
                    one_job.append(jobdetails[0]) #requirements
                    one_job.append(jobdetails[1]) #responsbility
                    index = 0
                    for c in child.p:
                        if index == 0:
                            #print(c)   
                            one_job.append(c)  #地区
                        elif index == 2:
                            #print(c)   
                            one_job.append(c)  #经验
                        elif index == 4:
                            #print(c)   
                            one_job.append(c)  #学历
                        index += 1
                elif child.name == 'div' and child['class'] == ['info-company']:
                    #print(child.a.string)
                    index = 0
                    for c in child.p:
                        if index == 0:
                            #print(c)    #行业
                            one_job.append(c)
                        elif index == 2:
                            #print(c)    #公司发展阶段 A/B/C/D轮/上市
                            one_job.append(c)
                        elif index == 4:
                            #print(c)    #规模
                            one_job.append(c)
    
                        index += 1
                        pass
            #print(one_job)  
            jobs.append(one_job)
    
        return jobs
        
    jobs_info=get_jobs_info("https://www.zhipin.com/job_detail/?query=nlp&scity=101190100&industry=&position=")
    

     数据抓取完成后

    数据探索

    这部分,需要对pandas,seaborn有一些了解.

    下面我们就可以用seaborn对数据做可视化处理了.

    解决sns显示中文字体的问题  
    from matplotlib.font_manager import FontProperties  
    myfont=FontProperties(fname=r'C:WindowsFontssimhei.ttf',size=14)  
    sns.set(font=myfont.get_name())
    
    • 学历

    先来看看学历的要求.(说到这我就心痛,为什么当初要放弃读研,真想抽自己两耳光!!!! 直接导致了现在接近一半的职位连门槛都跨不进去)。

    可以看到NLP工程师对学历的要求还是比较高,图标里硕士学历要求基本接近40%.实际上,要接近50%,因为有的岗位在职位搜索页面标注的是本科即可,但是实际上职位详情里又说明了要求硕士.

    所以,有志于NLP的小伙伴能读研的还是读研吧,有志于NLP的小伙伴能读研的还是读研吧,有志于NLP的小伙伴能读研的还是读研吧,重要的事情说三遍.

    •  经验.

    可以看到3年左右经验是比较受欢迎的.这也符合常识,首先NLP这几年是随着深度学习的发展开始火起来,经验特别丰富的从业者并不多.而且,不光是NLP,别的岗位也是3/5/8年比较吃香,因为此时你已经是这个级别的熟练工种了.

    • 学历+经验

            依然类似的结论,在各个学历下,都是3年左右的需求比较多.

    • 规模

          首先,千人以上的公司招聘需求相对大,比较好理解. 比较意外的是100-499的中小公司招聘需求相对较多.可能是最近几年随着深度学习的兴起,很多AI相关业务的A轮/B轮的创业公司.

    验证一下我们上面的猜测,100-499规模中,A/B轮的比较多.

    • 地区

    排除没有标明具体地区的,剩下的雨花台铁心桥一带需求最多,因为那边是"宇宙的中心",大量的科技公司和码农聚集到软件大道一带.  剩下的江宁区的岗位也相对多.

    • 薪水

    大部分集中在15-30k

    我们取月薪的均值再看一眼.这里我们添加新的一列"平均月薪".

    #处理月薪数据
    def f(s):
        #x="17k-18k"
        l = s.replace('k','').split('-')
    
        tmp=[int(e) for e in l]
        return sum(tmp)/len(tmp)
    
    df["平均月薪"]=df["月薪"].apply(f)
    

    那种4k的基本是实习生.这么一看平均有22k,很诱人,有没有.  考虑到用人单位说的15-30k,一般指15k.... 我们再处理一下数据,绘图

    def min_salary(s):
        #x="17k-18k"
        l = s.replace('k','').split('-')
    
        return int(l[0])
    
    df["最低月薪"]=df["月薪"].apply(min_salary)
    

      

     再看看不同规模公司中,不同学历与月薪的关系.小公司里本科生更多.大公司里硕士生占比提高.

    NLP工程师需要会什么?

     之前的代码里,我们已经抓取到了任职描述和岗位要求,现在我们使用jieba去做分词.

    • 注意去掉stopwords
    • 词典添加自定义词.比如希望'机器学习'被认为是一个完整的词,而不是‘机器’、‘学习’两个词.
    f = open("./词表/哈工大停用词表.txt",encoding='utf-8')
    stopword_list = [line.strip() for line in f.readlines()]
    self_defined_list = ['1','2','3','4','5','6','以上学历','关于',' '] stopword_list.extend(self_defined_list) print(stopword_list) def add_self_defined_words(): jieba.add_word('机器学习') jieba.add_word('深度学习') def get_words(serie): clean_contents=[] for s in serie: s_tmp = ''.join(s) #clean_s= re.sub(r'[^u4e00-u9fa5]', '', s_tmp) #https://github.com/fxsjy/jieba/issues/528 这个会去除中文词之外的词 clean_s = s_tmp clean_contents.append(clean_s) add_self_defined_words() word_list = [word for word in jieba.cut(''.join(clean_contents),cut_all=False) if word not in stopword_list] print(word_list) tags=jieba.analyse.extract_tags(''.join(clean_contents), topK=20) print(tags) return word_list,tags require_word_list,require_tags = get_words(df["任职要求"]) responsibility_word_list,responsibility_tags = get_words(df["岗位职责"])

    结巴的topk关键词抽取使用的是tfidf,不是词频.仅供参考.这里我们其实更关心词频.

    可以看到经验还是很重要的.不管是相关工作经验还是研究经验.

    同样的看下岗位职责

    为了探索特定词的词频,写了函数count_specific_word,考虑了相似词,比如Python和python其实想表达的是一个意思.

    一般框架名都为英文比如tensorflow/hadoop等,写了函数get_englishword_list去获取这些英文词,情况如下:

    可以发现tensorflow是最常被要求掌握的深度学习框架.

    #获取特定词的出现次数
    def count_specific_word(serie,word_list):
        index = [False] * len(serie)
        for w in word_list:
            tmp_list = list(serie == w)
            #print(list(tmp_list).count(True))
            
            index=list(np.logical_or(tmp_list,index))  #注意一下两个boolean list相应位置and  or的用法
            #print(index.count(True))
    
        return list(index).count(True)
    
    print(count_specific_word(require_word_series,["TensorFlow"]))
    print(count_specific_word(require_word_series,["经验"]))
    print(count_specific_word(require_word_series,["研究生","硕士"]))
    print(count_specific_word(require_word_series,["深度学习","机器学习"]))
    print(count_specific_word(require_word_series,["python","Python"]))
    
    #把中文去掉
    def get_englishword_list():
        l = []
        for w in require_word_list:
            w=re.sub(r'[u4e00-u9fa5
    ]', '',w)
            if w == "":
                continue
            else:
                #print(w)
                l.append(w.lower())
        
        print(l)
        return l
    
    enw_serie = pd.Series(get_englishword_list())
    enw_serie.value_counts()
    

    为了获得更直观的印象,我们将关键词用词云绘制.

    from wordcloud import WordCloud, ImageColorGenerator
    from scipy.misc import imread
    import matplotlib.pyplot as plt
    def picture(wordlist):
        font='C:WindowsFontssimhei.ttf'
        wc = WordCloud(background_color="white",font_path=font,max_words=2000)
        wc.generate(" ".join(wordlist))
        
        plt.figure()
        plt.imshow(wc, interpolation="bilinear")
        plt.axis("off")
        plt.show()  
    picture(require_word_list),picture(responsibility_word_list)

      

    将两组词合起来绘制出的词云如下:

    总结:当前的NLP工程师招聘,基本上都要求有工作经验或研究经验的.(实际上意味着你如果你没有在学生阶段有NLP的经验的话,那么这个岗位基本也就与你无缘了...工作后会因为没有相关经验很难切入这个领域...不切入这个领域又很难积累经验...死循环)。 需要掌握python/java等,需要了解深度学习,最好能掌握诸如tensorflow的框架,具体要掌握的nlp相关技能会涉及数据挖掘、文本分词分类、实体抽取、知识图谱构件等.

    最后,如果有南京地区的同学,求内推....

  • 相关阅读:
    azure备份虚拟机
    本地git部署web连接azure的git存储库
    dnsmasq服务的安装与配置
    hadoop错误- slave节点无法启动data node数据节点进程,但是master节点datanode正常启动
    hadoop错误--转发-hadoop启动遇到的各种问题
    hadoop错误--集群启动master时namenode进程无法启动
    c++的字节对齐
    fstream 和 iostream
    C语言的声明的优先级规则
    齐次矩阵
  • 原文地址:https://www.cnblogs.com/sdu20112013/p/10407169.html
Copyright © 2020-2023  润新知