深圳幻海软件技术有限公司 欢迎您!

用Python分析深圳程序员工资有多高?还真是多金的程序员!

2023-02-26

前言多图预警、多图预警、多图预警。秋招季,毕业也多,跳槽也多。我们的职业发展还是要顺应市场需求,那么各门编程语言在深圳的需求怎么呢?工资待遇怎么样呢?zone在上次写了这篇文章之后用Python告诉你深圳房租有多高,想继续用Python分析一下,当前深圳的求职市场怎么样?顺便帮一下秋招的同学。于是便

前言

多图预警、多图预警、多图预警。秋招季,毕业也多,跳槽也多。我们的职业发展还是要顺应市场需求,那么各门编程语言在深圳的需求怎么呢?工资待遇怎么样呢?zone 在上次写了这篇文章之后 用Python告诉你深圳房租有多高 ,想继续用 Python 分析一下,当前深圳的求职市场怎么样?顺便帮一下秋招的同学。于是便爬取了某拉钩招聘数据。以下是本次爬虫的样本数据:

 

 

 

样本

本次统计数据量为 4658 ,其中某拉钩最多能显示 30 页数据,每页 15 条招聘信息,则总为:

30 x 15 = 450

首页爬取跳过一页,则为 435 条,故数据基本爬完。其余不够数量的语言为该语言在深圳只有这么多条招聘信息。

统计结果

各语言平均工资

其中

  • 精准推荐
  • 自然语言
  • 机器学习
  • Go 语言
  • 图像识别

独领风骚啊!!!平均工资都挺高的。区块链炒得挺火的,好像平均薪资并没有那么高。我统计完之后,感觉自己拖后腿了,ma 的!!!要删库跑路了!(注:下图为月薪,单位:K)

 

各语言平均薪资

平均工资计算方式:

 

某钩 item

***值与***值,求平均数,如图薪资则为:

(10k + 20k)/2 = 15k

***,再总体求平均数。

公司福利词云

看福利还是挺丰富的,带薪休假、下午茶、零食、节假日。

 

福利词云

公司发展级别排行

总体由 A 轮向 D 轮缩减,大部分公司不需要融资,嗯,估计是拿不到资本融资,但是自家人又有钱的。

 

公司发展级别

各语言工作年限要求与学历要求

看看你的本命语言的市场需求怎么样?你达标了吗?其中三至五年的攻城狮职位挺多的,不怕找不到工作。还有一个趋势是,薪资越高,学历要求越高高。看来学历还是挺重要的。

Java

 

Java 工作年限要求

 

 

Java 学历要求

Python

 

Python 工作年限要求

 

 

Python 学历要求

C 语言

 

C 语言工作年限要求

 

 

C 语言学历要求

机器学习

 

机器学习工作年限要求

 

 

机器学习学历要求

图像识别

 

图像识别工作年限要求

 

 

图像识别学历要求

自然语言

 

自然语言工作年限要求

 

 

自然语言学历要求

区块链

 

区块链工作年限要求

 

 

区块链学历要求

Go 语言

 

Go 语言工作年限要求

 

 

Go

PHP

 

PHP 工作年限要求

 

 

PHP 学历要求

爬虫技术分析

  • 请求库:selenium
  • HTML 解析:BeautifulSoup、xpath
  • 词云:wordcloud
  • 数据可视化:pyecharts
  • 数据库:MongoDB
  • 数据库连接:pymongo

爬虫代码实现

看完统计结果之后,有没有跃跃欲试?想要自己也实现以下代码?以下为代码实现。

对网页右击,点击检查,找到一条 item 的数据:

 

网页源码

数据库存储结构:


  • 1.
/* 1 */ 

 "_id" : ObjectId("5b8b89328ffaed60a308bacd"), 
 "education" : "本科",# 学习要求 
 "companySize" : "2000人以上",# 公司人数规模 
 "name" : "python开发工程师",# 职位名称 
 "welfare" : "“朝九晚五,公司平台大,发展机遇多,六险一金”",# 公司福利 
 "salaryMid" : 12.5,# 工资上限与工资下限的平均数 
 "companyType" : "移动互联网",# 公司类型 
 "salaryMin" : "10",# 工资下限 
 "salaryMax" : "15",# 工资上限 
 "experience" : "经验3-5年",# 工作年限 
 "companyLevel" : "不需要融资",# 公司级别 
 "company" : "XXX技术有限公司"# 公司名称 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

由于篇幅原因,以下只展示主要代码:

# 获取网页源码数据 
# language => 编程语言 
# city => 城市 
# collectionType => 值:True/False True => 数据库表以编程语言命名 False => 以城市命名 
def main(self, language, city, collectionType): 
 print(" 当前爬取的语言为 => " + language + " 当前爬取的城市为 => " + city) 
 url = self.getUrl(language, city) 
 browser = webdriver.Chrome() 
 browser.get(url) 
 browser.implicitly_wait(10) 
 for i in range(30): 
 selector = etree.HTML(browser.page_source) # 获取源码 
 soup = BeautifulSoup(browser.page_source, "html.parser"
 span = soup.find("div", attrs={"class""pager_container"}).find("span", attrs={"action""next"}) 
 print( 
 span) # <span action="next" class="pager_next pager_next_disabled" hidefocus="hidefocus">下一页<strong class="pager_lgthen pager_lgthen_dis"></strong></span> 
 classArr = span['class'
 print(classArr) # 输出内容为 -> ['pager_next''pager_next_disabled'
 attr = list(classArr)[0] 
 attr2 = list(classArr)[1] 
 if attr2 == "pager_next_disabled":#分析发现 class 属性为 ['pager_next''pager_next_disabled'] 时,【下一页】按钮不可点击 
 print("已经爬到***一页,爬虫结束"
 break 
 else
 print("还有下一页,爬虫继续"
 browser.find_element_by_xpath('//*[@id="order"]/li/div[4]/div[2]').click() # 点击【下一页】按钮 
 time.sleep(5) 
 print('第{}页抓取完毕'.format(i + 1)) 
 self.getItemData(selector, language, city, collectionType)# 解析 item 数据,并存进数据库 
 browser.close() 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

爬虫分析实现

# 获取各语言样本数量 
def getLanguageNum(self): 
 analycisList = [] 
 for index, language in enumerate(self.getLanguage()): 
 collection = self.zfdb["z_" + language] 
 totalNum = collection.aggregate([{'$group': {'_id''''total_num': {'$sum': 1}}}]) 
 totalNum2 = list(totalNum)[0]["total_num"
 analycisList.append(totalNum2) 
 return (self.getLanguage(), analycisList) 
# 获取各语言的平均工资 
def getLanguageAvgSalary(self): 
 analycisList = [] 
 for index, language in enumerate(self.getLanguage()): 
 collection = self.zfdb["z_" + language] 
 totalSalary = collection.aggregate([{'$group': {'_id''''total_salary': {'$sum''$salaryMid'}}}]) 
 totalNum = collection.aggregate([{'$group': {'_id''''total_num': {'$sum': 1}}}]) 
 totalNum2 = list(totalNum)[0]["total_num"
 totalSalary2 = list(totalSalary)[0]["total_salary"
 analycisList.append(round(totalSalary2 / totalNum2, 2)) 
 return (self.getLanguage(), analycisList) 
# 获取一门语言的学历要求(用于 pyecharts 的词云) 
def getEducation(self, language): 
 results = self.zfdb["z_" + language].aggregate([{'$group': {'_id''$education''weight': {'$sum': 1}}}]) 
 educationList = [] 
 weightList = [] 
 for result in results: 
 educationList.append(result["_id"]) 
 weightList.append(result["weight"]) 
 # print(list(result)) 
 return (educationList, weightList) 
# 获取一门语言的工作年限要求(用于 pyecharts 的词云) 
def getExperience(self, language): 
 results = self.zfdb["z_" + language].aggregate([{'$group': {'_id''$experience''weight': {'$sum': 1}}}]) 
 totalAvgPriceDirList = [] 
 for result in results: 
 totalAvgPriceDirList.append( 
 {"value": result["weight"], "name": result["_id"] + " " + str(result["weight"])}) 
 return totalAvgPriceDirList 
# 获取 welfare 数据,用于构建福利词云 
def getWelfare(self): 
 content = '' 
 queryArgs = {} 
 projectionFields = {'_id'False'welfare'True} # 用字典指定 
 for language in self.getLanguage(): 
 collection = self.zfdb["z_" + language] 
 searchRes = collection.find(queryArgs, projection=projectionFields).limit(1000) 
 for result in searchRes: 
 print(result["welfare"]) 
 content += result["welfare"
 return content 
# 获取公司级别排行(用于条形图) 
def getAllCompanyLevel(self): 
 levelList = [] 
 weightList = [] 
 newWeightList = [] 
 attrList = ["A轮""B轮""C轮""D轮及以上""不需要融资""上市公司"
 for language in self.getLanguage(): 
 collection = self.zfdb["z_" + language] 
 # searchRes = collection.find(queryArgs, projection=projectionFields).limit(1000) 
 results = collection.aggregate([{'$group': {'_id''$companyLevel''weight': {'$sum': 1}}}]) 
 for result in results: 
 levelList.append(result["_id"]) 
 weightList.append(result["weight"]) 
 for index, attr in enumerate(attrList): 
 newWeight = 0 
 for index2, level in enumerate(levelList): 
 if attr == level
 newWeight += weightList[index2] 
 newWeightList.append(newWeight) 
 return (attrList, newWeightList)  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.