日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python爬虫爬取智联招聘(进阶版)

發布時間:2023/12/14 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python爬虫爬取智联招聘(进阶版) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

運行平臺:?Windows ?
Python版本:?Python3.6 ?
IDE:?Sublime Text ??
其他工具:??Chrome瀏覽器

0、寫在前面的話

本文是基于基礎版上做的修改,如果沒有閱讀基礎版,請移步?Python爬蟲抓取智聯招聘(基礎版)

在基礎版中,構造url時使用了urllib庫的urlencode函數:

url = 'https://sou.zhaopin.com/jobs/searchresult.ashx?' + urlencode(paras)
? ?try:
? ? ? ?# 獲取網頁內容,返回html數據
? ? ? ?response = requests.get(url, headers=headers)
? ?...

其實用reuqests庫可以完成此工作,本例將該部分改為:

url = 'https://sou.zhaopin.com/jobs/searchresult.ashx?'
? ?try:
? ? ? ?# 獲取網頁內容,返回html數據
? ? ? ?response = requests.get(url, params=paras, headers=headers)
? ?...

1、找到職位鏈接

為了得到更加詳細的職位信息,我們要找到職位鏈接,在新的頁面中尋找數據。上篇文章中我們沒有解析職位鏈接,那再來找一下吧:

修改一下正則表達式:

# 正則表達式進行解析
? ?pattern = re.compile('<td class="zwmc".*?href="(.*?)" target="_blank">(.*?)</a>.*?' # 匹配職位詳情地址和職位名稱
? ? ? ?'<td class="gsmc">.*? target="_blank">(.*?)</a>.*?' ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 匹配公司名稱
? ? ? ?'<td class="zwyx">(.*?)</td>', re.S) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# 匹配月薪 ? ? ?

? ?# 匹配所有符合條件的內容
? ?items = re.findall(pattern, html) ?

2、求工資平均值

工資有兩種形式xxxx-yyyy或者面議,此處取第一種形式的平均值作為分析標準,雖有偏差但是也差不多,這是求職中最重要的一項指標。

for item in items:
? ?salary_avarage = 0
? ?temp = item[3]
? ?if temp != '面議':
? ? ? ?idx = temp.find('-')
? ? ? ?# 求平均工資
? ? ? ?salary_avarage = (int(temp[0:idx]) + int(temp[idx+1:]))//2

3、解析職位詳細信息

3.1 網頁解析

第一步已經將職位地址找到,在瀏覽器打開之后我們要找到如下幾項數據:

在開發者工具中查找這幾項數據,如下圖所示:

HTML結構如下所示:

# 數據HTML結構
<body>
|------<div class="terminalpage clearfix">
==>|------<div class="terminalpage-left">
==>==>|------<ul class="terminal-ul clearfix">
==>==>==>|------<li><span>工作經驗:</span><strong>3-5年</strong>
==>==>==>|------<li><span>最低學歷:</span><strong>本科</strong>
==>==>|------<div class="terminalpage-main clearfix">
==>==>==>|------<div class="tab-cont-box">
==>==>==>==>|------<div class="tab-inner-cont">
==>==>==>==>==>|------<p>工作職責:</p>
==>==>==>==>==>|------<p>********</p>
==>==>==>==>==>|------<p>********</p> ? ?# 工作職責詳情
==>|------<div class="terminalpage-right"> ? ?
==>==>|------<div class="company-box">
==>==>==>|------<ul class="terminal-ul clearfix terminal-company mt20">
==>==>==>==>|------<li><span>公司規模:</span><strong>100-499人</strong>

3.2 代碼實現

為了學習一下BeautifulSoup庫的使用,我們不再使用正則表達式解析,而是BeautifulSoup庫解析HTML標簽來獲得我們想要得到的內容。

解析庫的安裝:pip install beautifulsoup4

下面介紹一下本例中使用到的功能:

  • 庫的引入:from bs4 import BeautifulSoup

  • 數據引入:soup = BeautifulSoup(html, 'html.parser')?,其中html是我們要解析的html源碼,html.parser指定HTML的解析器為Python標準庫。

  • 查找標簽:find(name,attrs,recursive,text,**kwargs),find返回的匹配結果的第一個元素

  • 查找所有標簽:find_all(name,attrs,recursive,text,**kwargs)可以根據標簽名,屬性,內容查找文檔,返回找到的所有元素

  • 獲取內容:get_text()就可以獲取文本內容

  • 獲取子標簽:soup.p這種方式就可以獲取到soup下的第一個p標簽

def get_job_detail(html):
? ?requirement = ''
? ?# 使用BeautifulSoup進行數據篩選
? ?soup = BeautifulSoup(html, 'html.parser')
? ?# 找到<ul class="terminal-ul clearfix">標簽
? ?for ul in soup.find_all('ul', class_='terminal-ul clearfix'):
? ? ? ?# 該標簽共有8個子標簽,分別為:
? ? ? ?# 職位月薪|工作地點|發布日期|工作性質|工作經驗|最低學歷|招聘人數|職位類別
? ? ? ?lis = ul.find_all('strong')
? ? ? ?# 工作經驗
? ? ? ?years = lis[4].get_text()
? ? ? ?# 最低學歷
? ? ? ?education = lis[5].get_text()
? ?# 篩選任職要求
? ?for terminalpage in soup.find_all('div', class_='terminalpage-main clearfix'):
? ? ? ?for box in terminalpage.find_all('div', class_='tab-cont-box'):
? ? ? ? ? ?cont = box.find_all('div', class_='tab-inner-cont')[0]
? ? ? ? ? ?ps = cont.find_all('p')
? ? ? ? ? ?# "立即申請"按鈕也是個p標簽,將其排除
? ? ? ? ? ?for i in range(len(ps) - 1):
? ? ? ? ? ? ? ?requirement += ps[i].get_text().replace("\n", "").strip() ? # 去掉換行符和空格

? ?# 篩選公司規模,該標簽內有四個或五個<li>標簽,但是第一個就是公司規模
? ?scale = soup.find(class_='terminal-ul clearfix terminal-company mt20').find_all('li')[0].strong.get_text()

? ?return {'years': years, 'education': education, 'requirement': requirement, 'scale': scale}

本次我們將職位描述寫入txt文件,其余信息寫入csv文件。

csv文件采用逐行寫入的方式這樣也可以省點內存,修改write_csv_rows函數:

def write_csv_rows(path, headers, rows):
? ?'''
? ?寫入行
? ?'''

? ?with open(path, 'a', encoding='gb18030', newline='') as f:
? ? ? ?f_csv = csv.DictWriter(f, headers)
? ? ? ?# 如果寫入數據為字典,則寫入一行,否則寫入多行
? ? ? ?if type(rows) == type({}):
? ? ? ? ? ?f_csv.writerow(rows)
? ? ? ?else:
? ? ? ? ? ?f_csv.writerows(rows)

添加寫txt文件函數:

def write_txt_file(path, txt):
? ?'''
? ?寫入txt文本
? ?'''

? ?with open(path, 'a', encoding='gb18030', newline='') as f:
? ? ? ?f.write(txt)

我們最重要對職位描述的內容進行詞頻統計,一些標點符號等會影響統計,使用正則表達式將其剔除:

# 對數據進行清洗,將標點符號等對詞頻統計造成影響的因素剔除
pattern = re.compile(r'[一-龥]+')
filterdata = re.findall(pattern, job_detail.get('requirement'))
write_txt_file(txt_filename, ''.join(filterdata))

至此,職位詳細信息的獲取及保存的工作已經完成,來看一下此時的main函數:

def main(city, keyword, region, pages):
? ?'''
? ?主函數
? ?'''

? ?csv_filename = 'zl_' + city + '_' + keyword + '.csv'
? ?txt_filename = 'zl_' + city + '_' + keyword + '.txt'
? ?headers = ['job', 'years', 'education', 'salary', 'company', 'scale', 'job_url']
? ?write_csv_headers(csv_filename, headers)
? ?for i in range(pages):
? ? ? ?'''
? ? ? ?獲取該頁中所有職位信息,寫入csv文件
? ? ? ?'''

? ? ? ?job_dict = {}
? ? ? ?html = get_one_page(city, keyword, region, i)
? ? ? ?items = parse_one_page(html)
? ? ? ?for item in items:
? ? ? ? ? ?html = get_detail_page(item.get('job_url'))
? ? ? ? ? ?job_detail = get_job_detail(html)

? ? ? ? ? ?job_dict['job'] = item.get('job')
? ? ? ? ? ?job_dict['years'] = job_detail.get('years')
? ? ? ? ? ?job_dict['education'] = job_detail.get('education')
? ? ? ? ? ?job_dict['salary'] = item.get('salary')
? ? ? ? ? ?job_dict['company'] = item.get('company')
? ? ? ? ? ?job_dict['scale'] = job_detail.get('scale')
? ? ? ? ? ?job_dict['job_url'] = item.get('job_url')

? ? ? ? ? ?# 對數據進行清洗,將標點符號等對詞頻統計造成影響的因素剔除
? ? ? ? ? ?pattern = re.compile(r'[一-龥]+')
? ? ? ? ? ?filterdata = re.findall(pattern, job_detail.get('requirement'))
? ? ? ? ? ?write_txt_file(txt_filename, ''.join(filterdata))
? ? ? ? ? ?write_csv_rows(csv_filename, headers, job_dict)

4、數據分析

本節內容為此版本的重點。

4.1 工資統計

我們對各個階段工資的占比進行統計,分析該行業的薪資分布水平。前面我們已經把數據保存到csv文件里了,接下來要讀取salary列:

def read_csv_column(path, column):
? ?'''
? ?讀取一列
? ?'''

? ?with open(path, 'r', encoding='gb18030', newline='') as f:
? ? ? ?reader = csv.reader(f)
? ? ? ?return [row[column] for row in reader]

# main函數里添加
print(read_csv_column(csv_filename, 3))

#下面為打印結果
['salary', '7000', '5000', '25000', '12500', '25000', '20000', '32500', '20000', '15000', '9000', '5000', '5000', '12500', '24000', '15000', '18000', '25000', '20000', '0', '20000', '12500', '17500', '17500', '20000', '11500', '25000', '12500', '17500', '25000', '22500', '22500', '25000', '17500', '7000', '25000', '3000', '22500', '15000', '25000', '20000', '22500', '15000', '15000', '25000', '17500', '22500', '10500', '20000', '17500', '22500', '17500', '25000', '20000', '11500', '11250', '12500', '14000', '12500', '17500', '15000']

從結果可以看出,除了第一項,其他的都為平均工資,但是此時的工資為字符串,為了方便統計,我們將其轉換成整形:

salaries = []
sal = read_csv_column(csv_filename, 3)
? ?# 撇除第一項,并轉換成整形,生成新的列表
? ?for i in range(len(sal) - 1):
? ? ? ?# 工資為'0'的表示招聘上寫的是'面議',不做統計
? ? ? ?if not sal[i] == '0':
? ? ? ? ? ?salaries.append(int(sal[i + 1]))
? ?print(salaries)

# 下面為打印結果
[7000, 5000, 25000, 12500, 25000, 20000, 32500, 20000, 15000, 9000, 5000, 5000, 12500, 24000, 15000, 18000, 25000, 20000, 0, 20000, 12500, 20000, 11500, 17500, 25000, 12500, 17500, 25000, 25000, 22500, 22500, 17500, 17500, 7000, 25000, 3000, 22500, 15000, 25000, 20000, 22500, 15000, 22500, 10500, 20000, 15000, 17500, 17500, 25000, 17500, 22500, 25000, 12500, 20000, 11250, 11500, 14000, 12500, 15000, 17500]

我們用直方圖進行展示:

plt.hist(salaries, bins=10 ,)
plt.show()

生成效果圖如下:

從圖中可以看出工資分布的情況,這樣在你找工作時可以做一個參考。

4.2 職位描述詞頻統計

對職位描述詞頻統計的意義是可以了解該職位對技能的基本要求,如果正在找工作,可以估計一下自己的要求是否符合該職位;如果想要一年后換工作,那么也可以提前做好準備,迎接新的挑戰。

詞頻統計用到了 jieba、numpy、pandas、scipy庫。如果電腦上沒有這兩個庫,執行安裝指令:

  • pip install jieba

  • pip install pandas

  • pip install numpy

  • pip install scipy

4.2.1 讀取txt文件

前面已經將職位描述保存到txt文件里了,現在我們將其讀出:

def read_txt_file(path):
? ?'''
? ?讀取txt文本
? ?'''

? ?with open(path, 'r', encoding='gb18030', newline='') as f:
? ? ? ?return f.read()

簡單測試一下:

import jieba
import pandas as pd

content = read_txt_file(txt_filename)
segment = jieba.lcut(content)
words_df=pd.DataFrame({'segment':segment})
print(words_df)

# 輸出結果如下:
? ? ?segment
0 ? ? ? ?崗位職責
1 ? ? ? ? ?參與
2 ? ? ? ? ?公司
3 ? ? ? ?軟件產品
4 ? ? ? ? ?后臺
5 ? ? ? ? ?研發
6 ? ? ? ? ? 和
7 ? ? ? ? ?維護
8 ? ? ? ? ?工作
9 ? ? ? ? ?參與
10 ? ? ? ?建筑物
11 ? ? ? ? 聯網
12 ? ? ? 數據分析
13 ? ? ? ? 算法
14 ? ? ? ? ?的
15 ? ? ? ? 設計
16 ? ? ? ? ?和
17 ? ? ? ? 開發
18 ? ? ? ? ?可
19 ? ? ? ? 獨立
20 ? ? ? ? 完成
21 ? ? ? ? 業務
22 ? ? ? ? 算法
23 ? ? ? ? 模塊
... ? ? ? ? ? ...

從結果可以看出:“崗位職責”、“參與”、“公司”、軟件產品“、”的“、”和“等單詞并沒有實際意義,所以我們要將他們從表中刪除。

4.2.2 stop word

下面引入一個概念:stop word, 在網站里面存在大量的常用詞比如:“在”、“里面”、“也”、“的”、“它”、“為”這些詞都是停止詞。這些詞因為使用頻率過高,幾乎每個網頁上都存在,所以搜索引擎開發人員都將這一類詞語全部忽略掉。如果我們的網站上存在大量這樣的詞語,那么相當于浪費了很多資源。

在百度搜索stpowords.txt進行下載,放到py文件同級目錄。接下來測試一下:

content = read_txt_file(txt_filename)
segment = jieba.lcut(content)
words_df=pd.DataFrame({'segment':segment})

stopwords=pd.read_csv("stopwords.txt",index_col=False,quoting=3,sep=" ",names=['stopword'],encoding='utf-8')
words_df=words_df[~words_df.segment.isin(stopwords.stopword)]

print(words_df)

# 以下為輸出結果
0 ? ? ? ?崗位職責
1 ? ? ? ? ?參與
2 ? ? ? ? ?公司
3 ? ? ? ?軟件產品
4 ? ? ? ? ?后臺
5 ? ? ? ? ?研發
7 ? ? ? ? ?維護
8 ? ? ? ? ?工作
9 ? ? ? ? ?參與
10 ? ? ? ?建筑物
11 ? ? ? ? 聯網
12 ? ? ? 數據分析
13 ? ? ? ? 算法
15 ? ? ? ? 設計
17 ? ? ? ? 開發
19 ? ? ? ? 獨立
21 ? ? ? ? 業務
22 ? ? ? ? 算法
23 ? ? ? ? 模塊
24 ? ? ? ? 開發
28 ? ? ? ? 產品
29 ? ? ? ? 目標
31 ? ? ? ? 改進
32 ? ? ? ? 創新
33 ? ? ? ? 任職
35 ? ? ? ? 熟練
38 ? ? ? ? 開發
39 ? ? ? ? 經驗
40 ? ? ? ? 優先
41 ? ? ? ? 熟悉
... ? ? ?...

從結果看出,那些常用的stop word比如:“的”、“和”、“可”等已經被剔除了,但是還有一些詞如“崗位職責”、“參與”等也沒有實際意義,如果對詞頻統計不產生影響,那么就無所謂,在后面統計時再決定是否對其剔除。

4.2.3 詞頻統計

重頭戲來了,詞頻統計使用numpy

import numpy

words_stat = words_df.groupby(by=['segment'])['segment'].agg({"計數":numpy.size})
? ?words_stat = words_stat.reset_index().sort_values(by=["計數"],ascending=False)
? ?print(words_stat)

# 以下是爬取全部“北京市海淀區Python工程師”職位的運行結果:
? ?segment ? 計數
362 ? ? ?開發 ?505
590 ? ? ?熟悉 ?409
701 ? ? ?經驗 ?281
325 ? ? ?工作 ?209
820 ? ? ?負責 ?171
741 ? ? ?能力 ?169
793 ? ? ?設計 ?161
82 ? ? ? 優先 ?160
409 ? ? ?技術 ?157
621 ? ? ?相關 ?145
322 ? ?崗位職責 ?127
683 ? ? ?系統 ?126
64 ? ? ? 產品 ?124
904 ? ? ?項目 ?123
671 ? ? ?算法 ?107
78 ? ? ? 任職 ?107
532 ? ? ?框架 ?107
591 ? ? ?熟練 ?104

可以看出,某些詞語還是影響了統計結果,我將以下stop word加入stopword.txt中:

開發、熟悉、熟練、精通、經驗、工作、負責、能力、有限、相關、崗位職責、任職、語言、平臺、參與、優先、技術、學習、產品、公司、熟練掌握、以上學歷

最后運行結果如下:

775 ? ? ?設計 ?136
667 ? ? ?系統 ?109
884 ? ? ?項目 ?105
578 ? ? ?熟練 ? 95
520 ? ? ?框架 ? 92
656 ? ? ?算法 ? 90
143 ? ? ?分析 ? 90
80 ? ? ? 優化 ? 77
471 ? ? 數據庫 ? 75
693 ? ? ?維護 ? 66
235 ? ? ?團隊 ? 65
72 ? ? ? 代碼 ? 61
478 ? ? ?文檔 ? 60
879 ? ? ?需求 ? 58
766 ? ? 計算機 ? 56
698 ? ? ?編程 ? 56
616 ? ? ?研發 ? 49
540 ? ? ?溝通 ? 49
527 ? ? ?模塊 ? 49
379 ? ? ?性能 ? 46
695 ? ? ?編寫 ? 45
475 ? ?數據結構 ? 44

這樣基本上就是對技能的一些要求了,你也可以根據自己的需求再去修改stopword.txt已達到更加完美的效果。

4.2.4 詞頻可視化:詞云

詞頻統計雖然出來了,可以看出排名,但是不完美,接下來我們將它可視化。使用到wordcloud庫,詳細介紹見 github ,使用pip install wordcloud進行安裝。

from scipy.misc import imread
from wordcloud import WordCloud, ImageColorGenerator

? ?# 設置詞云屬性
? ?color_mask = imread('background.jfif')
? ?wordcloud = WordCloud(font_path="simhei.ttf", ? # 設置字體可以顯示中文
? ? ? ? ? ? ? ? ? ?background_color="white", ? ? ? # 背景顏色
? ? ? ? ? ? ? ? ? ?max_words=100, ? ? ? ? ? ? ? ? ?# 詞云顯示的最大詞數
? ? ? ? ? ? ? ? ? ?mask=color_mask, ? ? ? ? ? ? ? ?# 設置背景圖片
? ? ? ? ? ? ? ? ? ?max_font_size=100, ? ? ? ? ? ? ?# 字體最大值
? ? ? ? ? ? ? ? ? ?random_state=42,
? ? ? ? ? ? ? ? ? ?width=1000, height=860, margin=2,# 設置圖片默認的大小,但是如果使用背景圖片的話, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 那么保存的圖片大小將會按照其大小保存,margin為詞語邊緣距離
? ? ? ? ? ? ? ? ? ?)


? ?# 生成詞云, 可以用generate輸入全部文本,也可以我們計算好詞頻后使用generate_from_frequencies函數
? ?word_frequence = {x[0]:x[1]for x in words_stat.head(100).values}
? ?word_frequence_dict = {}
? ?for key in word_frequence:
? ? ? ?word_frequence_dict[key] = word_frequence[key]

? ?wordcloud.generate_from_frequencies(word_frequence_dict)
? ?# 從背景圖片生成顏色值 ?
? ?image_colors = ImageColorGenerator(color_mask)
? ?# 重新上色
? ?wordcloud.recolor(color_func=image_colors)
? ?# 保存圖片
? ?wordcloud.to_file('output.png')
? ?plt.imshow(wordcloud)
? ?plt.axis("off")
? ?plt.show()

運行效果圖如下(左圖為原圖,右圖為生成的圖片):

至此,詞頻統計及其可視化完成。

5、其他想法

本例中進行了兩種數據分析,雖為進階版,但是還是有很多可以繼續發揮的地方:

  • 分析工作年限和工資的關系并展示、預測

  • 統計不同工作崗位的薪資差別

  • 利用多線程或多進程提升效率

有興趣的可以嘗試做一下。

完整代碼: #-*- coding: utf-8 -*- import re import csv import jieba import numpy import requests from tqdm import tqdm import pandas as pd from scipy.misc import imread from wordcloud import WordCloud, ImageColorGenerator from collections import Counter from bs4 import BeautifulSoup import matplotlib.pyplot as plt from requests.exceptions import RequestExceptiondef get_one_page(city, keyword, region, page):''' 獲取網頁html內容并返回 ''' paras = {'jl': city, # 搜索城市 'kw': keyword, # 搜索關鍵詞 'isadv': 0, # 是否打開更詳細搜索選項 'isfilter': 1, # 是否對結果過濾 'sg': 'd5259c62115f44e3bbb380dc88411919', 'p': page, # 頁數 're': region # region的縮寫,地區,2005代表海淀 }headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36', 'Host': 'sou.zhaopin.com', 'Referer': 'http://sou.zhaopin.com/jobs/searchresult.ashx?jl=530&kw=python%E5%B7%A5%E7%A8%8B%E5%B8%88&sm=0&p=1', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9' }url = 'https://sou.zhaopin.com/jobs/searchresult.ashx?' try:# 獲取網頁內容,返回html數據 response = requests.get(url, params=paras, headers=headers)print(response.url)# 通過狀態碼判斷是否獲取成功 if response.status_code == 200:return response.textreturn None except RequestException as e:return None def parse_one_page(html):''' 解析HTML代碼,提取有用信息并返回 ''' # 正則表達式進行解析 pattern = re.compile('<td class="zwmc".*?href="(.*?)" target="_blank">(.*?)</a>.*?' # 匹配職位詳情地址和職位名稱 '<td class="gsmc">.*? target="_blank">(.*?)</a>.*?' # 匹配公司名稱 '<td class="zwyx">(.*?)</td>', re.S) # 匹配月薪 # 匹配所有符合條件的內容 items = re.findall(pattern, html)for item in items:job_name = item[1]job_name = job_name.replace('<b>', '')job_name = job_name.replace('</b>', '')salary_avarage = 0 temp = item[3]if temp != '面議':idx = temp.find('-')# 求平均工資 salary_avarage = (int(temp[0:idx]) + int(temp[idx+1:]))//2 # html = get_detail_page(job_url) # print(html) yield {'job': job_name, 'job_url': item[0], 'company': item[2], 'salary': salary_avarage}def get_detail_page(url):''' 獲取職位詳情頁html內容并返回 ''' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 'Host': 'jobs.zhaopin.com', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9' }try:# 獲取網頁內容,返回html數據 response = requests.get(url, headers=headers)# 通過狀態碼判斷是否獲取成功 if response.status_code == 200:return response.textreturn None except RequestException as e:return None def get_job_detail(html):requirement = '' # 使用BeautifulSoup進行數據篩選 soup = BeautifulSoup(html, 'html.parser')# 找到<ul class="terminal-ul clearfix">標簽 for ul in soup.find_all('ul', class_='terminal-ul clearfix'):# 該標簽共有8個子標簽,分別為: # 職位月薪|工作地點|發布日期|工作性質|工作經驗|最低學歷|招聘人數|職位類別 lis = ul.find_all('strong')# 工作經驗 years = lis[4].get_text()# 最低學歷 education = lis[5].get_text()# 篩選任職要求 for terminalpage in soup.find_all('div', class_='terminalpage-main clearfix'):for box in terminalpage.find_all('div', class_='tab-cont-box'):cont = box.find_all('div', class_='tab-inner-cont')[0]ps = cont.find_all('p')# "立即申請"按鈕也是個p標簽,將其排除 for i in range(len(ps) - 1):requirement += ps[i].get_text().replace("\n", "").strip() # 去掉換行符和空格 # 篩選公司規模,該標簽內有四個或五個<li>標簽,但是第一個就是公司規模 scale = soup.find(class_='terminal-ul clearfix terminal-company mt20').find_all('li')[0].strong.get_text()return {'years': years, 'education': education, 'requirement': requirement, 'scale': scale}def write_csv_file(path, headers, rows):''' 將表頭和行寫入csv文件 ''' # 加入encoding防止中文寫入報錯 # newline參數防止每寫入一行都多一個空行 with open(path, 'a', encoding='gb18030', newline='') as f:f_csv = csv.DictWriter(f, headers)f_csv.writeheader()f_csv.writerows(rows)def write_csv_headers(path, headers):''' 寫入表頭 ''' with open(path, 'a', encoding='gb18030', newline='') as f:f_csv = csv.DictWriter(f, headers)f_csv.writeheader()def write_csv_rows(path, headers, rows):''' 寫入行 ''' with open(path, 'a', encoding='gb18030', newline='') as f:f_csv = csv.DictWriter(f, headers)# 如果寫入數據為字典,則寫入一行,否則寫入多行 if type(rows) == type({}):f_csv.writerow(rows)else:f_csv.writerows(rows)def read_csv_column(path, column):''' 讀取一列 ''' with open(path, 'r', encoding='gb18030', newline='') as f:reader = csv.reader(f)return [row[column] for row in reader]def write_txt_file(path, txt):''' 寫入txt文本 ''' with open(path, 'a', encoding='gb18030', newline='') as f:f.write(txt)def read_txt_file(path):''' 讀取txt文本 ''' with open(path, 'r', encoding='gb18030', newline='') as f:return f.read()def main(city, keyword, region, pages):''' 主函數 ''' csv_filename = 'zl_' + city + '_' + keyword + '.csv' txt_filename = 'zl_' + city + '_' + keyword + '.txt' headers = ['job', 'years', 'education', 'salary', 'company', 'scale', 'job_url']salaries = []write_csv_headers(csv_filename, headers)for i in range(pages):''' 獲取該頁中所有職位信息,寫入csv文件 ''' job_dict = {}html = get_one_page(city, keyword, region, i)items = parse_one_page(html)for item in items:html = get_detail_page(item.get('job_url'))job_detail = get_job_detail(html)job_dict['job'] = item.get('job')job_dict['years'] = job_detail.get('years')job_dict['education'] = job_detail.get('education')job_dict['salary'] = item.get('salary')job_dict['company'] = item.get('company')job_dict['scale'] = job_detail.get('scale')job_dict['job_url'] = item.get('job_url')# 對數據進行清洗,將標點符號等對詞頻統計造成影響的因素剔除 pattern = re.compile(r'[一-龥]+')filterdata = re.findall(pattern, job_detail.get('requirement'))write_txt_file(txt_filename, ''.join(filterdata))write_csv_rows(csv_filename, headers, job_dict)sal = read_csv_column(csv_filename, 3)# 撇除第一項,并轉換成整形,生成新的列表 for i in range(len(sal) - 1):# 工資為'0'的表示招聘上寫的是'面議',不做統計 if not sal[i] == '0':salaries.append(int(sal[i + 1]))plt.hist(salaries, bins=10 ,)plt.show()content = read_txt_file(txt_filename)segment = jieba.lcut(content)words_df = pd.DataFrame({'segment':segment})stopwords = pd.read_csv("stopwords.txt",index_col=False,quoting=3,sep=" ",names=['stopword'],encoding='utf-8')words_df = words_df[~words_df.segment.isin(stopwords.stopword)]words_stat = words_df.groupby(by=['segment'])['segment'].agg({"計數":numpy.size})words_stat = words_stat.reset_index().sort_values(by=["計數"],ascending=False)# 設置詞云屬性 color_mask = imread('background.jfif')wordcloud = WordCloud(font_path="simhei.ttf", # 設置字體可以顯示中文 background_color="white", # 背景顏色 max_words=100, # 詞云顯示的最大詞數 mask=color_mask, # 設置背景圖片 max_font_size=100, # 字體最大值 random_state=42, width=1000, height=860, margin=2,# 設置圖片默認的大小,但是如果使用背景圖片的話, # 那么保存的圖片大小將會按照其大小保存,margin為詞語邊緣距離 )# 生成詞云, 可以用generate輸入全部文本,也可以我們計算好詞頻后使用generate_from_frequencies函數 word_frequence = {x[0]:x[1]for x in words_stat.head(100).values}word_frequence_dict = {}for key in word_frequence:word_frequence_dict[key] = word_frequence[key]wordcloud.generate_from_frequencies(word_frequence_dict)# 從背景圖片生成顏色值 image_colors = ImageColorGenerator(color_mask)# 重新上色 wordcloud.recolor(color_func=image_colors)# 保存圖片 wordcloud.to_file('output.png')plt.imshow(wordcloud)plt.axis("off")plt.show()# wordcloud = wordcloud.fit_words(word_frequence_list) # plt.imshow(wordcloud) # wordcloud.generate(words_stat) if __name__ == '__main__':main('北京', 'QT工程師', 2005, 10)


總結

以上是生活随笔為你收集整理的Python爬虫爬取智联招聘(进阶版)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。