文章目录
需求分析
知己知彼,方可百战不殆。在学习技术的时候我们往往面临太多选择而不知所措,可能是各个方面都有涉猎,对某个领域没有深入研究,看似什么都会,真要让你做个什么东西的时候就显得捉肘见襟。如果我们能从招聘职位所需的技能开始学习,便可练就一身硬功夫,为实战应用中打下良好的基础。通过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 下,其中包含了工作地点、公司名、职位等信息。 我们只需要保存这个数据就可以了。
至此我们分析完毕网页,下面可以开始爬取过程了。
PositionId 页面解析
获取所需的岗位ID,每一个招聘页面详情都有一个所属的ID索引
核心代码
# 获取所有的职位信息;
position = result['content']['positionResult']['result']
# DataFrame是二维数据格式, 便于后续的分析与处理;
df = pd.DataFrame(position)
修改配置文件 config.py : 添加新的配置信息
# 爬取数据的页数
pages = 100
# 存储信息的csv文件位置
csv_filename = 'lagou.csv'
# 多线程开启的线程数;
ThreadCount = 100修改文件 lagou.py :页面解析
def analyse_PositionID(html):
"""
根据获取的页面解析每一个招聘页面详情都有一个所属的ID索引
:param html:
:return:
"""
tag = 'positionId'
positions = html['content']['positionResult']['result']
df = pd.DataFrame(positions)
return df
数据存储:
csv 格式
开启线程池,批量爬取职位信息,并存储于 csv 文件;
修改文件 lagou.py : 封装页面爬取和页面解析的任务;
def task(page):
# 拉勾网页面
url_start = 'https://www.lagou.com/jobs/list_python'
# 真实的拉勾网url地址
url_parse = 'https://www.lagou.com/jobs/positionAjax.json?
needAddtionalResult=false'
# 获取指定页拉勾网的职位信息, 返回的是json反序列化的结果
html = getPositionIDPage(url_start, url_parse, page=page)
# pprint.pprint(content)
# 解析页面, 返回DataFrame格式的数据;
df = analyse_PositionID(html)
return df
修改文件 lagou.py : 将批量爬取的信息存储到 csv 文件中;
def save_as_csv():
"""
将获取的页面解析后的信息通过多线程的方式以csv格式存储到文件
:return:
"""
# 开启线程池
with ThreadPoolExecutor(ThreadCount) as pool:
# map方法中,可迭代对象传入函数是从前到后逐个提取元素, 并将结果依次存储到
results中;
results = pool.map(task, range(1, pages + 1))
# 拼接获取的所有信息, axis=0代表往跨行(down),而axis=1代表跨列(across)
total_df = pd.concat(results, axis=0)
"""
sep: 输出文件的字段分隔符, 默认为逗号;
header: 是否写出列名;
index: 是否写入行名称(索引);
""" total_df.to_csv(csv_filename, sep=',', header=True, index=False)
logging.info("文件%s存储成功" %(csv_filename))
return total_df
if __name__ == '__main__':
save_as_csv()
数据分析
可视化中文显示问题解决
常见字体库下载网址
将下载好的字体库文 simhei.ttf 存在本机 ~/anaconda3/lib/python3.7/site-
packages/matplotlib/mpl-data/fonts/ttf/ 目录中;
获取字体的缓存位置;
print(matplotlib.font_manager.get_cachedir())
shell命令清空缓存
rm -fr /home/kiosk/.cache/matplotlib
常见错误及解决方式
在使用 fake_useragen 的时候出现如下错误:
raise FakeUserAgentError ('Maximum amount of retries reached')
fake_useragent.errors.FakeUserAgentError : Maximum amount of retries reached
解决方法:
from fake_useragent import UserAgent
# 加这个参数后就可以用了, 在发送请求时把验SSL证书关掉, 设置verify为False
ua = UserAgent(verify_ssl=False)
获取页面信息时出现请求频繁问题
{ 'success' : False, 'msg' : '您操作太频繁,请稍后再访问', 'clientIp' : '113.14.1.254'}
解决方法: 使用 seesion 获取平时可以看到的页面信息, 在通过这个session对象获取真实的 url ;
# 创建一个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)
项目代码
配置文件(config.py)
# encoding=utf-8
"""
Date:2019-08-14 10:52
User:LiYu
Email:liyu_5498@163.com
"""
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 =