• 智联招聘爬虫源码分析(一)


        最近一直在关注秋招,虽然还没轮到我,不过提前准备总是好的。近期听闻今年秋招形势严峻,为了更好的准备将来的实习、工作,我决定在招聘网站上爬取一些与数据有关的岗位信息,借以给自己将来的职业道路选择提供参考。

    一、原理

        通过Python的requests库,向网站服务器发送请求,服务器返回相关网页的源码,再通过正则表达式等方式在网页源码中提取出我们想要的信息。

    二、网页分析

        2.1岗位详情url

            在智联招聘网站中搜索'大数据',跳转到大数据岗位页面,接下来我们点开开发者选项,刷新页面,在Network面板的XHR中发现了这样一个数据包:

    XHR: XHR为向服务器发送请求和解析服务器响应提供了流畅的接口,能够以异步方式从服务器取得更多信息,意味着用户单击后,可以不必刷新页面也能取得新数据

            在新的页面打开后:

            这个页面里出现的所有的岗位信息都在里面了:岗位名称、公司名称、薪水、地区、详情界面的url都在该json里。但是这些信息都不是最重要的,我需要岗位要求以及岗位职责的要求。

            将该json解析,得到如下结构的json数据:

            code的值为HTTP的响应码,200表示请求成功。而results数组则是该页面岗位信息的数据。点开第一条数据(results的第一个元素):

            页面中出现的所有数据,以及相关的超链接都在这儿。其中,我们需要的是指向岗位详情界面的超链接——'positionURL'。点击该链接,进去该岗位信息详情页面:

            好了,我们需要的信息出现了,不过为了简化页面分析的操作,以及尽可能地不被反爬,我决定选择移动适配的页面。

            再打开开发者选项,在该岗位详情页面,刷新:

            在<meta>中找到'mobile-agent',提取后面的url——'url=//m.zhaopin.com/jobs/CZ745244850J00020982209/',打开:

            真清爽!

        2.2 Xpath定位

            XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言

        分析该网页的源代码,寻找我们所需信息的位置:

        岗位名称、月薪、公司、地区、学历、年限信息都在'//*[@id="r_content"]/div[1]/div/div[1]/div[1]/'下。

    1. title = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[1]/h1/text()')  
    2. pay = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[1]/div[1]/text()')  
    3. place = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[3]/div[1]/span[1]/text()')  
    4. campanyName = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[2]/text()')  
    5. edu = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[3]/div[1]/span[3]/text()')  

    岗位要求与岗位职责在同一个<div>标签里:

        也爬出来:

    1. comment = selector.xpath('//*[@id="r_content"]/div[1]/div/article/div/p/text()')  

    好了,最复杂的部分搞定。

    三、JSON数据包地址

        我们将前三页的数据包地址比对一下就能看出问题:

    1. https://fe-api.zhaopin.com/c/i/sou?pageSize=60&cityId=489&workExperience=-1&education=-1&companyType=-1&employmentType=-1&jobWelfareTag=-1&kw=%E5%A4%A7%E6%95%B0%E6%8D%AE&kt=3&_v=0.14571817&x-zp-page-request-id=ce8cbb93b9ad4372b4a9e3330358fe7c-1541763191318-555474  
    2. https://fe-api.zhaopin.com/c/i/sou?start=60&pageSize=60&cityId=489&workExperience=-1&education=-1&companyType=-1&employmentType=-1&jobWelfareTag=-1&kw=%E5%A4%A7%E6%95%B0%E6%8D%AE&kt=3&_v=0.14571817&x-zp-page-request-id=ce8cbb93b9ad4372b4a9e3330358fe7c-1541763191318-555474  
    3. https://fe-api.zhaopin.com/c/i/sou?start=120&pageSize=60&cityId=489&workExperience=-1&education=-1&companyType=-1&employmentType=-1&jobWelfareTag=-1&kw=%E5%A4%A7%E6%95%B0%E6%8D%AE&kt=3&_v=0.14571817&x-zp-page-request-id=ce8cbb93b9ad4372b4a9e3330358fe7c-1541763191318-555474  
    4. https://fe-api.zhaopin.com/c/i/sou?start=180&pageSize=60&cityId=489&workExperience=-1&education=-1&companyType=-1&employmentType=-1&jobWelfareTag=-1&kw=%E5%A4%A7%E6%95%B0%E6%8D%AE&kt=3&_v=0.14571817&x-zp-page-request-id=ce8cbb93b9ad4372b4a9e3330358fe7c-1541763191318-555474  

    1.我们可以看出第一页的url结构与后面的url结构有明显的不同。

    2.非首页的url有明显的规律性。

    3.'kw=*&kt'里的字符为'大数据'的UTF-8编码。

    所以我们对数据包有如下的操作:

    1. if __name__ == '__main__':  
    2.     key = '大数据'  
    3.     
    4.     url = 'https://fe-api.zhaopin.com/c/i/sou?pageSize=60&cityId=489&workExperience=-1&education=-1&companyType=-1&employmentType=-1&jobWelfareTag=-1&kw=' + key + '&kt=3&lastUrlQuery=%7B%22pageSize%22:%2260%22,%22jl%22:%22489%22,%22kw%22:%22%E5%A4%A7%E6%95%B0%E6%8D%AE%22,%22kt%22:%223%22%7D'  
    5.     infoUrl(url)  
    6.     
    7.     urls = ['https://fe-api.zhaopin.com/c/i/sou?start={}&pageSize=60&cityId=489&kw='.format(i*60)+key+'&kt=3&lastUrlQuery=%7B%22p%22:{},%22pageSize%22:%2260%22,%22jl%22:%22489%22,%22kw%22:%22java%22,%22kt%22:%223%22%7D'.format(i) for i in range(1,50)]  
    8.     for url in urls:  
    9.         infoUrl(url)  

    四、源码结构

        1、截取整个结果界面的JSON数据包,从中提取出各个招聘栏的url。

        2、进入招聘详细信息页面,提取移动端url。

        3、进入移动端界面,抓取需要的信息。

    五、源码

    1. ''''' 
    2.     智联招聘——爬虫源码————2018.11 
    3. '''  
    4. import requests  
    5. import re  
    6. import time  
    7. from lxml import etree  
    8. import csv  
    9. import random  
    10.     
    11. fp = open('智联招聘.csv','wt',newline='',encoding='UTF-8')  
    12. writer = csv.writer(fp)  
    13. '''''地区,公司名,学历,岗位描述,薪资,福利,发布时间,工作经验,链接'''  
    14. writer.writerow(('职位','公司','地区','学历','岗位','薪资','福利','工作经验','链接'))  
    15.     
    16. def info(url):  
    17.     res = requests.get(url)  
    18.     u = re.findall('<meta name="mobile-agent" content="format=html5; url=(.*?)" />', res.text)  
    19.     
    20.     if len(u) > 0:  
    21.         u = u[-1]  
    22.     else:  
    23.         return  
    24.     
    25.     u = 'http:' + u  
    26.     
    27.     headers ={  
    28.         'User-Agent''Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36'  
    29.     }  
    30.     
    31.     res = requests.get(u,headers=headers)  
    32.     selector = etree.HTML(res.text)  
    33.     
    34.     # # 岗位名称  
    35.     title = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[1]/h1/text()')  
    36.     # # 岗位薪资  
    37.     pay = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[1]/div[1]/text()')  
    38.     # # 工作地点  
    39.     place = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[3]/div[1]/span[1]/text()')  
    40.     # # 公司名称  
    41.     companyName = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[2]/text()')  
    42.     # # 学历  
    43.     edu = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[3]/div[1]/span[3]/text()')  
    44.     # # 福利  
    45.     walfare = selector.xpath('//*[@id="r_content"]/div[1]/div/div[3]/span/text()')  
    46.     # # 工作经验  
    47.     siteUrl = res.url  
    48.     workEx = selector.xpath('//*[@id="r_content"]/div[1]/div/div[1]/div[3]/div[1]/span[2]/text()')  
    49.     # # 岗位详细  
    50.     comment = selector.xpath('//*[@id="r_content"]/div[1]/div/article/div/p/text()')  
    51.     writer.writerow((title, companyName, place, edu, comment, pay, walfare, workEx, siteUrl))  
    52.     print(title, companyName, place, edu, comment, pay, walfare, workEx, siteUrl)  
    53.     
    54. def infoUrl(url):  
    55.     res = requests.get(url)  
    56.     selector = res.json()  
    57.     code = selector['code']  
    58.     if code == 200:  
    59.         data = selector['data']['results']  
    60.         for i in data:  
    61.             href = i['positionURL']  
    62.             info(href)  
    63.             time.sleep(random.randrange(1,4))  
    64.     
    65. if __name__ == '__main__':  
    66.     key = '大数据'  
    67.     
    68.     url = 'https://fe-api.zhaopin.com/c/i/sou?pageSize=60&cityId=489&workExperience=-1&education=-1&companyType=-1&employmentType=-1&jobWelfareTag=-1&kw=' + key + '&kt=3&lastUrlQuery=%7B%22pageSize%22:%2260%22,%22jl%22:%22489%22,%22kw%22:%22%E5%A4%A7%E6%95%B0%E6%8D%AE%22,%22kt%22:%223%22%7D'  
    69.     infoUrl(url)  
    70.     
    71.     urls = ['https://fe-api.zhaopin.com/c/i/sou?start={}&pageSize=60&cityId=489&kw='.format(i*60)+key+'&kt=3&lastUrlQuery=%7B%22p%22:{},%22pageSize%22:%2260%22,%22jl%22:%22489%22,%22kw%22:%22java%22,%22kt%22:%223%22%7D'.format(i) for i in range(1,50)]  
    72.     for url in urls:  
    73.         infoUrl(url)  

    Ps.因为某些原因,我打算每个月爬取智联招聘、51job的岗位信息一次,源码、优化都会以博客的形式写出来,欢迎关注~

    源码地址:智联招聘_爬虫源码

  • 相关阅读:
    Android Studio 2.2以上支持了Cmake的配置JNI的相关参数
    Unable to instantiate receiver xxx.receiver.NetworkReceiver异常
    关于imageview matrix
    Android NDK开发 JNI操作java构造方法,普通方法,静态方法(七)
    COOKIE和SESSION的区别
    Android NetworkInterface 的 name
    Android ROM资源文件存放位置
    selinux
    当WebView运行在特权进程时抛出安全异常,Hook方式解决方案(包含对Android 8.0的处理)
    Android判断当前是否在主线程
  • 原文地址:https://www.cnblogs.com/magicxyx/p/9937244.html
Copyright © 2020-2023  润新知