蘇州市java崗位的薪資情況(1)

8月份已經正式離職,這兩個月主要在作新書校對工做。9月份陸續投了幾份簡歷,參加了兩次半面試,第一次是家作辦公自動化的公司,開的薪水和招聘信息嚴重不符,感受實在是在浪費時間,你說你給不了那麼多爲什還往上發佈?第二次是家作業務系統的中型公司,結果面試個人技術總監直接被我按在地上摩擦,估計沒戲了。還有半次,是個研究所,電話和微信簡單溝通了一下,結果感受本身有點被摩擦的意思,不愧掛着研究倆字。後兩家公司的薪水區間幾乎相同,但人員的技術水平卻相差很大,這讓我有些好奇,忍不住想分析一下蘇州相似崗位的薪資水平。html

我在51job上搜索了一下蘇州,計算機軟件,互聯網/電子商務,計算機服務,近一月的java相關職位,一共33頁。前端

第1頁的URL是:java

https://search.51job.com/list/070300,000000,0000,00,3,99,java,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=面試

第2頁是:瀏覽器

https://search.51job.com/list/070300,000000,0000,00,3,99,java,2,2.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=微信

不一樣之處在 java2,1.html 和 java2,2.html 看來那個不一樣的數字就是翻頁信息。架構

在瀏覽器F12一下,頁面dom佈局大概是這樣:app

 因而爬取了一下所有數據:運維

  1 from urllib.request import urlopen
  2 from urllib.error import HTTPError
  3 from bs4 import BeautifulSoup
  4 import csv
  5 from itertools import chain
  6 import threading
  7 
  8 def get_jobs(url):
  9     '''
 10     根據url爬取職位信息
 11     :param url:
 12     :return: 職位列表,每一個元素是一個四元組(職位名, 薪資,發佈時間,詳情頁面url)
 13     '''
 14     try:
 15         html = urlopen(url)
 16     except HTTPError as e:
 17         print('Page was not found')
 18         return []
 19 
 20     jobs = []
 21     try:
 22         bsObj = BeautifulSoup(html.read())
 23         jobs_div = bsObj.find('div', {'id': 'resultList'}).findAll('div', {'class':'el'})
 24         for div in jobs_div[1:]:
 25             span_list = div.findAll('span')
 26             job_name = span_list[0].a.get_text().strip() # 職位名稱
 27             job_url = span_list[0].a.attrs['href'].strip() # 職位詳情url
 28             job_comp = span_list[1].a.get_text().strip() #公司名稱
 29             job_salary = span_list[3].get_text().strip() # 薪資
 30             job_date = span_list[4].get_text().strip() # 日期
 31             jobs.append((job_comp, job_name, job_salary, job_date, job_url))
 32     except AttributeError as e:
 33         print(e)
 34         return []
 35     return jobs
 36 
 37 def crawl():
 38     '''
 39     分頁蘇州市近一月內的java相關職位
 40     :return: 職位列表,每一個元素是一個四元組(職位名, 薪資,發佈時間,詳情頁面url)
 41     '''
 42     # 查詢條件:java;蘇州;計算機軟件、計算機服務(系統、數據服務、維修)、互聯網/電子商務;近一月
 43     url = 'https://search.51job.com/list/070300,000000,0000,01%252C38%252C32,9,99,java,2,{0}.html?' \
 44           'lang=c&stype=&postchannel=0000&workyear=99&cotype=99&degreefrom=99' \
 45           '&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1' \
 46           '&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='
 47     all_jobs = []
 48 
 49     def _crawl(page_start, page_end):
 50         '''
 51         分頁爬取數據
 52         :param page_start: 起始頁
 53         :param page_end: 終止頁
 54         :return:
 55         '''
 56         print('crawl {0}~{1} start...'.format(page_start, page_end))
 57         for i in range(page_start, page_end):
 58             # 翻頁url
 59             page_url = url.format(str(i))
 60             jobs = get_jobs(page_url)
 61             if len(jobs) == 0:
 62                 break
 63             all_jobs.append(jobs)
 64         print('crawl {0}~{1} over'.format(page_start, page_end))
 65 
 66     # 線程列表
 67     thread_list = []
 68     start_nums = list(range(0, 45, 5))
 69     end_nums = list(range(5, 50, 5))
 70     # 每5頁一個線程, 最多50頁
 71     for i in range(len(start_nums)):
 72         t = threading.Thread(target=_crawl, args=(start_nums[i], end_nums[i]))
 73         thread_list.append(t)
 74 
 75     print('開始爬取數據...')
 76     for t in thread_list:
 77         t.start()
 78     for t in thread_list:
 79         t.join()
 80     print('爬取結束')
 81 
 82     return all_jobs
 83 
 84 def save_data(all_jobs):
 85     '''
 86     將職位信息保存到joblist.csv
 87     :param all_jobs: 二維列表,每一個元素是一頁的職位信息
 88     '''
 89     print('正在保存數據...')
 90     with open('joblist.csv', 'w', encoding='utf-8', newline='') as fp:
 91         w = csv.writer(fp)
 92         # 將二維列表轉換成一維
 93         t = list(chain(*all_jobs))
 94         w.writerows(t)
 95         print('保存結束,共{}條數據'.format(len(t)))
 96 
 97 if __name__ == '__main__':
 98     # 爬取數據
 99     all_jobs = crawl()
100     # 保存數據
101     save_data(all_jobs)

爲了爬的快點,開了多個線程,最後把數據保存在joblist.csv中。近一個月共有967個java相關職位:dom

 

打開csv,發現裏面的數據並不太好:

……

江蘇未至科技股份有限公司,實施工程師(蘇州),4-8千/月,09-25,https://jobs.51job.com/suzhou-gxq/105762963.html?s=01&t=0
江蘇未至科技股份有限公司,交付工程師,6-7千/月,09-25,https://jobs.51job.com/suzhou-gxq/104253078.html?s=01&t=0
易程創新科技有限公司蘇州分公司,高級軟件工程師,1-2萬/月,09-25,https://jobs.51job.com/suzhou-gxq/100292396.html?s=01&t=0
江蘇未至科技股份有限公司,項目經理,0.8-1.6萬/月,09-25,https://jobs.51job.com/suzhou-gxq/85646230.html?s=01&t=0
達內時代教育集團,諮詢顧問底薪4-7K+五險一金,1-1.5萬/月,09-25,https://jobs.51job.com/suzhou-gsq/113505714.html?s=01&t=0
達內時代教育集團,搜索顧問底薪4-7K-上市企業,1-1.5萬/月,09-25,https://jobs.51job.com/suzhou-gsq/113505583.html?s=01&t=0
蘇州工業園區測繪地理信息有限公司...,Web前端開發工程師,6-15萬/年,09-25,https://jobs.51job.com/suzhou-gyyq/86942466.html?s=01&t=0
江蘇雲坤信息科技有限公司,項目經理,1-1.8萬/月,09-25,https://jobs.51job.com/suzhou-gyyq/112994728.html?s=01&t=0
江蘇雲坤信息科技有限公司,前端開發工程師,0.8-1.5萬/月,09-25,https://jobs.51job.com/suzhou-gyyq/70761080.html?s=01&t=0
蘇州智享雲信息科技有限公司,系統架構師,1.6-2.5萬/月,09-25,https://jobs.51job.com/suzhou/108411172.html?s=01&t=0
英諾賽科(蘇州)半導體有限公司,MES 工程師,0.6-1萬/月,09-25,https://jobs.51job.com/suzhou-wjq/115142646.html?s=01&t=0
蘇州麥芒軟件科技有限公司,軟件測試助理工程師,4-6千/月,09-25,https://jobs.51job.com/suzhou/115511688.html?s=01&t=0
三門峽崤雲信息服務股份有限公司,大數據挖掘工程師,0.8-2萬/月,09-25,https://jobs.51job.com/sanmenxia/110394655.html?s=01&t=0
蘇州春慷諮詢管理有限公司,軟件實施工程師,0.3-1萬/月,09-25,https://jobs.51job.com/suzhou-gsq/115617730.html?s=01&t=0
蘇州佑捷科技有限公司,高級開發工程師,1.5-2萬/月,09-25,https://jobs.51job.com/suzhou-gxq/114727492.html?s=01&t=0
蘇州佑捷科技有限公司,Android開發工程師,1-2.5萬/月,09-25,https://jobs.51job.com/suzhou-gxq/114726758.html?s=01&t=0
瑞泰信息技術有限公司,.NET開發工程師(實習生),6.5-8.5千/月,09-25,https://jobs.51job.com/suzhou/108055469.html?s=01&t=0
北京直真科技股份有限公司,前端開發工程師(蘇州),1.1-1.7萬/月,09-25,https://jobs.51job.com/suzhou/113018219.html?s=01&t=0

……

職位包含測試、項目經理、售前、Android,還有一部分.net也混進來了,因此分析前須要過濾掉這些數據。'測試', '.Net', '運維', '嵌入式','前端',這些職位都不要,’總監', '主管', '技術', '研發', '開發', '經理', 'java', 'JAVA', 'Java', '工程師’ ,這些須要保留。

薪資的單位也不統一,有萬/年,萬/月,千/月, 統一轉換成萬/年,沒寫薪資的也不要。

 1 import csv
 2 from decimal import Decimal
 3 import pandas as pd
 4 import numpy as np
 5 
 6 def load_datas():
 7     '''
 8     從joblist.csv中裝載數據
 9     :return: 數據集 datas
10     '''
11     datas = []
12     with open('joblist.csv', encoding='utf-8') as fp:
13         r = csv.reader(fp)
14         for row in r:
15             datas.append(row)
16     return datas
17 
18 def clear(datas):
19     '''
20     數據清洗
21     規則:
22         1.沒有標明薪資的,直接去掉;
23         2.萬/月和千/月轉換成萬/年
24     :param datas: 原始數據
25     :return: 清洗後的數據
26     '''
27     result = []
28     for d in datas:
29         # 清洗後的數據
30         new_d = []
31         new_d.append(d[0]) # 公司
32         job = filter_job(d[1]) # 公司
33         # 去掉公司不符合的數據
34         if job == '':
35             continue
36         new_d.append(d[1]) # 職位
37         salary_start, salary_end = salary_trans(d[2])
38         # 去掉沒寫薪資的數據
39         if salary_start == '':
40             continue
41         else:
42             new_d.append(salary_start)
43             new_d.append(salary_end)
44         new_d.append(d[3]) # 發佈日期
45         new_d.append(d[4]) # 詳細頁面URL
46         result.append(new_d)
47     return result
48 
49 def filter_job(job):
50     '''
51     過濾職位名稱
52     :param job: 職位
53     :return: 若是被過濾掉,返回''
54     '''
55     # 黑名單
56     black = ['測試', '.Net', '運維', '嵌入式', '前端']
57     # job在黑名單中
58     if [job.find(x, 0, len(job)) for x in black].count(-1) < len(black):
59         return ''
60     # job在白名單
61     white = ['總監', '主管', '技術', '研發', '開發', '經理', 'java', 'JAVA', 'Java', '工程師']
62     if [job.find(x, 0, len(job)) for x in white].count(-1) > 0:
63         return job
64     return ''
65 
66 def salary_trans(salary):
67     '''
68     對薪資進行轉換
69     :param salary: 薪資
70     :return: 二元組(起始年薪(萬/年), 終止年薪(萬/年))
71     '''
72     start, end = '', '' # 起始年薪, 終止年薪
73     # 將全部薪資單位轉換成 萬/年
74     if salary.endswith('萬/年'):
75         s = salary.replace('萬/年', '').split('-')
76         start, end = s[0], s[1]
77     elif salary.endswith('萬/月'):
78         s = salary.replace('萬/月', '').split('-')
79         start = (Decimal(s[0]) * 12).normalize()
80         end = (Decimal(s[1]) * 12).normalize()
81     elif salary.endswith('千/月'):
82         s = salary.replace('千/月', '').split('-')
83         start = (Decimal(s[0]) * 12 / 10).normalize()
84         end = (Decimal(s[1]) * 12 / 10).normalize()
85     return str(start), str(end)
86 
87 if __name__ == '__main__':
88     # 讀取並清洗數據
89     datas = np.array(clear(load_datas()))
90     print(len(datas)) 

 還剩789條。

分析開始。招聘信息上絕大多數都是以起薪資爲準, 最高薪資就是作個樣子,所以只分析起薪。先快速統計一下:

 

 1 def analysis(datas):
 2     ''' 數據分析 '''
 3     df = pd.DataFrame({'comp_name': datas[:, 0],
 4                        'job_name': datas[:, 1],
 5                        'salary_start': datas[:, 2],
 6                        'salary_end': datas[:, 3],
 7                        'publish_date': datas[:, 4],
 8                        'url': datas[:, 5]})
 9     # 所有起始薪資
10     salary_col = df['salary_start']
11     print('按起始薪資快速統計'.center(60, '-'))

 

 一共有789條記錄,其中最多的是年薪12W,共出現了162次,大多數職位也就1W的月薪。

再看起薪出現次數最多的top10。

 

 1 def analysis(datas):
 2     ''' 數據分析 '''
 3     df = pd.DataFrame({'comp_name': datas[:, 0],
 4                        'job_name': datas[:, 1],
 5                        'salary_start': datas[:, 2],
 6                        'salary_end': datas[:, 3],
 7                        'publish_date': datas[:, 4],
 8                        'url': datas[:, 5]})
 9     # 所有起始薪資
10     salary_col = df['salary_start']
11     print('按起始薪資快速統計'.center(60, '-'))
12     # 按起始薪資快速統計
13     print(salary_col.describe())
14     # 起薪出現次數最多的top10
15     salary_count_top_n(salary_col, 10)
16 
17 def salary_count_top_n(salary_col, n):
18     ''' 起薪出現次數最多的top n '''
19     print(('起薪出現次數最多的top' + str(n)).center(60, '-'))
20     print('起薪\t數量')
21     # 起薪出現次數最多的top n
22     count_top_n = salary_col.value_counts(sort=True, ascending=False).head(n)
23     print(count_top_n)
24     count_top_n.plot(kind='bar')
25     plt.rcParams['font.sans-serif'] = ['SimHei']  # 用來正常顯示中文標籤
26     plt.xlabel('薪資(萬/年)')
27     plt.ylabel('職位數量')
28     plt.show()

 真是一看嚇一跳,月薪1W如下大概有500條,約佔總職位數量的65%。

再看起薪最高的top 10:

 2     ''' 數據分析 '''
 3     df = pd.DataFrame({'comp_name': datas[:, 0],
 4                        'job_name': datas[:, 1],
 5                        'salary_start': datas[:, 2],
 6                        'salary_end': datas[:, 3],
 7                        'publish_date': datas[:, 4],
 8                        'url': datas[:, 5]})
 9     ……
10     # 起薪最高的top10
11     urls = salary_high_top_n(df, 10)
12 
13 
14 def salary_high_top_n(df, n):
15     ''' 起薪最高的top n '''
16     print(('起薪最高的top' + str(n)).center(60, '-'))
17     salary_grp = df.groupby('salary_start')
18     # 按起薪分組
19     salary_top_n = sorted(salary_grp, reverse=True, key=lambda x: float(x[0]))[0:n]
20     print('%-16s%-20s' % ('起薪', '數量'))
21     # 職位對應的url
22     urls = []
23     for salary, group in salary_top_n:
24         print('%-20s%-20d' % (salary, len(group)))
25         urls +=  group.url.values.tolist()
26     return urls

 

 

 

top 10中共64個職位,年薪24W的佔了26個,約佔top10的40%,24W如下的佔了65%以上。月薪2W竟然都是高薪了,還有前途嗎?

 

 


 

  做者:我是8位的

  出處:http://www.cnblogs.com/bigmonkey

  本文以學習、研究和分享爲主,如需轉載,請聯繫本人,標明做者和出處,非商業用途! 

  掃描二維碼關注公做者衆號「我是8位的」

相關文章
相關標籤/搜索