job 网站爬取 python 职位信息
题目
在 51job 网站上,爬取 2020 年发布的 Python 开发工程师的职位的薪酬,计算北京地区改职位的平均薪酬。均要求采用多进程,或者多线程的方式完成
功能概述
使用 python 语言实现爬取 51job 网站的 2020 年的“python 开发工程师”的所有岗位信息,分别把每一条岗位信息按照[岗位,公司名称,公司地址,薪资,发布时间]存储到 MySQL 数据库中,实现数据存储和后面的查询检索筛选功能。使用 python 中的多线程库设计多线程爬虫来提高爬取速度。
爬取保存数据完毕后通过执行 Select 语句向数据库中查找相关信息,例如题目中的需求查找北京地区的所有薪资平均。通过计算后输出北京地区 python 开发工程师的平均薪资。
所使用关键 python 库
lxml.etree :解析 HTML 为 HTML DOM 文档
使用 selector.xpath(xpath)根据 xpath 路径获得相应标签的内容
pymysql: 提供 python 连接,使用,修改 MySQL 数据库的函数
threading : python 中提供多线程设计的库
urllib : 根据 url 打开访问页面,读取网页数据
数据库表的设计
功能详细介绍
对于单条岗位信息的分析保存
首先通过浏览器获得每一条信息所在标签的 xpath 路径
然后通过调用 lxml.etree 中的 Element 对象的 getchildren()函数来获得
标签下的每一个子内容,如图中的一个 div element 通过调用 getchildren 可以返回他的 5 个标签,t1-t5,分别对应每一条岗位信息中需要获取的五个内容,之后通过字符串分割 split 的方法将五个内容取出来保存到列表中作为定义的函数的返回值
关键代码:
```c++ def get_one_item(items): # 获得一个信息条目的所有信息 info=[] try: item = items[0].getchildren() except IndexError: print("完毕") exit(0) try: for it in item: content = tostring(it, encoding="utf-8").decode('utf-8') # print(content)
if ('<p class="e73_e1d3_d3d2bce t1' in content): # 获取标题
title = content.split('<a target="_blank" title="')[1]
title = title.split('" href="')[0]
info.append(title)
if ('<span class="tdd_782e_2e9619f t2' in content): # 获取公司名称
company = content.split('<a target="_blank" title="')[1]
company = company.split('" href="')[0]
info.append(company)
if ('<span class="u9f_1473_73b8714 t3' in content): # 获取公司地址
address = content.split('"t3">')[1]
address = address.split('</span>')[0]
info.append(address)
if ('<span class="v83_a44e_4ee44a8 t4' in content): # 获取工资
salary = content.split('"t4">')[1]
salary = salary.split('</span>')[0]
info.append(salary)
if ('<span class="x7b_4b4b_4ba46a4 t5' in content): # 获取发布日期
date = content.split('"t5">')[1]
date = date.split('</span>')[0]
info.append(date)
except IndexError:
info=[]
return info
pass
return info
```
对于一个页面的所有信息的保存
通过网页 HTML 源码的分析可知,每个页面中的信息项的 xpath 路径中只有 div[]中的内容存在差别,分别是从 4 到 53,也就是说一个页面存在 50 条数据。
通过使用 for 循环来对每一条信息的 xpath 分别获得相应的标签内容
关键代码:
```c++
一个页面中的所有信息
def get_page_info(url): req = urllib.request.Request(url) html = urllib.request.urlopen(req).read() # 解析html为HTML DOM文档 selector = etree.HTML(html) # 抓取一项信息 page_info = [] for i in range(4, 54): # 获取所有的信息项目 xpa = '//*[@id="resultList"]/div[' + str(i) + ']' items = selector.xpath(xpa) if(len(get_one_item(items))!=0): page_info.append(get_one_item(items)) # print(get_one_item(items))
return page_info
```
将整理好的信息存入 MySQL 数据库
使用 pymysql 中的函数连接和操作本地 MySQL 数据库
关键代码:
```c++
存入数据库
# 连接MYSQL数据库
db = pymysql.connect(host='127.0.0.1', user='root', password='root', db='jobinfo', port=3306)
print('连接数据库成功!')
conn = db.cursor() # 获取指针以操作数据库
# conn.execute('set names utf8')
for ite in pageInfo:
for i in range(len(ite)):
ite[i] = '"' + ite[i] + '"'
sql = 'insert into `table`(岗位,公司名称,公司地址,薪资,发布日期) values({},{},{},{},{})'.format(ite[0], ite[1], ite[2], ite[3],
ite[4])
conn.execute(sql)
db.commit()
db.close()
```
在 MySQL 数据库中的存储结果部分展示如下:
开启多个线程爬取网站
关键代码:
c++
num=[1]
while num[0]<38:
= threading.Thread(target=run_get(num,'thread_1'))
start()
= threading.Thread(target=run_get(num,'thread_2'))
start()
= threading.Thread(target=run_get(num, 'thread_3'))
start()
= threading.Thread(target=run_get(num, 'thread_4'))
start()
本程序中使用四个线程进行爬取,其中 python 岗位信息一共有 38 个页面,分别对每一页的 url 进行修正,用于不同页面的加载,从而实现自动翻页操作
查询数据库获得北京地区的平均薪资
首先查找数据库中地址信息要使用模糊查找,因为爬取下来的地址信息中,北京包括不同的区,例如西城区,海淀区等等
sql = "SELECT 薪资 FROM
table
WHERE 公司地址 LIKE '北京%'"
在使用 select 语句时,仅查找北京开头的信息,从而实现了模糊查找。
然后将薪资信息进行累加求平均值,对于不同的薪资计算格式分别整理成元/月的单位。
关键代码:
```c++ for dic in data_dict: if("万/月" in dic['薪资']): value=dic['薪资'].split('万')[0] value=value.split('-') a=float(value[0]) 10000 b=float(value[1]) 10000 total+=(a+b)/2 elif("千/月" in dic['薪资']): value = dic['薪资'].split('千')[0] value = value.split('-') a = float(value[0]) * 1000 b = float(value[1]) * 1000 total += (a + b) / 2 elif("万/年" in dic['薪资']): value = dic['薪资'].split('万')[0] value = value.split('-') a = float(value[0]) * 10000/12 b = float(value[1]) * 10000/12 total += (a + b) / 2 elif("元/天" in dic['薪资']): value = dic['薪资'].split('元')[0] a = float(value[0]) * 30 total += a else: value = dic['薪资'].split('元')[0] a = float(value[0]) * 30*24 total += a
```
程序最后的平均薪资输出为:
经分析可知,北京地区 python 开发工程师的平均薪资约是 1.7w/月
参考文献
- 位置服务信息集成与搜索系统的研究与实现(兰州理工大学·张晓峰)
- 基于Actor模型的广域分布式爬虫的设计与实现(北京邮电大学·陈凌鹏)
- 面向人物简介的主题爬虫设计与实现(吉林大学·蒋超)
- 垂直搜索引擎爬虫系统的研究与实现(贵州大学·吴建强)
- 基于Actor模型的广域分布式爬虫的设计与实现(北京邮电大学·陈凌鹏)
- 基于网络爬虫的数据采集系统设计与实现(东北大学·赵彦松)
- 主题网络爬虫的研究和实现(武汉理工大学·林捷)
- 面向主题的爬行搜索策略研究与实现(陕西师范大学·王敏翔)
- 网络爬虫系统的研究与实现(电子科技大学·赵茉莉)
- 基于Web的主题搜索应用技术研究(黑龙江大学·谢冬松)
- 面向校园招聘主题的分布式爬虫系统的设计与实现(大连交通大学·张佳琦)
- 软件更新信息系统的开发研究(南京邮电大学·徐琼)
- 面向校园招聘主题的分布式爬虫系统的设计与实现(大连交通大学·张佳琦)
- 基于网络爬虫的数据采集系统设计与实现(东北大学·赵彦松)
- 基于网络爬虫的计量数据分析系统开发(吉林大学·邹思宇)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:毕设向导 ,原文地址:https://m.bishedaima.com/yuanma/36109.html