网页源码解析 - 智联招聘搜索列表
一开始必须要解析智联招聘搜索列表页,从这里更方便实现各种深层级数据抓取。
网页地址是:
http://sou.zhaopin.com/jobs/searchresult.ashx
搜索参数
智联招聘的服务器只接收Get方式,如果用Post方式抓取页面,则不会返回想要的招聘信息,而会得到一堆广告。
下面是我手动测试的一些智联在这个页面Get方式传递的搜索参数,也是目前最常用的(注释掉的不怎么常用):
data_filter = {
'kw' : keyword, # 搜索关键词
'sm' : '0', # 显示方式代码: 列表是'0',详细是'1'。显示不同源码也不同,尽量选列表模式,源码更好解析。
'jl' : '北京', # 搜索城市:'北京',多项用'+'连接(URL编码为%2B)
#'bj' : '', # 职位类别代码:互联网产品/运营管理 的代码为 '160200',多项用'%3B'连接(URL编码的%)
#'in' : '', # 行业代码:多项用';'连接(URL编码为%3B)
'kt' : '0', # 关键词搜索范围:全文'0' | 公司名'1' | 职位名'2'
'isadv' : '0', # 是否高级搜索:快速搜索'0' | 高级搜索'1'
# 'isfilter' : '1', # 是不是筛选器: '0' | '1'
# 'ispts' : '', # 通常为 '1'
#'sj' : '', # 职位子类别代码:
# 'gc' : '5号', # 地铁线路: '5号'
# 'ga' : '立水桥', # 地名或地铁站名: '天通苑南' 、 '小汤山'
# 'sb' : '0', # 排序方式代码:默认排序是'0',相关度排序是'1', 首发日排序是'2'
#'fjt' : '10000', # 职位标签 五险一金'10000' 年底双薪'10001' 绩效奖金'10002' 等等
# 'sf' : '-1', # 月薪底线:'8001' 不限是'-1'
# 'st' : '-1', # 月薪上限:'10000' 不限是'-1'
# 'ct' : '-1', # 公司性质代码
# 'el' : '-1', # 学历代码
# 'we' : '-1', # 工作经验代码
# 'et' : '-1', # 职位类型代码:兼职'1' 全职'2' 实习'4'
# 'pd' : '-1', # 发布时间(天数):一周是'7',一个月是'30',不限是'-1'
'p' : page, # 页码,超出总页码时,则会显示最后一页
#'gr' : '', #
# 're' : '2015', # 这个限制了搜素数量,但是其实也不是按年份搜索
'sg' : guid, # 即全网唯一标示符——GUID
#'' : '' #
}
它在python中的用法,就是通过urllib.urlencode()来转成URL参数格式,并提交。
网页源码解析 - “列表模式”
如果解析“列表模式”的智联招聘网页,需要在Get参数里面的sm设为0
。
里面唯一需要的就是中间的结果列表部分,
即id为'newlist_list_content_table'的DIV用,源码如下:
<div class="newlist_list_content" id="newlist_list_content_table">
<table width="853" class="newlist" cellpadding="0" cellspacing="0">
一条招聘信息
</table>
<table cellpadding="0" cellspacing="0" width="853" class="newlist">
一条招聘信息
</table>
</div>
其中会循环输出class为newlist
的Table表格
即一条一条的招聘信息。
每一条招聘信息的源码如下:
<table cellpadding="0" cellspacing="0" width="853" class="newlist">
<tr>
<td class="zwmc" style="width: 250px;">
<input type="checkbox" name="vacancyid" value="CC575878820J90250640000_530_1_03_201__1_" onclick="zlapply.uncheckAll('allvacancyid')" />
<div style="width: 224px;*width: 218px; _width:200px; float: left">
<a style="font-weight: bold" par="ssidkey=y&ss=201&ff=03" href="http://jobs.zhaopin.com/575878820250640.htm" target="_blank">会计(<b>数据</b>)</a>
</div>
</td>
<td style="width: 60px;" class="fk_lv"><span>87%</span></td>
<td class="gsmc"><a href="http://company.zhaopin.com/CC575878820.htm" target="_blank">中海软银投资管理有限公司</a></td>
<td class="zwyx">面议</td>
<td class="gzdd">北京</td>
<td class="gxsj"><span>12-10</span><a class="newlist_list_xlbtn" href="javascript:;"></a></td>
</tr>
<tr style="display: none" class="newlist_tr_detail">
<td width="833px" style="line-height: 0;" colspan="6">
<div class="newlist_detail">
<div class="clearfix">
<ul>
<li class="newlist_deatil_two"><span>地点:北京</span><span>公司性质:民营</span><span>公司规模:100-499人</span><span>经验:5-10年</span><span>学历:大专</span><li class="newlist_deatil_last"> 岗位职责: 1. 熟练使用excel<b>数据</b>统计功能; 2.核对第三方支付平台及技术后台<b>数据</b>并找出差异; 3. 完成与<b>数据</b>部工作衔接,做好<b>数据</b>台账的统计工作; 4.根据资产端和资金端<b>数据</b>完成日汇总报表; 5. 领导交办的其他工作。...</li></li>
</ul>
<dl>
<dt>
<a href="javascript:void(0)" onclick="return zlapply.searchjob.ajaxApplyBrig1('CC575878820J90250640000_530','ssi','_1_03_201__2_')">
<img src="/assets/images/newlist_sqimg_03.jpg" />
</a>
</dt>
<dd><a href="javascript:zlapply.searchjob.saveOne('CC575878820J90250640000_530')"><img src="/assets/images/newlist_scimg_06.jpg" /></a></dd>
</dl>
</div>
</div>
</tr>
</table>
在“列表”模式中,每一条记录采用了Table格式,第一个TR是简述信息,第二个TR是扩展信息。简述信息中,每个信息都有固定Class属性,而且是非空信息,是肯定能获取到的。而扩展信息中,规则性不强,只能用“公司性质:xx”这样的正则表达式来匹配或是用tag的嵌套层级和顺序来定位,成功率和稳定性都不高。
总结一下,这里的主要定位方式为:
职位名称:
class = "zwmc"
反馈率 :
class = "fk_lv"
公司名称:
class = "gsmc"
职位月薪:
class = "zwyx"
或<span>职位月薪:xx</span>
工作地点:
class = "gzdd"
或<span>地点:xx</span>
更新时间:
class = "gxsj"
或<li><p>12-10</p></li>
公司性质:
<span>公司性质:xx</span>
公司规模:
<span>公司规模:xx</span>
学历要求:
<span>学历:xx</span>
岗位职责:
<li>岗位职责:xx</li>
其实还有tag的嵌套层级和顺序,可以用来定位信息。但是我不想这么做,因为这个太不稳定了,而且大大的增加了代码的长度,如果不存在信息还会导致报错。相比而言,用中文的人能理解的语言来进行正则匹配,更有成功率,且更容易操作。
网页源码解析 - “详细模式”
如果解析“详细模式”的智联招聘网页,需要在Get参数里面的sm设为1
。
里面唯一需要的就是中间的结果列表部分,
即id为'newlist_list_content_table'的DIV用,源码如下:
<div class="newlist_list_content" id="newlist_list_content_table">
<div class="newlist_detail newlist">一条招聘信息</div>
<div class="newlist_detail newlist">一条招聘信息</div>
</div>
其中会循环输出class为newlist_detail newlist
的子DIV层
即一条一条的招聘信息。
每一条招聘信息的源码如下:
<div class="newlist_detail newlist">
<div class="clearfix">
<ul>
<li class="newlist_deatil_first clearfix zwmc"><input type="checkbox" name="vacancyid" value="CC255550019J90256441000_530_1_03_201__1_" onclick=" zlapply.uncheckAll('allvacancyid') " /><div style="width:300px;float:left">
<a style="font-weight: bold" par="ssidkey=y&ss=201&ff=03" href="http://jobs.zhaopin.com/255550019256441.htm" target="_blank">
行政后勤经理</a></div></li>
<li class="newlist_deatil_three gsmc">
<a href="http://special.zhaopin.com/bj/2011/lsw05120476/enter.html" target="_blank">
乐视网信息技术(北京)股份有限公司</a></li>
<li class="newlist_deatil_two">
<span>地点:北京</span>
<span>公司性质:上市公司</span>
<span>公司规模:1000-9999人</span>
<span>学历:本科</span>
<li class="newlist_deatil_last">
岗位职责: 1、负责对日常行政后勤工作(包括名片、加班餐、办公用品、员工离入职、印章、会议室的相关事宜)进行全面的监督控制,发现问题及时予以规范,协助上级领导应对处理突发事件; 2、进行行政后勤各项费用预算,严格管控各项费用的使用情况,节省公司成本,实现效益的最大化; 3、部门员工的招聘与培养和...</li></li>
</ul>
<dl>
<p>12-07</p>
<dt>
<a href="javascript:void(0)" onclick="return zlapply.searchjob.ajaxApplyBrig1('CC255550019J90256441000_530', 'ssi' , '_1_03_201__2_' ) ">
<img src="/assets/images/newlist_sqimg_03.jpg" />
</a>
</dt>
<dd><a href="javascript:zlapply.searchjob.saveOne('CC255550019J90256441000_530')"><img src="/assets/images/newlist_scimg_06.jpg" /></a></dd>
</dl>
</div>
</div>
在源码上,虽然“详细模式”的解析和“列表模式”有很大的不同,几个信息的抓取方式不一样,但是却可以共用。如有的是按照class名,有的是按照tag名等。但是这不影响两种模式放在一起解析——为每一个信息元素如“月薪”、“公司名称”等,设置多种搜索方式。在写代码时,只要分别检索多种方式就可以获得数据。具体参考抓取代码的实现。
获取搜索结果数量
虽然每页只能显示40条信息,但是在页面上方还是会显示一共有多少条搜索结果。如“”
代码如下:
<span class="search_yx_tj">
共<em>2025</em>个职位满足条件
</span>
获取GUID——全局唯一标识符
虽然没有研究过GUID,但是我看到智联招聘的网页会在URL中显示的调用,参数名为sg
。
不知道它对爬虫有什么影响。不过我还是尝试着获取了一下,很简单直接用id搜索input标签的value就行。网页源码如下:
<input type="hidden" id="guid" value="6857d119ab0147938da7b78b4c18f857" />
获取当前页码及下一页的链接地址
智联招聘这个页面最逗的是,如果当前信息只有4页,那么及时url参数中页码指定100,它仍然不会自动跳转。所以从url或者.geturl()
来判断当前真实页码也就成了不对了。
不过好在一点,这个页面下方的页码控制栏
中可以清楚的看到当前页码是多少,所以就从这里入手。这部分网页源码如下:
<div class="pagesDown" style="_width:570px">
<ul>
<li><a class="pre-page nopress">上一页</a></li><li><a href="#" class="current" >1</a></li>
<li><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=2">2</a></li>
<li><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=3">3</a></li>
<li><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=4">4</a></li>
<li><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=5">5</a></li>
<li><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=6">6</a></li>
<li><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=7">7</a></li>
<li><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=8">8</a></li>
<li><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=9" class="pagesmore">...</a></li>
<li class="pagesDown-pos"><a href="http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=助理&sm=0&ga=立水桥&gc=5号线&gr=2&isfilter=1&fl=530&isadv=0&sg=c67ae20d31954238959da7915552c240&p=2" class="next-page">下一页</a>
<li class="nextpagego-box"><input type="hidden" id="guid" value="c67ae20d31954238959da7915552c240" />到 页<input type="text" class="pagesnum" name="goto" id="goto" value="1" onkeyup="zlapply.searchjob.fnCheckInt(this,event)" onchange="zlapply.searchjob.fnCheckInt(this,event)" onkeypress="zlapply.searchjob.enter2Page(this,event,51)" /><button type="button" class="nextpagego-btn" name="go" onclick="zlapply.searchjob.gotoPage(this.form.goto.value,51,'','c67ae20d31954238959da7915552c240')"></button></li>
<li class="clearfix"></li>
</ul>
</div>
从中可以看到,当前页码的定位极其方便,只要从class="pagesDown"
的div中找到class="current"
的a链接就得到了。
同理,下一页的链接可以找class="next-page"
的a标签获取href值。