其他分享
首页 > 其他分享> > 拉钩网招聘信息爬虫项目

拉钩网招聘信息爬虫项目

作者:互联网

需求分析

知己知彼,方可百战不殆。在学习技术的时候我们往往面临太多选择而不知所措,可能是各个方面都有
涉猎,对某个领域没有深入研究,看似什么都会,真要让你做个什么东西的时候就显得捉肘见襟。如果
我们能从招聘职位所需的技能开始学习,便可练就一身硬功夫,为实战应用中打下良好的基础。
通过python抓取拉钩网的招聘详情,并筛选其中的技能关键词,存储到 excel 中。

职位需求页面分析

通过观察可以发现,拉勾网的职位页面详情是由 http://www.lagou.com/jobs/
PositionId.html 组成。
而 PositionId 可以通过分析 Json 的 XHR 获得。而红框里的职位描述内容是我们要抓取的数据。
在这里插入图片描述
知道了数据的源头,接下来就按照常规步骤包装 Headers ,提交 FormData 来获取反馈数据。

PositionId 数据采集

注意:
拉勾网反爬虫做的比较严,请求头多添加几个参数才能不被网站识别。
我们找到真正的请求网址,发现返回的是一个 JSON 串,解析这个 JSON 串即可,而且注意是 POST
传值,通过改变 Form Data 中 pn 的值来控制翻页。
XHR : XMLHttpRequest 对象用于和服务器交换数据。
点击页面中的页数,比如第 2 页,我们可以在右边看到一个 POST 请求,这个请求里面包含了真实的
URL( 浏览器上的 URL 并没有职位数据,查看源代码就可以发现这一点)、 POST 请求的请求头
Headers 、 POST 请求提交的表单 Form Data (这里面包含了页面信息 pn 、搜索的职位信息 kd )
真实的URL获取
在这里插入图片描述
请求头信息
我们需要构造的请求头Headers信息,如果这里没有构造好的话,容易被网站识别为爬虫,从而拒绝访问请求。
表单信息
发送POST请求时需要包含的表单信息 Form Data 。
在这里插入图片描述

返回的JSON数据

发现需要的职位信息在 content –> positionResult –> result 下,其中包含了工作地点、公司名、职位等信息。 我们只需要保存这个数据就可以了。
至此我们分析完毕网页,下面可以开始爬取过程了。

项目代码

配置文件 config.py 文件

"""
Date: 2019--14 10:36
User: yz
Email: 1147570523@qq.com
Desc:
"""
from fake_useragent import UserAgent
import requests

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

url = 'http://172.25.254.39:9999/get_proxy/'
proxies = requests.get(url).text

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

核心代码文件 run.py

数据存储:
csv 格式

开启线程池,批量爬取职位信息,并存储于 csv 文件;
修改文件run.py : 封装页面爬取和页面解析的任务;

"""
Date: 2019--14 10:10
User: yz
Email: 1147570523@qq.com
Desc:
"""
import requests
import logging
import pandas as pd
import time
import pprint
from config import *
from concurrent.futures import ThreadPoolExecutor

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='lagou.log',
                    filemode='w')


def getPositionIDPage(url_start, url_parse, page=1, kd='python'):
    headers = {'User-Agent': ua.random,
               'Host': Host,
               'Origin': Origin,
               'Referer': Referer,
               'Connection': Connection,
               'Accept': Accept,
               'proxies': proxies
               }
    # 构造表单
    data = {
        'first': True,
        '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
        # print(cookie)
    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):
    """
   根据获取的页面解析每一个招聘页面详情都有一个所属的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_parse = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
    html = getPositionIDPage(url_start, url_parse,page=page)
    # pprint.pprint(content)
    df = analyse_PositionID(html)
    # 解析页面, 返回DataFrame格式的数据;
    return df

def save_as_csv():
    """
   将获取的页面解析后的信息通过多线程的方式以csv格式存储到文件
   :return:
   """
    # 开启线程池
    with ThreadPoolExecutor(ThreadCount) as pool:
        # map方法中,可迭代对象传入函数是从前到后逐个提取元素, 并将结果依次存储到results中;
        results = pool.map(task, range(1, pages + 1))
        # 拼接获取的所有信息, axis=0代表往跨行(down),而axis=1代表跨列(across)
    total_df = pd.concat(results, axis=0)
    """
    sep: 输出文件的字段分隔符, 默认为逗号;
    header: 是否写出列名;
    index: 是否写入行名称(索引);
    """
    total_df.to_csv(csv_filename, sep=',', header=True, index=False)
    logging.info("文件%s存储成功" % (csv_filename))
    return total_df
if __name__ == '__main__':
    save_as_csv()

在这里插入图片描述
在这里插入图片描述

PositionId 页面解析

获取所需的岗位ID,每一个招聘页面详情都有一个所属的ID索引。将我们爬取下来的信息提取出我们想要的信息。
核心代码:

"""
Date: 2019--14 11:52
User: yz
Email: 1147570523@qq.com
Desc:
"""
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_job_nature():
    jobNature_Series = df['jobNature'].value_counts()
    print(jobNature_Series)
    plt.figure(figsize=(10, 5))
    # 饼状图
    jobNature_Series.plot.pie()
    plt.show()

def show_company():
    companyShortName_Series = df['companyShortName'].value_counts()
    companyShortName_Series_gt5 =companyShortName_Series[companyShortName_Series > 2]  # 选取招聘Python相关职位个数大于等于5的公司
    plt.figure(figsize=(10, 5))
    companyShortName_Series_gt5.plot.bar()
    plt.show()

if __name__ == '__main__':
    show_second_type()
    show_job_nature()
    show_company()

职位类别统计
在这里插入图片描述
公司统计
统计每个公司出现的个数,然后选取招聘Python相关职位个数大于等于2的公司。
在这里插入图片描述

标签:url,Series,招聘,爬虫,拉钩,df,import,csv,页面
来源: https://blog.csdn.net/qq_41355482/article/details/99632046