一.网络爬虫设计方案:
1.主题网络爬虫名称:51job 招聘网站信息数据采集
2.主题网络爬虫爬取的内容:采集python岗位薪资,职位,城市,学历等信息
3.主题式网络爬虫设计方案概述:进入网站搜索python并勾选对应学历,确定网址url后翻页获取每一页的html代码并解析出对应数据,期间进行数据清洗,将不规范数据从源头去除,然后保存至字典,再利用 xlsxwriter 模块存入excel表格,最后进行数据可视化处理,绘制各城市薪资占比,各学历岗位热度,各学历薪资分布等信息图
二.主题页面的结构特征分析:
1.主题页面结构特征分析:每一条对应的岗位信息都在class='el' 的div标签中,我们可使用xpath解析出每一个div再对每一条岗位进行解析,这样可以避免结构不同所带来的数据不精准现象。
2.页面解析
三:网络爬虫程序设计:
1.数据采集
import requests from lxml import etree from xlsxwriter import Workbook # urls_0*列表存放的网址是通过修改url参数page实现的,循环100次即得到前100页的url,这里我们爬取四种学历对应的所以页数 # 博士学历,06 urls_06 = [] for page in range(1, 5): urls_06.append("https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,{}.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=06&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=".format(page)) "https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=03&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=" "https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=04&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=" # 硕士学历,05 urls_05 = [] for page in range(1, 59): urls_05.append("https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,{}.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=05&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=".format(page)) # 本科学历,04 urls_04 = [] for page in range(1, 407): urls_04.append("https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,{}.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=04&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=".format(page)) # 专科学历,03 urls_03 = [] for page in range(1, 103): urls_03.append("https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,{}.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=03&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=".format(page)) # 定义获取数据的函数 def get_data(tablename): # 声明四种学历,判断传入的tablename是哪种学历,对应取出urls educ = ['专科', '本科', '硕士', '博士'] url_infos = [urls_03, urls_04, urls_05, urls_06] urls = [] # 遍历判断出正确的学历目标url信息 for k, i in enumerate(educ): if tablename == i: urls = url_infos[k] # infos用来存储所有信息 infos = [] # 取出一页的链接逐条爬取 for url in urls: # 打印链接 print(url) # 获取页面源码 con = requests.get(url).content.decode("gbk") # 创建xpath对象解析页面 xp = etree.HTML(con) # 因为在招聘平台上有个别公司没有给出薪资,所以我们不可以直接去所有信息,需要逐条判断 html = xp.xpath("//div[@class='dw_table']//div[@class='el']") # 取出单条信息对应的xpath对象 for h in html: # 解析出岗位名称 title = h.xpath('p/span/a/text()') if title: # 将多余空格字符去除 title = title[0].replace(' ', '') # 取出公司名称 gs_name = h.xpath('span[@class="t2"]/a/text()')[0] # 取出工作地址 work_address = h.xpath('span[@class="t3"]/text()')[0] # 取出薪资 money = h.xpath('span[@class="t4"]/text()') # 判断该岗位是否开出薪资范围,如果有则取出,没有则用暂无提示 if money: money = money[0] else: # money = '暂无' # 如果该公司没有给出明确的薪资范围则不在我们爬取的目标中,跳过此层循环 continue # 将一个公司的对应信息存入infos列表中 infos.append({ '职位': title, '公司名': gs_name, '地址': work_address, '薪资': money }) # 将信息列表infos存入excel表格,表格名称即tablename players = infos ordered_list = ["职位", "公司名", "地址", "薪资"] wb = Workbook("./excels/%s.xlsx" % tablename) ws = wb.add_worksheet("New Sheet") first_row = 0 for header in ordered_list: col = ordered_list.index(header) ws.write(first_row, col, header) row = 1 for player in players: for _key, _value in player.items(): col = ordered_list.index(_key) ws.write(row, col, _value) row += 1 wb.close() # 定义列表存入四种学历 educ = ['专科', '本科', '硕士', '博士'] for v in educ: # 取出一条学历传入get_data函数 get_data(v)
保存成功:
2.数据清洗和处理
为减少代码冗余,我们在采集过程中就引入了数据的处理和清洗
3.数据分析与可视化
(1)地区热度词云图
import io import sys import jieba from matplotlib import pyplot as plt import matplotlib as mpl from wordcloud import WordCloud from xlrd import open_workbook f = '' for filename in ['专科','本科','硕士','博士']: mpl.rcParams['font.sans-serif'] = ['KaiTi'] mpl.rcParams['font.serif'] = ['KaiTi'] # sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') workbook = open_workbook(r'./excels/{}.xlsx'.format(filename)) # 打开xls文件 sheet_name= workbook.sheet_names() # 打印所有sheet名称,是个列表 sheet = workbook.sheet_by_index(0) # 根据sheet索引读取sheet中的所有内容 content = sheet.col_values(2)[0:] # 第3列内容 for i in content: f += i[:2] # 结巴分词,生成字符串,wordcloud无法直接生成正确的中文词云 cut_text = " ".join(jieba.cut(f)) wordcloud = WordCloud( # 设置字体,不然会出现口字乱码,文字的路径是电脑的字体一般路径,可以换成别的 font_path="C:/Windows/Fonts/simfang.ttf", # 设置了背景,宽高 background_color="white", width=2000, height=1200).generate(cut_text) plt.imshow(wordcloud, interpolation="bilinear") plt.axis("off") plt.savefig('地区热度词云图.png')
效果:
(2) 岗位数量折线图示
import io import sys from matplotlib import pyplot as plt import matplotlib as mpl from xlrd import open_workbook nums_list = [] for i in ['专科','本科','硕士','博士']: filename = i mpl.rcParams['font.sans-serif'] = ['KaiTi'] mpl.rcParams['font.serif'] = ['KaiTi'] # sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') workbook = open_workbook(r'./excels/{}.xlsx'.format(filename)) # 打开xls文件 sheet_name= workbook.sheet_names() # 打印所有sheet名称,是个列表 sheet = workbook.sheet_by_index(0) # 根据sheet索引读取sheet中的所有内容 content = sheet.col_values(0)[1:] # 第1列内容 nums_list.append(len(content)) input_values = ['专科','本科','硕士','博士'] squares = nums_list # 生成折现图 plt.plot(input_values, squares, linewidth=2,) # 调用绘制函数,传入输入参数和输出参数 plt.title("python岗位数量分布", fontsize=24) # 指定标题,并设置标题字体大小 plt.xlabel("学历", fontsize=14) # 指定X坐标轴的标签,并设置标签字体大小 plt.ylabel("岗位数量", fontsize=14) # 指定Y坐标轴的标签,并设置标签字体大小 plt.tick_params(axis='both', labelsize=14) # 参数axis值为both,代表要设置横纵的刻度标记,标记大小为14 plt.savefig("./岗位数量折线图示.png") # 打开matplotlib查看器,并保存绘制的图形
(3)各学历对应职位占比
import io import sys from matplotlib import pyplot as plt import matplotlib as mpl from xlrd import open_workbook filename = '专科' # 替换学历名称运行程序即可得到四张图片 mpl.rcParams['font.sans-serif'] = ['KaiTi'] mpl.rcParams['font.serif'] = ['KaiTi'] sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') workbook = open_workbook(r'./excels/{}.xlsx'.format(filename)) # 打开xls文件 sheet_name= workbook.sheet_names() # 打印所有sheet名称,是个列表 sheet = workbook.sheet_by_index(0) # 根据sheet索引读取sheet中的所有内容 content = sheet.col_values(0)[1:] # 第1列内容 new_con = [] for i in content: new_con.append(i.replace('\r','').replace('\n','')) nums = [] temp = {} for m in new_con: # 循环判断薪资是否在nums列表中 if m not in nums: # 不在则添加一个值为该薪资的键 nums.append(m) temp[m] = 0 if m in nums: # 在则将该建对应的值加1 temp[m] = temp[m] + 1 # 利用sorted函数对该字典排序 new_title = sorted(temp.items(), key=lambda item: item[1], reverse=True)[0:6] nums = [] input_values = [] for i in new_title: nums.append(i[1]) input_values.append(i[0]) sum_nums = sum(nums) squares = [x/sum_nums for x in nums] print(input_values) print(squares) # 保证圆形 plt.axes(aspect=1) plt.pie(x=squares, labels=input_values, autopct='%3.1f %%') plt.savefig("./岗位热度图示/{}岗位热度饼状图示.png".format(filename))
(4)各学历薪资状况
import io import sys from matplotlib import pyplot as plt import matplotlib as mpl from xlrd import open_workbook filename = '专科' # 替换学历名称运行程序即可得到四张图片 mpl.rcParams['font.sans-serif'] = ['KaiTi'] mpl.rcParams['font.serif'] = ['KaiTi'] sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') workbook = open_workbook(r'./excels/{}.xlsx'.format(filename)) # 打开xls文件 sheet_name= workbook.sheet_names() # 打印所有sheet名称,是个列表 sheet = workbook.sheet_by_index(0) # 根据sheet索引读取sheet中的所有内容 content = sheet.col_values(3)[0:] # 第4列内容 moneys = [] for i in content: if '月' in i: moneys.append(i[:-2]) nums = [] # num为临时变量,在下方提供判定作用 # money_num用来存储薪资范围最普遍的值 money_num = {} for m in moneys: # 循环判断薪资是否在nums列表中 if m not in nums: # 不在则添加一个值为该薪资的键 nums.append(m) money_num[m] = 0 if m in nums: # 在则将该建对应的值加1 money_num[m] = money_num[m] + 1 # 利用sorted函数对该字典排序 new_money_nums = sorted(money_num.items(), key=lambda item: item[1], reverse=True) x = [] y = [] for i in new_money_nums[0:8]: x.append(i[0]) y.append(i[1]) plt.bar(x, y, align='center') plt.title('python') plt.ylabel('人数') plt.xlabel('薪资') plt.savefig("./薪资范围图示/{}薪资分布柱状图.png".format(filename))
(5)代码汇总
四:结论:
从分析中可知要想得到更好的生活,就要好好学习哈哈哈,更要明白难的知识才会更有含金量,如果不刻苦学习将来可能只是初级运维师,越努力越幸运。
这次项目也让我感受到了python的魅力,获益良多,让我对后期课程更加感兴趣! 以后肯定好好学习, 把以前的不足都补上 !