拉勾网职位需求采集项目
需求分析
知己知彼,方可百战不殆。在学习技术的时候我们往往面临太多选择而不知所措,可能是各个方面都有
涉猎,对某个领域没有深入研究,看似什么都会,真要让你做个什么东西的时候就显得捉肘见襟。如果
我们能从招聘职位所需的技能开始学习,便可练就一身硬功夫,为实战应用中打下良好的基础。
通过python抓取拉钩网的招聘详情,并筛选其中的技能关键词,存储到 excel 中。
项目简介
职位需求页面分析
通过观察可以发现,拉勾网的职位页面详情是由 http://www.lagou.com/jobs/
PositionId.html 组成。
而 PositionId 可以通过分析 Json 的 XHR 获得。而红框里的职位描述内容是我们要抓取的数据。 知道了数据的源头,接下来就按照常规步骤包装 Headers ,提交 FormData 来获取反馈数据。
PositionId 数据采集
注意:
拉勾网反爬虫做的比较严,请求头多添加几个参数才能不被网站识别。
我们找到真正的请求网址,发现返回的是一个 JSON 串,解析这个 JSON 串即可,而且注意是 POST
传值,通过改变 Form Data 中 pn 的值来控制翻页。
XHR : XMLHttpRequest 对象用于和服务器交换数据。
点击页面中的页数,比如第 2 页,我们可以在右边看到一个 POST 请求,这个请求里面包含了真实的
URL( 浏览器上的 URL 并没有职位数据,查看源代码就可以发现这一点)、 POST 请求的请求头
Headers 、 POST 请求提交的表单 Form Data (这里面包含了页面信息 pn 、搜索的职位信息 kd )
真实的URL获取
请求头信息
我们需要构造的请求头Headers信息,如果这里没有构造好的话,容易被网站识别为爬虫,从而拒绝访
问请求。
表单信息
发送POST请求时需要包含的表单信息 Form Data 。
返回的JSON数据发现需要的职位信息在 content –> positionResult –> result 下,其中包含了工作地点、公司
名、职位等信息。 我们只需要保存这个数据就可以了。
至此我们分析完毕网页,下面可以开始爬取过程了。
代码
import pprint
import time
import pandas as pd
import requests
from config import *
from concurrent.futures import ThreadPoolExecutor
import logging
# 灵活配置日志级别,日志格式,输出位置
logging.basicConfig(level=logging.DEBUG, # 日志类型为DEBUG或者比DEBUG级别更高的类型保存在日志文件中;
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='lagou.log',
filemode='w')
def getPositionIDPage(url_start, url_parse, page=1, kd='python'):
"""
获取PositionId列表所在页面, 返回的时json数据;
:param url_start: 图形界面拉勾网职位信息的url地址;为了获取随机的session;
:param url_parse: 真实返回json格式的url地址
:param page: 访问的页数
:param kd: 搜索的关键字
:return: json数据格式的文本信息;
"""
# 构造请求头(headers)
headers = {'User-Agent': ua.random,
'Host': Host,
'Origin': Origin,
'Referer': Referer,
'Connection': Connection,
'Accept': Accept
}
# 构造表单
data = {
'first': False,
'pn': str(page),
'kd': kd
}
try:
# requests库的session对象能够帮我们跨请求保持某些参数,
# 也会在同一个session实例发出的所有请求之间保持cookies。
# 创建一个session对象
session = requests.Session()
# 用session对象发出get请求,设置cookies
session.get(url_start, headers=headers, timeout=3) # 请求首页获取cookies
cookie = session.cookies # 为此次获取的cookies
# 用session对象发出另外一个post请求,获取cookies , 返回响应信息
response = session.post(url=url_parse,
headers=headers,
data=data,
)
time.sleep(1)
# 响应状态码为4xx客户端错误,或者5xx服务器错误响应,来抛出异常:
response.raise_for_status()
response.encoding = response.apparent_encoding
except Exception as e:
logging.error("页面" + url_parse + "爬取失败:", e)
else:
logging.info("页面" + url_parse + "爬取成功" + str(response.status_code))
return response.json()
def analyse_PositionID(html):
"""
根据获取的页面解析每一个招聘页面详情都有一个所属的ID索引
:param html:
:return:
"""
# tag = 'positionId'
positions = html['content']['positionResult']['result']
df = pd.DataFrame(positions)
return df
def task(page):
# 拉勾网页面
url_start = 'https://www.lagou.com/jobs/list_%s' %(keyword)
# 真实的拉勾网url地址
url_parse = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult = false'
# 获取指定页拉勾网的职位信息, 返回的是json反序列化的结果
html = getPositionIDPage(url_start, url_parse, page=page, kd=keyword)
# pprint.pprint(content)
# 解析页面, 返回DataFrame格式的数据;
df = analyse_PositionID(html)
return df
if __name__ == '__main__':
with ThreadPoolExecutor(ThreadCount) as pool:
results = pool.map(task, range(1, pages+1))
total_df = pd.concat(results, axis=0)
total_df.to_csv(csvFileName, index=False,sep=',', header=True )
“”"
数据分析
import pandas as pd
from config import *
import matplotlib.pyplot as plt
import matplotlib
#配置中文字体和修改字体大小
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family'] = 'sans-serif'
matplotlib.rcParams['font.size'] = 10
# 读取csv文件的内容;
df = pd.read_csv(csvFileName)
# 获取数据的前5行;
# print(df.head(5))
# # 获取文件中的某一列数据
# thirdTypes = df['thirdType']
# # 对数据进行分组统计;
# groupTypesCount = thirdTypes.value_counts()
# print(thirdTypes)
# print(groupTypesCount)
def show_second_type():
# 获取职位类别分类并分组统计
secondType_Series = df['secondType'].value_counts()
print(secondType_Series)
# 设置图形的大小;
plt.figure(figsize=(10,5))
# 绘制条形图;bar: 条形图,
secondType_Series.plot.bar()
# # 展示图形
plt.show()
if __name__ == '__main__':
show_second_type()
“”"
配置文件的内容
“”"
from fake_useragent import UserAgent
Host = 'www.lagou.com'
Origin = 'https://www.lagou.com'
Referer = 'https://www.lagou.com/jobs/list_python'
Connection = 'keep-alive'
Accept = 'application/json, text/javascript, */*; q=0.01'
ua = UserAgent(verify_ssl=False)
ThreadCount = 50
pages = 5
csvFileName = 'lagou.csv'
keyword = 'java'