拉钩网数据爬取

特别声明

众所周知,拉勾网的反爬机制更新较为频繁,本博客所分享的方法不一定永久有效,即具有时效性。研究该网站的反爬机制仅供交流学习,千万不要用于做违法的事情。

网站介绍

拉勾网是一个专业的互联网招聘平台,该网站上有很多公司的招聘信息,所以该网站也成了很多爬虫爬取的重点对象。

20200121182955743

思路分析

本文以Python为例进行思路分析,首先,在搜索框中输入关键字Python,并点击搜索

20200121183349962

可以跳转到如上图所示的页面,我们要爬取的数据就是下面的职位信息

2020012118351965

查看网页源代码,我们可以发现并没有我们想要的数据,由此可以判断数据通过其他的URL请求得到,下面进行抓包分析

image-20200813172130426

通过抓包,我们发现了请求的URL,请求方式为POST,但是,当我们直接用POST方式请求时,却不能获取到数据,直接给你返回“请求太频繁”(这个提示应该是假的),我尝试增加请求头中的信息,依旧没有用。后来,经过分析我知道了网站后台可能会判断你请求时的cookie,只有cookie正确,才给你返回信息,因此,我们的思路就很明确了,只要在请求之前拿到cookie,并且在请求时在加上cookie就行了。

核心思路:

为了能够拿到我们想要的职位信息,我们分两步走。 第一步,先用get的方式请求一开始的URL,即我们访问页面的URL,这一步的目的是为了能够得到cookie,为下一步请求做准备。 第一次请求的URL:https://www.lagou.com/jobs/list_Python?labelWords=&fromSearch=true&suginput= 第二步,我们用第一步拿到的cookie来发送POST请求,请求的URL为: https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false

另外作为 POST 请求,在请求数据的时候,可以传递查询的参数和数据

image-20200813172005815

具体实现

首先,我们可以用requests库中的session方法来创建一个session对象来存储cookie,然后再用这个cookie进行第二步中的请求即可。

代码

"""
拉勾网反爬机制分析:
通过两次请求来获取职位列表,
第一次请求原始页面获取cookie
第二次请求时利用第一次获取到的cookie

"""
import requests
# 第一次请求的URL
first_url = 'https://www.lagou.com/jobs/list_Python?labelWords=&fromSearch=true&suginput='
# 第二次请求的URL
second_url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
# 伪装请求头
headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Connection': 'keep-alive',
    'Content-Length': '25',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Host': 'www.lagou.com',
    'Origin': 'https://www.lagou.com',
    'Referer': 'https://www.lagou.com/jobs/list_Python?labelWords=&fromSearch=true&suginput=',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-origin',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
    'X-Anit-Forge-Code': '0',
    'X-Anit-Forge-Token': 'None',
    'X-Requested-With': 'XMLHttpRequest'
}
# 创建一个session对象
session = requests.session()
# 请求的数据
data = {
    'first': 'true',
    'pn': '1',
    'kd': 'Python'
}
session.get(first_url, headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36'
})
result = session.post(second_url, headers=headers, data=data, allow_redirects=False)
print(result.json())

分页爬取:

# -*- encoding: utf-8 -*-

import requests
import json
import jsonpath
import time
import pandas as pd

# 第一次请求的URL
first_url = 'https://www.lagou.com/jobs/list_Python?labelWords=&fromSearch=true&suginput='
# 第二次请求的URL
second_url = 'https://www.lagou.com/jobs/positionAjax.json?'
# 伪装请求头
headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Connection': 'keep-alive',
    'Content-Length': '25',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Host': 'www.lagou.com',
    'Origin': 'https://www.lagou.com',
    'Referer': 'https://www.lagou.com/jobs/list_Python?labelWords=&fromSearch=true&suginput=',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-origin',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
    'X-Anit-Forge-Code': '0',
    'X-Anit-Forge-Token': 'None',
    'X-Requested-With': 'XMLHttpRequest'
}

# 创建一个session对象
session = requests.session()
session.get(first_url, headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36'
})

# 可以自己改变城市
params = {
    'px': 'default',
    'city': '北京',
    'needAddtionalResult': 'false'
}

page = 1
# 爬取 10 页
for i in range(10):
    # 请求的数据
    form_data = {
        'first': 'false',
        'pn': page,
        'kd': 'python'
    }
    response = session.post(url=second_url
                            , headers=headers
                            , params=params
                            , data=form_data,
                            allow_redirects=False)
    python_obj = json.loads(response.content)
    result_list = jsonpath.jsonpath(python_obj, '$..result')[0]
    for item in result_list:
        po = dict()
        po[u'positionName'] = item["positionName"]
        po[u'city'] = item['city']
        po[u'district'] = item['district']
        po[u'skillLables'] = item['skillLables']
        po[u'salary'] = item['salary']
        po[u'jobNature'] = item['jobNature']
        po[u'education'] = item['education']
        po[u'companyFullName'] = item['companyFullName']
        po[u'companySize'] = item['companySize']
        po[u'createTime'] = item['createTime']

        po = pd.DataFrame(po)
        po.to_csv('LGW.csv', header=False, index=False, mode='a+')

    page += 1
    time.sleep(4)

image-20200813194400349

参考

Update time: 2020-08-13

results matching ""

    No results matching ""