Python爬虫实战之三-基于Scrapy框架抓取Boss直聘的招聘信息
---------------readme---------------
简介:本人产品汪一枚,Python自学数月,对于小白,本文会是一篇比较容易上手的经验贴。当然毕竟是新手,欢迎大牛拍砖、狂喷~
致谢:
爬取Boss官网(www.zhipin.com)期间,若对Boss造成或小或大的影响,本人深感歉意。本文只为获取招聘信息和交流学习,并无恶意,再次鸣谢。
---------------正文分隔符---------------
开发环境
一、兵马未动,粮草先行
(1)、安装Scrapy
使用Mac自带终端安装,使用pip辅助安装。
在bash中输入命令:pip3installscrapy
如果pip3安装没有问题,安装scrapy理论上应该很顺利,因为坑都在pip3的安装过程里填完了...
ps:一个scrapy包里面竟然有如此之多的包,也难称作scarpy框架...
(2)、创建项目
安装完成Scrapy的安装,可以使用命令行创建新项目。
输入命令行:scrapystartprojectwww_zhipin_com
ps:我是参考经验贴中的教程创建的项目名称,项目的名称(www_zhipin_com)可按需求自定义。
创建项目完成后,在python3中打开该项目。
打开流程如下:python3->file->open,选择刚创建的项目。
导入项目后,可以看到在执行创建项目命令后,Scrapy会为我们自动创建spider所需的标准文件目录。
ps:开始一点点的体会到scrapy的强大,另外,也验证scrapy的安装已经没有问题了。
创建的项目,其中的文件作用如下:
看下入门教程给的解释,无力吐槽...
(3)、创建spider代码文件
在spiders的PythonPackage文件中创建本次的爬取的PythonFile文件。
文件名:zhipin_spider(ps:这个命名可随意设置,你高兴就好,给你一个机智的眼神...)
二、备马囤粮,攻城略地
(1)、大战在即,先谋而后动
以产品经理的为例,以列表第一为参考,Boss的页面布局图如下:
ps:VIPKID给的薪水很诱人啊...咳、咳...打完这一仗,回家可以整理下简历了...
我们依次从:微观->中观->宏观,三个视角分析下Boss的html页面布局。
1)、微观视角
单条招聘信息的Html布局如下:
页面的主要信息如下(按出场顺序):
如此看来,我们的item相应的要素信息基本有了,详情见Item模块。
2)、中观视角
单页招聘信息的Html布局如下:
一个ul中包含30个li,对应页面的30个招聘信息,工工整整的码着,就像等待被翻牌一样...呃,脑中瞬间闪过雍正爷和乾隆爷的伟岸形象...
ps:看着这JS代码,想起了今年前半年自学JS的那段时光,一晃18年已过大半。
3)、宏观视角
单此检索查询,Boss只提供了10页的检索信息,这也就意味着,单次一个关键词检索,我们只能获取到300个职位。
此处有个问题需要思考下:针对这样的宏观视角,我们的spider策略要如何制定?
我是这样思考的,贴出来大家可以讨论下:
首先,从效率的角度,如果关键词限定的范围越宽泛,则单次检索到所需的信息越少,例如,我需要查询的是产品经理及以上职位招聘信息,如果仅输入”产品“这个关键词,检索结果就会充斥着产品专员、产品运营等无效信息,所以从效率来讲,检索精度需越精准越好;
其次,从边界的角度,如果定位精准,就会出现边界限制的困境,很难通过我输入的精准关键词查询到关联的招聘职位,搜索范围就只限于当前的职级限制。
所以,基于此,本次作战的方针如下:单个关键词精准定位,不同领域多职级的轮循。
ps:方针确定,战略布局也就清晰了...
(2)、战略目标(Item)
既然要攻城略地,就需要确认下,哪些城哪片地可以入我等法眼。
在此,就不得不提一下产品的职业病:用户视角。
如果我是应聘者,我会需要以怎样的信息去快速筛选有意向的职位呢?答:首先是职位、薪水、哪个公司,其次是地址、要求、公司规模等。
其实,在微观的Html中已经标明Boss页面中展示的招聘信息,这些信息也是我们本次行动需要斩获的首要目标。
所以,items.py中的要素信息配置如下:
(3)、战略实施
指导方针和战略目标已经搞定,此时便可剑指城池,策马扬鞭,走起~
按照教程我们可以定义Spider中的要素信息如下:
简单说明下,name、allowed_domains和start_urls的定义,这个官网教程已经给解释和参考规则,此处不再赘述。
scity是用来设定需检索的城市的列表,‘c101010100/h_101010100’为Boss链接中的地址参数,代表:北京;
positions是用来定义需检索的职位信息列表,后续可以添加多个职位信息,可针对作战方针进行有针对的spider信息;
curPage、curScityIndex和curPositionIndex三个参数,分别用来标记页面、城市和岗位的当前spider情况,后续parse函数中用到。
headers,模拟浏览器访问,该部分信息的获取方式如下:
2)、start_requests(self)的方法介绍
教程中有三点需要注意:
由此可见,我们单独使用该方法可能没有办法满足要求,一会打一枪试一下就明白了。
3)、Boss页面的链接结构
url的结构分为两部分:招聘信息列表页和招聘详情页
①招聘信息列表页
地区:当前默认北京;
内容:待输入项,此处为了更大范围能进行职位的爬取,所以此处输入:‘产品’,可以筛选出经理、高级经理、总监的全部职称的招聘信息
职位类型:全部为空
公司行业:全部为空
“query=”查询的内容,“scity=”城市,后两个检索条件中的后两个,为空可忽略
对比后,与第一页的链接相差较大,尝试使用第二页面的样式模拟第一页面的请求。
可以正常打开第一页面,展示信息与之前的官网链接相同。
所以,第一页和第二页,以及后续的页面,均可以使用相同的url模版来模拟查询招聘信息。
另外,如果需要查询其他地区的招聘信息,则需要变更地区码。
综上所述:
请求招聘信息列表的url公共模版如下:
②招聘详情页
招聘的详细信息,主要存在详情页面展示,例如,职位描述、任职要求、公司简介等信息。
另为,cea321961162ff3e1Xd539W-GVE~,想一个ID的标示,打开Html源码确认一下。
这个ID在Html中定义为data-jid,所以我们可以将详情页的url使用如下规则进行拼装。
请求招聘详情页的url公共模版如下:
ps:jid为我们在item.py中定义的要素值,爬取该参数,等后期我们可以有针对性的了解单个有意向的招聘职位时,再进行招聘详情信息的爬取。
4)、重写start_requests(self)方法
根据招聘信息列表的url规则,我们可以对start_requests方法进行重写。
我们直接将参数url的配置方法写在start_requests()中,因其必须返回一个可迭代Itearable对应,所以参考官网教程使用列表(list)的方式'[]',将返回内容转换成可迭代对象。
理想总是美好的,但是现实确实残酷的,因为此处有坑,所以我们跳过后续的介绍(parse(self,response)代码见上文的zhipin_spider.py),我们先放一枪整体运行试一下...
运行结果:第一页可以在正常爬取,但是到第二页就报错。
报错报文如下:
所以借鉴参考例子的方式,利用另外一个函数专门来拼装url,将拼装后的url返回至start_requests(),同时使用列表list将返回值包装成可迭代对象,并发起第一次的Request请求。
同时在url_link(self)的callback回调parse,再parse()的callback回调url_link(),实现循环请求我们陆续拼装的url的页面,并爬取页面信息。
调整后的代码如下:
调整完,再执行时,则没有再报该问题。start_requersts(self)重写完成。
5)、定义parse(self,response)函数
有几处地方进行了数据的特殊处理,分别介绍下:
①salary的数据处理
页面中的salary的是Xk-Xk的形式,但是基于个人定制化的需求,将薪水拆分出:high、low、avg三个档位,拆分出来就可以针对薪水进行规则设置。
代码中对low和high的薪水分别进行判断,如果low低于20k,或者high低于25k则直接跳出for循环,继续寻找下个招聘信息,如果符合条件,则将招聘信息按照item设定,同时输出至指定路径。
ps:想想自己的可怜的薪水,说多了都是泪啊...
③轮循规则
我是按照城市优先、职位次之、页面再次之的顺序轮训。
这样设定,是基于这样的考虑:是按照变换的难易程度来设定嵌套层级。
爬取招聘信息,首先会考虑城市的因素,一般情况下,是会不会轻易更换所在城市,除非一些特殊情况;另外,我们也会尝试去爬取互联网相对发达的城市,可以对比下不同城市的就业情况。另外,在相同城市,会爬取每个职位的10页检索信息,因为Boss一次检索只会返回10页的招聘信息。
总之,anyway...你可以尝试相同职位的不同城市的轮循规则,爬取的数据应该是相同的。
④睡眠很重要
(4)、好戏,开整
但是在执行语句前还又一些小事情需要搞定
1)、设置UTF-8编码
为了让爬取到信息以utf-8的形式保存,需要添加一个设置。
在setting.py中添加(ps:在代码执行中也可以添加)
FEED_EXPORT_ENCODING='utf-8'2)、修改async关键字
在首次执行scrapycrawlzhipin-oitem.json时,程序报错,报文如下:
错误原因:SyntaxError:invalidsyntax
然后寻找相应的文件夹,路径如下:
MacintoshHD->资源库->Frameworks->Python.framework->Versions->3.7->lib->python3.7->site-packages->twisted->conch->manhole.py
使用安装python3时带的IDLE打开manhole.py文件,按照参考方案中修改async关键字。修改完,command+s保存即可。
万事具备,开整~
在bash中输入:cdwww_zhipin_com,然后回车,使命令切到zhipin的项目下
输入:scrapycrawlboss-oitem.json,然后回车
然后看着程序开始biubiu的执行,一阵舒爽....
执行的截图如下:
该命令会在程序执行完成后,在项目中生成一个对应的item.json文件。
同时,该文件也可以在python3中进行查看。
三、打扫战场
上文只是按照入门教程中提到的最简单的方式保存数据,只是保存到本地的json文件中,保存的数据格式如下:
因按照好几个教程尝试将数据保存只MongoDB中都未能成功,所以只好作罢。
如有大神不吝赐教,还望留言联系,不胜感激~
四、不足
但仍有一些不足,有待日后提升:
五、后记
查看招聘网站的种种不错的职位和待遇,真有一种跃跃欲试的冲动,找机会试试吧,希望能有能不错的机会...