网页源码解析 - 智联招聘搜索列表

一开始必须要解析智联招聘搜索列表页,从这里更方便实现各种深层级数据抓取。
网页地址是:
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为newlistTable表格
即一条一条的招聘信息。
每一条招聘信息的源码如下:

<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值。


SolomonXie
1.3k 声望480 粉丝

Those who exalt themselves will be humbled, and those who humble themselves will be exalted.