58招聘数据爬取准备: 源码分析

通过各种点击观察,发现58同城的URL构造挺特殊的。
根据互联网协议和规则,一般查询参数都直接在cgi后加参数,如cgi?key=abc&page=1这样的。
但是58喜欢赶潮,除了关键词key之外,一些重要的查询参数(职业、行业、页码等)都在URL的目录中构造,而不是作为参数。这个技术我不太懂-_-!,大概是服务器对URL进行分析再获取参数吧,这个不重要。
(注:我是用python开发,刚入门,目前正在用BeautifulSoup扩展,所以经常提到一些相关术语。另外,定位方法我建议采用CSS选择器,语法是通用的。)

招聘搜索页源码分析

下面是我将几乎全部搜索条件都加上的全链接:
*http://bj.58.com/haidian/tech/pve_5363_244_pve_5754_1476_pve_5356_6_pve_5357_6/?key=%E6%95%B0%E6%8D%AE&minxinzi=3000_4999&postdate=20151209_20151216&param6693=8&PGTID=0d303655-0047-792b-50b1-e40ba04c7e85&ClickID=1 *
好的,根据这个链接,以及各种尝试出来的判断,URL的结论如下:

  • 第一部分:子域名。bj.58.com,其中bj作为城市范围的“参数值”。值得一提的是,58同城没有省级分区,全都是针对某个城市。
  • 第二部分:目录参数。以下按目录固定顺序排列:
    1. /haidian/即海淀区,代表了地区或地点“参数值”,还可以是/wudaokou/五道口、/beijingdaxue/北京大学等,还可以是/beijingzhoubian/北京周边,都是区域那一栏所有选项的中文全拼。如果是现实全北京的数据的话,这个目录参数是被省略的的
    2. /tech/即职位类别为"计算机/互联网"类。这一部分有点意思,如果改成/job/就会不限分类,显示所有结果;如果改成/chengxuyuan/则会显示"程序员"的子职业分类。也就是说,58不区分各种职业的层级关系,也不考虑多选——要么全选要么单选。
    3. pve_5363_244_pve_5754_1476_pve_5356_6_pve_5357_6 这个是看起来最复杂的,但是稍微留意下也好理解,其实是——“更多”栏的筛选项,一般有四种参数在这里显示,每种之间用下划线连接,如果没有选择的话这里就不显示其值。其中pve_$$$$_??是固定格式,$$$$是4位数字代表参数名,后面的??是1~4位是不固定的数字代表参数值。
      • pve_5363:公司行业代号。后面的244是“计算机/互联网行业”。合在一起代表“公司行业为计算机及互联网行业”。
      • pve_5754:公司性质代号。后面的1476代表“私营”企业。
      • pve_5356:学历要求代号。后面的6代表“本科”。
      • pve_5357:经验要求代号。后面的6代表“3年-5年”。
  • 第三部分:查询参数。这里就没有固定顺序了。
    • params6693:福利待遇。如果值是1,代表五险一金;6代表周末双休。不可多选!
    • minixinzi:薪资范围。如0_9993000_4999等。

页码:

页码超出搜索结果的总页码时,会显示省略号。
但是结果再多,也只能显示到70页,和智联招聘差不多(到90页)。

包含招聘结果的大框架

页面唯一重要的列表信息,都包括在了这个框架中:

<div id="infolist" class="tablist cleft" tongji_id="ZP_job_list_div_items">
    <dl logr="p_1_33416242837515_24319259084094_0_1_ses^composite^0" _pos="1" sortid="503338211" class="">一条招聘信息</dl>
</div>

框架定位关键是<div>id="infolist",而结果列表中每一条的定位关键为<dl>标签包含logr属性,且规律为logr="p_?_????_ses^composite??"

逐行结果的代码解析

每一条信息的源码如下(量比较大):

<dl logr='p_1_33416242837515_24319259084094_0_1_ses^composite^0' _pos="1"  sortid='503338211'>
    <dd class="w46">
        <i infoid='24319259084094'></i>
        <input type="hidden" uid='33416242837515_0_0' name="uid"/>
    </dd>
    <dt>
        <a href='http://bj.58.com/chaoshishangye/24319259084094x.shtml' urlparams='psid=164836665190074319829635832&entinfo=24319259084094_0'  target="_blank" class="t"  _t='common'>数据处理员</a>
        <span class="hoverinfobox" style="display: none;">
         <div id="arrow">
            <em></em>
            <span></span>
        </div>
        <div id="tipsbox" class="tipsbox">
            <div class="xboxcontent" class="tipsbox">
                <div class="titbar"><h2>山东正元数字城市建设有限公司麻城项目</h2></div>
                <ul class="zhanshi clearfix">
                    <li class="mar30">
                        <span>招聘职位:</span>全职招聘
                    </li>
                    <li>
                        <span>招聘人数:</span>若干                </li>
                    <li class="mar30"> 
                        <span>工作经验:</span>不限                </li>
                    <li>
                        <span>学历要求:</span>不限
                    </li>
                    <!-- 
                    <li class="mar30">
                        <span>工作地点:</span>北京
                     </li> -->
                     <li class="mar30">
                        <span>转正工资:</span>1000-2000元
                     </li>
                </ul>
                <p>
                    有积极的态度和人际关系,能吃苦耐劳,文化水平高中以上。
                </p>
            </div>
        </div>
    </span>
    <span tag="bbbindcpc" url='http://bj.58.com/chaoshishangye/24319259084094x.shtml' name="zaixian_33416242837515"></span>
    </dt>
    <dd class="w271">
        <a href='http://qy.58.com/33416242837515/' urlparams='psid=164836665190074319829635832&entinfo=24319259084094_0' target="_blank" class="fl" title="山东正元数字城市建设有限公司麻城项目">山东正元数字城市建设有限公司麻...</a>
    </dd>
    <dd class="w96">  北京   </dd>
    <dd class="w68">   12-13    </dd>
</dl>

其中,一条信息的确认方式有3中:

  • dl [logr]dl [sortid]dl [_pos],合并定位
  • input [name="uid"]
  • div class="xboxcontent"div class="tipsbox"合并定位

获取每条招聘信息的基本内容

  1. 企业ID:定位在<i infoid='24319259084094'></i>
  • uid:定位在<input type="hidden" uid='33416242837515_0_0' name="uid"/>
  • 职位名称及职位详情页URL:
<a href='http://bj.58.com/chaoshishangye/24319259084094x.shtml' urlparams='psid=164836665190074319829635832&entinfo=24319259084094_0'  target="_blank" class="t"  _t='common'>数据处理员</a>` 

需要注意的是,详情url尽量结合hrefurlparams参数一起构造,不过不放在一起也无所谓。

  • 企业名称:定位在<div class="titbar"><h2>山东正元数字城市建设有限公司麻城项目</h2></div>
  • 招聘职位:查找语法是-> ul[class*=zhanshi] li nth-of-type(1) 或者不用nth-of-type()语法,而是按文本匹配。
  • 招聘人数:查找语法是-> ul[class*=zhanshi] li nth-of-type(2) 或者不用nth-of-type()语法,而是按文本匹配。
  • 工作经验:查找语法是-> ul[class*=zhanshi] li nth-of-type(3) 或者不用nth-of-type()语法,而是按文本匹配。
  • 学历要求:查找语法是-> ul[class*=zhanshi] li nth-of-type(4) 或者不用nth-of-type()语法,而是按文本匹配。
  • 转正工资:查找语法是-> ul[class*=zhanshi] li nth-of-type(5) 或者不用nth-of-type()语法,而是按文本匹配。
  • 职位描述:查找语法是-> ul[class*=zhanshi] + p
  • 企业名称及链接:定位在以下代码中。注意企业名称才用title属性中的,而不是被阉割的文本处。
<dd class="w271"> <a href='http://qy.58.com/33416242837515/' urlparams='psid=164836665190074319829635832&entinfo=24319259084094_0' target="_blank" class="fl" title="xxxx有限公司xx项目">xxxx有限公司...</a></dd>`
  • 工作地点:<dd class="w96"> 北京 </dd>
  • 发布日期:<dd class="w68"> 12-13 </dd>

判断是否为推广信息

如果一行信息内包括这条,那么就是推广信息:

<a class="tuiguang" title="58同城建议您优选选择精准推广" rel="nofollow" target="_blank" href="http://e.58.com/zhaopin/jingzhun.html#go">精准</a>

通过<a>标签的class="tuiguang"来定位。
如果是正常消息,则没有这个链接,且只显示文本的“今天”或者是“12-12”这种具体日期。

获取当前页码及下一页链接

这一步其实是非常重要的!直接关系到是否抓瞎。
首先,58的设置是这样的:
58最多只显示70页信息,每页45条。强行打开70页以上的页面,或者超过当前结果的总页数,都会显示新信息较少,我们为您推荐以下相关信息:
我们先来看源码,然后再处理。

<div class="pagerout">
    <div class="pager" tongji_id="ZP_job_list_div_next">
        <a class="prv" href="/job/pn7/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0"> 
            <span>上一页</span ></a> 
        <a href="/job/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>1</span></a>
        <a href="/job/pn2/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>2</span></a>
        <a href="/job/pn3/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>3</span></a>
                ...
        <a href="/job/pn4/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>4</span></a>
        <a href="/job/pn5/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>5</span></a>
        <a href="/job/pn6/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>6</span></a>
        <a href="/job/pn7/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>7</span></a>
            <strong><span>8</span></strong>
        <a href="/job/pn9/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>9</span></a>
        <a href="/job/pn10/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>10</span></a>
        <a href="/job/pn11/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>11</span></a>
        <a href="/job/pn12/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>12</span></a>
        <a class="next" href="/job/pn9/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0">
            <span>下一页</span></a>
        <a href="/job/?key=%E6%95%B0%E6%8D%AE&cmcskey=%E6%95%B0%E6%8D%AE&final=1&specialtype=gls&canclequery=isbiz%3D0" class="recently">
            <span>最新信息</span></a>
    </div>
</div>

从上面我们可以这样得到些信息:

  1. 上一页链接:div[class="pagerout"] a[class="prv"],获取其href属性值就好了。如果没有,表示正在第一页。
  • 下一页链接:div[class="pagerout"] a[class="next"],获取其href属性值就好了。如果没有,表示正在最后一页。
  • 当前页码:div[class="pagerout"] div[class="pager"] strong,当前页是不带链接的,所以要这样获取。

判断搜索结果是否读完

通过测试发现,根据结果数量的不同,除了正常外汇产生以下结果:

  1. 显示新信息较少,我们为您推荐以下相关信息:一般是因为超过了应有的页码了。这样的信息通过源码找到<dt class="shortMsg">新信息较少,我们为您推荐以下相关信息:</dt>就可以了。
  2. 显示很抱歉,没有找到符合已选条件的信息。\n建议您:,这是因为搜索条件太苛刻没有符合条件的。这样的,通过源码找到:
<i class="ico report"></i><p>很抱歉,没有找到符合已选条件的信息。<br />建议您:</p>

招聘详细页源码分析

这个页面比较简单,除了企业联系方式是动态加载的图片外都比较好定位抓取。不过联系方式也对我没什么太大用就不费那功夫了。

精简招聘信息

是被包含在头文件中用来给搜索引擎搜索用的,所以是精华中的精华哈哈。如下:

<meta name="description" content="[最新招聘信息]诚聘诚聘数据分析师5000+1人,工作地点位于北京海淀中关村,公司规模100-499人,薪资待遇5000-8000元,工作经验1-2年,学历要求大专,招聘岗位职责: 建立公司数据分析的系统,组织数据分析报表的整合和规范、优化; 建立公司数据管理、查询的各项规章制度; 建立公司每日、周、月、季、年度数据分析报表模板; 研究数据分析的方法,做到报表制作, 100)" />

只要通过<meta name="description"定位,获取其content属性值`就好了。

获取招聘基本信息

所有的信息都包含在了<div class="wb-main">...</div>框架中。能够找到的信息如下:

  1. 职位名称:
  • 更新时间:
  • 浏览人数和投递人数:这个略过,没什么用。
  • 企业名称及链接:都在<a class="companyName" >,直接获取href就行了。
  • 营业执照是否已经过验证:<div class="vip-yan fl"><span title="营业执照已验证" class="licIcon"></span>营业执照已认证</div>。找到<div class="vip-yan fl">就好了。
  • 所在行业、企业性质、企业规模和登记时间都在这里了:
<div class="compMsg clearfix">
    <ul>
        <li>
            <span>行业:</span>
            <a href="http://qy.58.com/bj_264/" target="_blank" >广告/创意</a>
        </li>
        <li>
            <span>性质: </span>私营
        </li>
        <li class="scale">
            <span>规模: </span>100-499人
        </li>
        <li class="joinday" style="display: none;">
            <span>入驻时长:</span>174天
        </li>
    </ul>
</div>

写累了,直接上BeautifulSoup格式的css选择器的查找语法,分别为:
所在行业 =div[class*=compMsg] ul li a[href]找到,
企业性质 = div[class*=compMsg] ul li nth-of-type(2),
企业规模 = div[class*=compMsg] ul li nth-of-type(3)或者li[class="scale"],
入驻时间 = div[class*=compMsg] ul li nth-of-type(4)li[class="joinday"]

获取联系信息

都包含在这个div中:

<div class="contact mt25" id="lianxi" tongji_id="ZP_job_detail_div_contact">...</div>

然后可以找到这些信息:

  1. 联系人:<span class="conTip">王经理 <span>(联系我时请说明是在58同城上看到的)</span></span>,定位方法:div[class="conTip"]
  • 工作地点:源码有点长,定位方法:只能用文字匹配了,找到<dt>工作地址:</dt><span class="area">这2个标签,它们
    中间的标签就是地址。
  • 卫星定位:其实也不用费劲,直接找到a[class="map"],获取其href然后用增则表达式匹配2个116.337795这种数字,就得到精确坐标了。源码如下:
<a class="map" href="javascript:setbg('诚聘数据分析师',430,240,'http://qy.58.com/mapdetail.html?lat=116.337795%2C39.977523&name=%E5%B7%A5%E4%BD%9C%E5%9C%B0%E7%82%B9');"><i></i>查看地图</a>

获取企业介绍

企业信息都包含在这里面:

<div class="compIntro" id="gongsi">...</div>

定位方式为:直接div[class="compIntro"]#gongsi获取所有文字内容就是企业介绍了。

企业主页源码分析

58还真是方便,再牛的企业都是一模一样的简单网页。不过还好,这也方便获取数据了。
这个页面极其简单,但是有一点需要注意,数据是用表格动态呈现的,每种信息的位置并不固定,是根据企业有没有这个信息才显示出来的。所以在信息定位上,尽量避免用序号,只能用中文匹配了。。需要获取的数据如下:

  1. 卫星定位:在头文件中,如<meta name="location" content="province=北京;city=北京; coord=116.404,39.915">。找到<meta name="location" />获取coord属性值就好了。
  • 企业名称及ID:div[class="compT"] a[href]就可以找到企业名称,在href属性中的是/ID/这样的格式,去掉/就好了。
  • 企业资质:最好在div[class="basicMsg"] tr中用文字匹配。
  • 企业性质:最好在div[class="basicMsg"] tr中用文字匹配。
  • 企业行业:最好在div[class="basicMsg"] tr中用文字匹配。
  • 企业规模:最好在div[class="basicMsg"] tr中用文字匹配。
  • 联系人: 最好在div[class="basicMsg"] tr中用文字匹配。
  • 联系电话:用文字匹配或[class="telNum"] img,注意,联系电话都是图片格式的,而且可以不止一个!(省事的话就别下载图片了,保存链接就好了,因为图片来源明显不是静态图片而是服务器动态生成的。)
  • 企业网址(自己的):最好在div[class="basicMsg"] tr a中或用文字匹配。
  • 企业邮箱:和电话一样,用文字匹配或[class="telNum"] img来找图片。
  • 公司地址:最好在div[class="basicMsg"] tr中用文字匹配。

企业信用档案页面URL及源码分析

这个页面不知道入口在哪里?偶然看到的,然后心里大呼——哇塞!哈哈
虽然找不到入口或者查询页面,但是发现其实看懂URL就很简单了,必要格式如下:
http://credit.vip.58.com/usercredit?userId=企业ID
那么这时候刚才获取的企业ID就起作用了。手工输入了一下,ID对的话每家企业都能出来。
建立了档案的企业——会显示巨详细的信息!连法人代表、注册资本、详细地址全都有。
没建立档案的企业——也会显示页面,但信息处全都是空白。
下面就简单分析下基本信息的获取。

获取企业营业执照信息

表格基本上是固定位置的,因为大家营业执照都一样嘛哈哈~
首先获取信息框架:div[class="zzxx_ta"] table,然后再到这个框架里操作,就简单多了。
下面是信息定位分析:

  1. 公司名称:td[class="tdbg"] + td的第1项或span[class="headTitle"]
  • 注册号:td[class="tdbg"] + td的第2项
  • 经营地址:td[class="tdbg"] + td的第3项
  • 注册资本:td[class="tdbg"] + td的第4项
  • 成立日期:td[class="tdbg"] + td的第5项
  • 法定代表人:td[class="tdbg"] + td第6项
  • 登记机关:td[class="tdbg"] + td的第7项
  • 企业类型:td[class="tdbg"] + td的第8项
  • 营业期限:td[class="tdbg"] + td的第9项
  • 核准日期:td[class="tdbg"] + td的第10项
  • 登记状态:td[class="tdbg"] + td的第11项
  • 在营(开业)企业:td[class="tdbg"] + td的第12项
  • 经营范围:td[class="tdbg"] + td的第13项

获取企业其他信息

  1. 企业简介:div[class="briefIntro"]
  • 企业图片:div[class="albumBox"] img
  • 企业抽查检查信息:div[class="zzxx_ta"] nth-of-type(1) tr,如果有记录则显示,无记录则只显示一条“无xx信息”。可以适当排除。
  • 企业经营异常信息:div[class="zzxx_ta"] nth-of-type(2) tr,如果有记录则显示,无记录则只显示一条“无xx信息”。可以适当排除。
  • 企业行政处罚信息:div[class="zzxx_ta"] nth-of-type(3) tr,如果有记录则显示,无记录则只显示一条“无xx信息”。可以适当排除。
  • 企业严重违法信息:div[class="zzxx_ta"] nth-of-type(4) tr,如果有记录则显示,无记录则只显示一条“无xx信息”。可以适当排除。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容