拉勾网职位需求采集项目

一.需求分析

拉勾网的职位页面详情是由 http://www.lagou.com/jobs/ PositionId.html 组成。
我们打开不同的python求职页面,可以看到url地址的区别(如图不同之处为6284525和6278314):
在这里插入图片描述
在这里插入图片描述
而 PositionId 可以通过分析 Json 的 XHR 获得。我们要爬取的数据在content—>positionResult----->result下,包含了工作地点、公司名、职位等信息。 我们需要保存这个数据:
在这里插入图片描述
在这里插入图片描述
知道了数据的源头,接下来就按照常规步骤包装 Headers ,提交 FormData 来获取反馈数据。
注意防止反爬虫:
1.拉勾网反爬虫做的比较严,请求头多添加几个参数才能不被网站识别。
2.我们找到真正的请求网址,发现返回的是一个 JSON 串,解析这个 JSON 串即可,而且注意是 POST
传值,通过改变 Form Data 中 pn 的值来控制翻页。
真实请求的网址:
在这里插入图片描述
请求头信息:
在这里插入图片描述
Form data:
在这里插入图片描述

二.项目代码

1.核心代码,包括了构造headers,构造form data,获取json数据。

import time
import requests
import logging
from config import *
import pprint
import pandas as  pd
from concurrent.futures import ThreadPoolExecutor
def getPositionIDPage(url_start, url_parse, page=1, kd='python'):
    """

 获取PositionId列表所在页面, 返回的时json数据;
   :param url_start:   图形界面拉勾网职位信息的url地址;为了获取随机的session;
   :param url_parse: 真实返回json格式的url地址
   :param page: 访问的页数
   :param kd: 搜索的关键字
   :return: json数据格式的文本信息;
   """
    # 构造请求头(headers)
    headers = {'User-Agent': ua.random,
               'Host': Host,
               'Origin': Origin,
               'Referer': Referer,
               'Connection': Connection,
               'Accept': Accept,
               'proxies':proxies

               }

    # 构造表单
    data = {
        'first': False,
        'pn': str(page),
        'kd': kd

    }

    try:
        # requests库的session对象能够帮我们跨请求保持某些参数,
        # 也会在同一个session实例发出的所有请求之间保持cookies。
        # 创建一个session对象
        session = requests.Session()
        # 用session对象发出get请求,设置cookies
        session.get(url_start, headers=headers, timeout=3)  # 请求首页获取cookies
        cookie = session.cookies  # 为此次获取的cookies
        # 用session对象发出另外一个post请求,获取cookies , 返回响应信息
        response = session.post(url=url_parse,
                                headers=headers,
                                data=data,

                                )
        time.sleep(1)
        # 响应状态码为4xx客户端错误,或者5xx服务器错误响应,来抛出异常:
        response.raise_for_status()
        response.encoding = response.apparent_encoding
    except Exception as e:
        logging.error("页面" + url_parse + "爬取失败:", e)
    else:
        logging.info("页面" + url_parse + "爬取成功" + str(response.status_code))
        return response.json()


def analyse_PositionID(html):
    def analyse_PositionID(html):
        """
       根据获取的页面解析每一个招聘页面详情都有一个所属的ID索引
       :param html:
       :return:
       """
        #tag = 'positionId'
        positions = html['content']['positionResult']['result']
        df = pd.DataFrame(positions)
        return df

#封装爬取任务
def task(page):
   # 拉勾网页面
   url_start = 'https://www.lagou.com/jobs/list_python'
   # 真实的拉勾网url地址
   url_parse = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
   # 获取指定页拉勾网的职位信息, 返回的是json反序列化的结果
   html = getPositionIDPage(url_start, url_parse, page=page)
   # pprint.pprint(content)
   # 解析页面, 返回DataFrame格式的数据;
   df = analyse_PositionID(html)
   return  df

def save_as_csv():
    # 开启线程池
    with ThreadPoolExecutor(ThreadCount) as pool:
        results = pool.map(task, range(1, pages + 1))
    total_df = pd.concat(results, axis=0)
    total_df.to_csv(csv_filename, sep=',', header=True, index=False)
    logging.info("文件%s存储成功" % (csv_filename))
    return total_df


if __name__ == '__main__':
    # url_start = 'https://www.lagou.com/jobs/list_python'
    # url_parse = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult = false'
    # 
    # content = getPositionIDPage(url_start, url_parse)
    # pprint.pprint(content)
    save_as_csv()

2.配置config文件,把经常修改的信息写在config文件中,便于修改

from fake_useragent import UserAgent
Host = 'www.lagou.com'
Origin = 'https://www.lagou.com'
Referer = 'https://www.lagou.com/jobs/list_python'
Connection = 'keep-alive'
Accept = 'application/json, text/javascript, */*; q=0.01'
ua = UserAgent(verify_ssl=False)

# 爬取数据的页数
pages = 10
# 存储信息的csv文件位置
csv_filename = 'lagou.csv'
# 多线程开启的线程数;
ThreadCount = 100

结果如下图:
在这里插入图片描述
三.拉勾网页面分析
1.职位类别统计与公司统计

import pandas as pd
from config import  *
import matplotlib.pyplot as plt
import matplotlib#配置中文字体和修改字体大小
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family'] = 'sans-serif'
matplotlib.rcParams['font.size'] = 12
# 用来正常显示负号
plt.rcParams['axes.unicode_minus']=False
df = pd.read_csv(csv_filename, encoding='utf-8')
def show_second_type():
   # 获取职位类别分类并分组统计
   secondType_Series = df['secondType'].value_counts()
   # 设置图形的大小;
   plt.figure(figsize=(10,5))
   # 绘制条形图;
   secondType_Series.plot.bar()
   # 展示图形
   plt.show()
 
def show_company():
   companyShortName_Series = df['companyShortName'].value_counts()
   companyShortName_Series_gt5 =
companyShortName_Series[companyShortName_Series > 5]  # 选取招聘Python相关职位个数大
于等于5的公司
   plt.figure(figsize=(10, 5))
   companyShortName_Series_gt5.plot.bar()
   plt.show()
   
show_company()   
show_second_type()

职位统计:
在这里插入图片描述
公司统计:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值