python爬蟲:爬取拉勾網職位並分析

博客內容:爬取拉鉤網上的數據並進行分析,參考代碼鏈接爲點擊打開鏈接

網頁爬取部分:

import requests  
import math  
import pandas as pd  
import time  

def get_json(url,num):  
   '''''從網頁獲取JSON,使用POST請求,加上頭部信息'''
   #my_headers 是json的一個實例
   my_headers = {  
           'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',  
           'Host':'www.lagou.com',  
           'Referer':'https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?labelWords=&fromSearch=true&suginput=',
           # 'Referer':'https://www.lagou.com/jobs/list_%E5%88%9D%E4%B8%AD%E7%89%A9%E7%90%86%E8%80%81%E5%B8%88?labelWords=&fromSearch=true&suginput=',
           'X-Anit-Forge-Code':'0',
           'X-Anit-Forge-Token': 'None',  
           'X-Requested-With':'XMLHttpRequest'  
           }

   my_data = {  
           'first': 'true',  
           'pn':num,
           'kd':'數據分析'}

   res = requests.post(url, headers = my_headers, data = my_data)  
   res.raise_for_status()  #檢查請求是否成功,有錯就會報出,正常就只會輸出none
   res.encoding = 'utf-8'  
   # 得到包含職位信息的字典  
   page = res.json()  
   return page  


def get_page_num(count):  
   '''''計算要抓取的頁數'''  
   # 每頁15個職位,向上取整  
   res = math.ceil(count/15)  
   # 拉勾網最多顯示30頁結果  
   if res > 30:  
       return 30  
   else:  
       return res  

def get_page_info(jobs_list):  
   '''''對一個網頁的職位信息進行解析,返回列表'''  
   page_info_list = []  
   for i in jobs_list:  
       job_info = []  
       job_info.append(i['companyFullName'])  
       job_info.append(i['companyShortName'])  
       job_info.append(i['companySize'])  
       job_info.append(i['financeStage'])  
       job_info.append(i['district'])  
       job_info.append(i['positionName'])  
       job_info.append(i['workYear'])  
       job_info.append(i['education'])  
       job_info.append(i['salary'])  
       job_info.append(i['positionAdvantage'])  
       page_info_list.append(job_info)  
   return page_info_list  

def main():  
   url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E6%B7%B1%E5%9C%B3&needAddtionalResult=false'
   # url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E6%B7%B1%E5%9C%B3&needAddtionalResult=false'

   # 先設定頁數爲1,獲取總的職位數  
   page_1 = get_json(url,1)  
   total_count = page_1['content']['positionResult']['totalCount']  #通過分析網頁,找到返回網頁中的totalCount
   num = get_page_num(total_count)  #調用函數,計算出總網頁數
   total_info = []  
   time.sleep(20)  #這裏爲什麼要停20秒?
   print('職位總數:{},頁數:{}'.format(total_count,num))  #這裏是python中的語法

   for n in range(1,3):
       # 對每個網頁讀取JSON, 獲取每頁數據  
       page = get_json(url,n)  
       jobs_list = page['content']['positionResult']['result']
       # print(jobs_list)
       page_info = get_page_info(jobs_list)
       total_info += page_info
       # print(total_info)
       print('已經抓取第{}頁, 職位總數:{}'.format(n, len(total_info)))  
       # 每次抓取完成後,暫停一會,防止被服務器拉黑  
       time.sleep(30)  
   #將總數據轉化爲data frame再輸出  
   df = pd.DataFrame(data = total_info,columns = ['公司全名','公司簡稱','公司規模','融資階段','區域','職位名稱','工作經驗','學歷要求','工資','職位福利'])   
   df.to_csv('lagou_datamini_jobs.csv',index = False)
   print('已保存爲csv文件.')  

if __name__== "__main__":   
   main()

數據分析代碼:

import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from wordcloud import WordCloud
from scipy.misc import imread
import jieba
from pylab import mpl

# 使matplotlib模塊能顯示中文
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默認字體
mpl.rcParams['axes.unicode_minus'] = False # 解決保存圖像是負號'-'顯示爲方塊的問題

# 讀取數據
df = pd.read_csv('lagou_jobs.csv', encoding = 'gbk')
#df = pd.read_csv(r'H:\pycharm\python\reptileLagou\reptile\lagou_jobs.csv', encoding='gbk')

# 數據清洗,剔除實習崗位
#pandas刪除某行的方式是先找到它的行索引
df.drop(df[df['職位名稱'].str.contains('實習')].index, inplace=True)#找到需要剔除的關鍵字的位置後再進行剔除
# print(df.describe())

# 由於CSV文件內的數據是字符串形式,先用正則表達式將字符串轉化爲列表,再取區間的均值
pattern = '\d+'
df['工作年限'] = df['工作經驗'].str.findall(pattern)

avg_work_year = []
for i in df['工作年限']:
   # 如果工作經驗爲'不限'或'應屆畢業生',那麼匹配值爲空,工作年限爲0
   if len(i) == 0:
       avg_work_year.append(0)
   # 如果匹配值爲一個數值,那麼返回該數值
   elif len(i) == 1:
       avg_work_year.append(int(''.join(i)))
   # 如果匹配值爲一個區間,那麼取平均值
   else:
       num_list = [int(j) for j in i]
       avg_year = sum(num_list)/2
       avg_work_year.append(avg_year)

df['經驗'] = avg_work_year

# 將字符串轉化爲列表,再取區間的前25%,比較貼近現實
df['salary'] = df['工資'].str.findall(pattern)

avg_salary = []
for k in df['salary']:
   int_list = [int(n) for n in k]
   avg_wage = int_list[0]+(int_list[1]-int_list[0])/4
   avg_salary.append(avg_wage)

df['月工資'] = avg_salary
# 將清洗後的數據保存,以便檢查
df.to_csv('draft.csv', index = False)

# 描述統計
print('數據分析師工資描述:\n{}'.format(df['月工資'].describe())) #pandas 的describe()函數會列出各列的和、平均數、方差、最小值、最大值以及quantile數值

# 繪製頻率直方圖並保存
plt.hist(df['月工資'],bins = 12)
plt.xlabel('工資 (千元)')
plt.ylabel('頻數')
plt.title("工資直方圖")
plt.savefig('histogram.jpg')
plt.show()

# 繪製餅圖並保存
count = df['區域'].value_counts()
# 將龍華區和龍華新區的數據彙總
count['龍華新區'] += count['龍華區']
del count['龍華區']
plt.pie(count, labels = count.keys(),labeldistance=1.4,autopct='%2.1f%%')
plt.axis('equal')  # 使餅圖爲正圓形
plt.legend(loc='upper left', bbox_to_anchor=(-0.1, 1))
plt.savefig('pie_chart.jpg')
plt.show()

# 繪製詞雲,將職位福利中的字符串彙總
text = ''
for line in df['職位福利']:
   text += line
# 使用jieba模塊將字符串分割爲單詞列表
cut_text = ' '.join(jieba.cut(text))
color_mask = imread('cloud.jpg')  #設置背景圖
cloud = WordCloud(
       # font_path = 'yahei.ttf',
       font_path='simhei.ttf',#字體格式,不設置就會亂碼,如果加載的字體格式環境裏不存在會報OSError的錯。
       background_color = 'white',#背景顏色
       mask = color_mask,#詞雲背景圖
       max_words = 1000,#最大單詞數
       max_font_size = 100#最大字體號
       )
word_cloud = cloud.generate(cut_text)#產生詞雲
# 保存詞雲圖片
word_cloud.to_file('word_cloud.jpg')#保存詞雲
plt.imshow(word_cloud)#顯示詞雲圖片
plt.axis('off')
plt.show()

# 實證統計,將學歷不限的職位要求認定爲最低學歷:大專
df['學歷要求'] = df['學歷要求'].replace('不限','大專')

# 學歷分爲大專\本科\碩士,將它們設定爲虛擬變量
dummy_edu = pd.get_dummies(df['學歷要求'],prefix = '學歷')
# 構建迴歸數組
df_with_dummy = pd.concat([df['月工資'],df['經驗'],dummy_edu],axis = 1)

# 建立多元迴歸模型
y = df_with_dummy['月工資']
X = df_with_dummy[['經驗','學歷_大專','學歷_本科','學歷_碩士']]
X=sm.add_constant(X)
model = sm.OLS(y,X)
results = model.fit()
print('迴歸方程的參數:\n{}\n'.format(results.params))
print('迴歸結果:\n{}'.format(results.summary()))

數據分析結果:

圖一:工資頻率直方圖



圖二:崗位位置分佈圖


圖三:崗位福利待遇詞雲圖



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章