python爬取招聘網站,Python爬取歷年招聘數據,告訴你如何成為備受追捧的數據分析工程師!

 2023-10-22 阅读 27 评论 0

摘要:作者 | 法納斯特責編 | 郭芮近年來,數據分析師的需求熱度持續攀升,并且隨著數據價值的不斷挖掘越發得到市場認可。一個喜聞樂見的事實是,數據分析師、數據挖掘工程師、乃至于數據科學家都會有著較高的起薪,是行業公認的香餑餑。本文中就通過對BO

640?wx_fmt=gif

640?wx_fmt=jpeg

作者 | 法納斯特

責編 | 郭芮

近年來,數據分析師的需求熱度持續攀升,并且隨著數據價值的不斷挖掘越發得到市場認可。一個喜聞樂見的事實是,數據分析師、數據挖掘工程師、乃至于數據科學家都會有著較高的起薪,是行業公認的香餑餑。

本文中就通過對BOSS直聘、拉勾網數據分析崗的數據進行分析,了解數據分析崗的行業情況,也以此來了解從事數據分析所需要的技能。python爬取招聘網站、


640?wx_fmt=png

網頁分析


一開始我的設想是通過爬蟲框架Pyspider進行數據獲取。

講道理,Pyspider確實是一款優秀的爬蟲框架,我們可以利用它快速方便地實現頁面抓取。不過帶來便捷性的同時,也有它的局限性,復雜頁面不好爬取。在本次針對BOSS直聘和拉勾網的數據爬取中,前者成功使用了Pyspider,但后者卻不行,因為拉勾網的數據是Ajax加載的。

也就是說,拉勾網崗位數據請求的網址是不變的,改變的是表單數據,表單數據隨著頁數改變,請求方式為POST,這里沒辦法在Pyspider里用循環遍歷來獲取每一頁的數據。也許是我對Pyspider框架了解的不夠,還達不到得心應手。所以最后拉勾網的爬取,采用平常的辦法,在PyCharm中自行編寫程序。

1、獲取BOSS直聘索引頁信息:

640?

獲取BOSS直聘索引頁信息,主要是崗位名稱、薪資、地點、工作年限、學歷要求,公司名稱、類型、狀態、規模。

本來一開始是想對詳情頁分析的,還可以獲取詳情頁里的工作內容和工作技能需求。然后由于請求太多,就放棄了。索引頁有10頁,1頁有30個崗位,一個詳情頁就需要一個請求,算起來一共有300個請求。

我是到了第2頁(60個請求),就出現了訪問過于頻繁的警告。而只獲取索引頁信息的話,只有10個請求,基本上沒什么問題,外加也不想去鼓搗代理IP,所以來點簡單的。

2、獲取拉勾網索引頁信息:

640?

獲取拉勾網索引頁信息,主要是崗位名稱、地點、薪資、工作年限、學歷要求,公司名稱、類型、狀態、規模,工作技能,工作福利。

網頁為Ajax請求,我采用PyCharm編寫代碼,輕車熟路。


640?wx_fmt=png

數據獲取


1、Ppyspider獲取BOSS直聘數據

Pyspider的安裝很簡單,直接在命令行pip3 install pyspider即可。

這里因為之前沒有安裝Pyspider對接的PhantomJS(處理JavaScript渲染的頁面),所以需要從網站下載下來它的exe文件,將其放入Python的exe文件所在的文件夾下。

最后在命令行輸入pyspider all,即可運行Pyspider。

在瀏覽器打開網址http://localhost:5000/,創建項目,添加項目名稱,輸入請求網址,得到如下圖:

640?

最后在Pyspider的腳本編輯器里編寫代碼,結合左邊的反饋情況,對代碼加以改正。

640?

腳本編輯器具體代碼如下:

#!/usr/bin/env?python
#?-*-?encoding:?utf-8?-*-
#?Project:?BOSS

from?pyspider.libs.base_handler?import?*
import?pymysql
import?random
import?time
import?re

count?=?0

class?Handler(BaseHandler):
????#?添加請求頭,否則出現403報錯
????crawl_config?=?{'headers':?{'User-Agent':?'Mozilla/5.0?(Windows?NT?6.1;?WOW64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/63.0.3239.132?Safari/537.36'}}

????def?__init__(self):
????????#?連接數據庫
????????self.db?=?pymysql.connect(host='127.0.0.1',?user='root',?password='774110919',?port=3306,?db='boss_job',?charset='utf8mb4')

????def?add_Mysql(self,?id,?job_title,?job_salary,?job_city,?job_experience,?job_education,?company_name,?company_type,?company_status,?company_people):
????????#?將數據寫入數據庫中
????????try:
????????????cursor?=?self.db.cursor()
????????????sql?=?'insert?into?job(id,?job_title,?job_salary,?job_city,?job_experience,?job_education,?company_name,?company_type,?company_status,?company_people)?values?("%d",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s")'?%?(id,?job_title,?job_salary,?job_city,?job_experience,?job_education,?company_name,?company_type,?company_status,?company_people);
????????????print(sql)
????????????cursor.execute(sql)
????????????print(cursor.lastrowid)
????????????self.db.commit()
????????except?Exception?as?e:
????????????print(e)
????????????self.db.rollback()

????@every(minutes=24?*?60)
????def?on_start(self):
????????#?因為pyspider默認是HTTP請求,對于HTTPS(加密)請求,需要添加validate_cert=False,否則599/SSL報錯
????????self.crawl('https://www.zhipin.com/job_detail/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&scity=100010000&industry=&position=',?callback=self.index_page,?validate_cert=False)

????@config(age=10?*?24?*?60?*?60)
????def?index_page(self,?response):
????????time.sleep(random.randint(2,?5))
????????for?i?in?response.doc('li?>?div').items():
????????????#?設置全局變量
????????????global?count
????????????count?+=?1
????????????#?崗位名稱
????????????job_title?=?i('.job-title').text()
????????????print(job_title)
????????????#?崗位薪水
????????????job_salary?=?i('.red').text()
????????????print(job_salary)
????????????#?崗位地點
????????????city_result?=?re.search('(.*?)<em?class=',?i('.info-primary?>?p').html())
????????????job_city?=?city_result.group(1).split('?')[0]
????????????print(job_city)
????????????#?崗位經驗
????????????experience_result?=?re.search('<em?class="vline"/>(.*?)<em?class="vline"/>',?i('.info-primary?>?p').html())
????????????job_experience?=?experience_result.group(1)
????????????print(job_experience)
????????????#?崗位學歷
????????????job_education?=?i('.info-primary?>?p').text().replace('?',?'').replace(city_result.group(1).replace('?',?''),?'').replace(experience_result.group(1).replace('?',?''),'')
????????????print(job_education)
????????????#?公司名稱
????????????company_name?=?i('.info-company?a').text()
????????????print(company_name)
????????????#?公司類型
????????????company_type_result?=?re.search('(.*?)<em?class=',?i('.info-company?p').html())
????????????company_type?=?company_type_result.group(1)
????????????print(company_type)
????????????#?公司狀態
????????????company_status_result?=?re.search('<em?class="vline"/>(.*?)<em?class="vline"/>',?i('.info-company?p').html())
????????????if?company_status_result:
????????????????company_status?=?company_status_result.group(1)
????????????else:
????????????????company_status?=?'無信息'
????????????print(company_status)
????????????#?公司規模
????????????company_people?=?i('.info-company?p').text().replace(company_type,?'').replace(company_status,'')
????????????print(company_people?+?'\n')
????????????#?寫入數據庫中
????????????self.add_Mysql(count,?job_title,?job_salary,?job_city,?job_experience,?job_education,?company_name,?company_type,?company_status,?company_people)
????????#?獲取下一頁信息
????????next?=?response.doc('.next').attr.href
????????if?next?!=?'javascript:;':
????????????self.crawl(next,?callback=self.index_page,?validate_cert=False)
????????else:
????????????print("The?Work?is?Done")
????????#?詳情頁信息獲取,由于訪問次數有限制,不使用
????????#for?each?in?response.doc('.name?>?a').items():
????????????#url?=?each.attr.href
????????????#self.crawl(each.attr.href,?callback=self.detail_page,?validate_cert=False)

????@config(priority=2)
????def?detail_page(self,?response):
????????#?詳情頁信息獲取,由于訪問次數有限制,不使用
????????message_job?=?response.doc('div?>?.info-primary?>?p').text()
????????city_result?=?re.findall('城市:(.*?)經驗',?message_job)
????????experience_result?=?re.findall('經驗:(.*?)學歷',?message_job)
????????education_result?=?re.findall('學歷:(.*)',?message_job)

????????message_company?=?response.doc('.info-company?>?p').text().replace(response.doc('.info-company?>?p?>?a').text(),'')
????????status_result?=?re.findall('(.*?)\d',?message_company.split('?')[0])
????????people_result?=?message_company.split('?')[0].replace(status_result[0],?'')

????????return?{
????????????"job_title":?response.doc('h1').text(),
????????????"job_salary":?response.doc('.info-primary?.badge').text(),
????????????"job_city":?city_result[0],
????????????"job_experience":?experience_result[0],
????????????"job_education":?education_result[0],
????????????"job_skills":?response.doc('.info-primary?>?.job-tags?>?span').text(),
????????????"job_detail":?response.doc('div').filter('.text').eq(0).text().replace('\n',?''),
????????????"company_name":?response.doc('.info-company?>?.name?>?a').text(),
????????????"company_status":?status_result[0],
????????????"company_people":?people_result,
????????????"company_type":?response.doc('.info-company?>?p?>?a').text(),
????????}

獲取BOSS直聘數據分析崗數據如下:

640?

2、PyCharm獲取拉勾網數據

import?requests
import?pymysql
import?random
import?time
import?json

count?=?0
#?設置請求網址及請求頭參數
url?=?'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
headers?=?{
????'User-Agent':?'Mozilla/5.0?(Windows?NT?6.1;?WOW64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/63.0.3239.132?Safari/537.36',
????'Cookie':?'你的Cookie值',
????'Accept':?'application/json,?text/javascript,?*/*;?q=0.01',
????'Connection':?'keep-alive',
????'Host':?'www.lagou.com',
????'Origin':?'https://www.lagou.com',
????'Referer':?'ttps://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?labelWords=sug&fromSearch=true&suginput=shuju'
}

#?連接數據庫
db?=?pymysql.connect(host='127.0.0.1',?user='root',?password='774110919',?port=3306,?db='lagou_job',?charset='utf8mb4')


def?add_Mysql(id,?job_title,?job_salary,?job_city,?job_experience,?job_education,?company_name,?company_type,?company_status,?company_people,?job_tips,?job_welfare):
????#?將數據寫入數據庫中
????try:
????????cursor?=?db.cursor()
????????sql?=?'insert?into?job(id,?job_title,?job_salary,?job_city,?job_experience,?job_education,?company_name,?company_type,?company_status,?company_people,?job_tips,?job_welfare)?values?("%d",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s",?"%s")'?%?(id,?job_title,?job_salary,?job_city,?job_experience,?job_education,?company_name,?company_type,?company_status,?company_people,?job_tips,?job_welfare);
????????print(sql)
????????cursor.execute(sql)
????????print(cursor.lastrowid)
????????db.commit()
????except?Exception?as?e:
????????print(e)
????????db.rollback()


def?get_message():
????for?i?in?range(1,?31):
????????print('第'?+?str(i)?+?'頁')
????????time.sleep(random.randint(10,?20))
????????data?=?{
????????????'first':?'false',
????????????'pn':?i,
????????????'kd':?'數據分析'
????????}
????????response?=?requests.post(url=url,?data=data,?headers=headers)
????????result?=?json.loads(response.text)
????????job_messages?=?result['content']['positionResult']['result']
????????for?job?in?job_messages:
????????????global?count
????????????count?+=?1
????????????#?崗位名稱
????????????job_title?=?job['positionName']
????????????print(job_title)
????????????#?崗位薪水
????????????job_salary?=?job['salary']
????????????print(job_salary)
????????????#?崗位地點
????????????job_city?=?job['city']
????????????print(job_city)
????????????#?崗位經驗
????????????job_experience?=?job['workYear']
????????????print(job_experience)
????????????#?崗位學歷
????????????job_education?=?job['education']
????????????print(job_education)
????????????#?公司名稱
????????????company_name?=?job['companyShortName']
????????????print(company_name)
????????????#?公司類型
????????????company_type?=?job['industryField']
????????????print(company_type)
????????????#?公司狀態
????????????company_status?=?job['financeStage']
????????????print(company_status)
????????????#?公司規模
????????????company_people?=?job['companySize']
????????????print(company_people)
????????????#?工作技能
????????????if?len(job['positionLables'])?>?0:
????????????????job_tips?=?','.join(job['positionLables'])
????????????else:
????????????????job_tips?=?'None'
????????????print(job_tips)
????????????#?工作福利
????????????job_welfare?=?job['positionAdvantage']
????????????print(job_welfare?+?'\n\n')
????????????#?寫入數據庫
????????????add_Mysql(count,?job_title,?job_salary,?job_city,?job_experience,?job_education,?company_name,?company_type,?company_status,?company_people,?job_tips,?job_welfare)


if?__name__?==?'__main__':
????get_message()

獲取拉勾網數據分析崗數據如下:

640?

這里的數據庫都是自己在外面創建的,就不貼代碼細說了。


640?wx_fmt=png

數據可視化


1、城市分布圖

640?640?

崗位的分布情況,這里可以看出崗位大多都分布在東部地區,中部也有一些。

2、城市分布熱力圖

640?640?

京津冀、長三角、珠三角密集度不相上下,成都重慶地區也有一些小需求。

可以說北上廣深,這四個一線城市包攬了大部分的崗位需求。

3、工作經驗薪水圖

640?640?

這里通過看箱形圖的四分位及中間值,大致能看出隨著工作年限的增長,薪資也是一路上升。

BOSS直聘里,1年以內工作經驗的薪資,有個最高4萬多的,這肯定是不合理的。于是就去數據庫看了下,其實那個崗位要求是3年以上,但實際給的標簽卻是1年以內,所以說數據來源提供的數據的準確性很重要。

4、學歷薪水圖

640?640?

總的來說「碩士」>「本科」>「大專」,當然大專、本科中也有高薪水的。畢竟越往后能力就越重要,學歷算是一個重要的加分項。

5、公司狀態薪水圖

640?640?

這里的數據沒什么特點,就當了解下這些概念。一個公司的發展,可以是從「天使輪」一直到「上市公司」,路途坎坷。

6、公司規模薪水圖

640?640?

正常來說,公司規模越大,薪水應該會越高。畢竟大廠的工資擺在那里,想不知道都難。

不過這里沒能體現出來差距,倒是發現人數最少的公司,最高工資給的不高,難不成是初期缺錢?

7、公司類型TOP10

640?640?

數據分析崗主要集中在互聯網行業,「金融」、「地產」、「教育」、「醫療」、「游戲」也有所涉及,大部分崗位需求都集中第三產業上。

8、工作技能圖

這個算是本文的重點,這些技能將會是日后學習的重點。

640?

數據挖掘、SQL、BI、數據運營、SPSS、數據庫、MySQL等等最重要。

9、工作福利圖

640?

這里可以看出大部分重點都圍繞著「五險一金」、「福利多」、「團隊氛圍好」、「晉升空間大」、「行業大牛領頭」上。

要是哪家公司都具備了,那簡直就是要上天。不過你我都清楚,這是不存在的,就算可能存在,也只是別人家的公司而已~


640?wx_fmt=png

總結


最后貼兩張BOSS直聘以及拉勾網薪水TOP20,以此來作為勉勵。

1、BOSS直聘薪水TOP20

640?

2、拉勾網薪水TOP20

640?

畢竟我們不能僅僅當條咸魚,我們要當就當一只有夢想的咸魚!!!

獲取完整源碼可點擊:https://github.com/Tobby-star/JOB?files=1。

作者:法納斯特,Python愛好者,專注爬蟲,數據分析及可視化。

聲明:本文首發個人公眾號法納斯特,作者投稿,版權歸其個人所有。


640?wx_fmt=png

?熱 文?推 薦?

??華為員工 iPhone 發文遭罰;百度遭約談勒令整改;錘子 1577 萬元被法院保全 | 極客頭條

??30 歲后,哪些職業瓶頸阻礙了你的成長?

??漫畫:什么是字符集和編碼?ASCII、UTF-8、UTF-16、UTF-32 又是什么?

從傾家蕩產到身價百億,這個85后只用了8年

??難逃寒冬裁員的“大追殺”,30 歲女碼農該何去何從?

??OpenStack 2018 年終盤點

拼多多黃崢給陸奇“兼職”,欲挖掘這類AI人才

??老程序員肺腑忠告:千萬別一輩子靠技術生存!

print_r('點個好看吧!');
var_dump('點個好看吧!');
NSLog(@"點個好看吧!");
System.out.println("點個好看吧!");
console.log("點個好看吧!");
print("點個好看吧!");
printf("點個好看吧!\n");
cout?<<?"點個好看吧!"?<<?endl;
Console.WriteLine("點個好看吧!");
fmt.Println("點個好看吧!");
Response.Write("點個好看吧!");
alert("點個好看吧!")
echo "點個好看吧!"

640?wx_fmt=gif點擊“閱讀原文”,打開 CSDN App 閱讀更貼心!

640?wx_fmt=png喜歡就點擊“好看”吧

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息