【Python】猎聘网招聘数据爬虫(Python网络爬虫课设简要)

2023-11-02

【Python】猎聘网招聘数据爬虫(Python网络爬虫课设简要)

注:

  • 本文仅供学习交流使用!

  • 合肥学院-20信管-20302211009

  • 项目文件可自行前往博客主页下载或联系作者qq(3416252112)。

  • 爬取数据耗时约50分钟!

1、背景介绍(废话)

随着全球经济的发展和全球化竞争的加剧,招聘人才对于企业的成功变得至关重要。同时,求职者也面临着日益激烈的就业竞争。在这样的背景下,招聘市场不断发展,招聘过程变得更加复杂和竞争激烈。

互联网的普及和技术的发展给招聘带来了新的机遇和挑战。互联网招聘平台的兴起为企业和求职者提供了更广泛的交流和信息渠道。企业可以在招聘平台上发布招聘信息,同时通过筛选和匹配算法更准确地找到符合要求的人才;求职者可以通过招聘平台查找和申请适合自己的工作岗位。这种高效便捷的招聘方式极大地提高了招聘效率和成功率。

作为国内领先的互联网招聘平台之一,猎聘网汇聚了众多企业和求职者。其庞大的企业用户群体和海量的招聘信息资源使得猎聘网成为了人力资源管理领域的重要参考和决策依据。因此,对于猎聘网招聘数据的爬取和可视化分析具有重要的研究和实践价值。

在接下来的报告中,我们将详细介绍猎聘网招聘数据的爬取与可视化方法,并探讨其在人力资源决策和市场分析中的应用。

2、研究内容与目标(废话)

招聘数据对于人力资源决策具有重要性。通过分析招聘数据,可以了解当前市场的人才需求情况、行业的就业趋势以及薪资水平的变化等信息。这些信息对企业在招聘岗位时可以更好地定位和吸引合适的人才,从而提高招聘的效率和成功率。同时,求职者可以利用招聘数据了解就业市场的动态,选择适合自己的岗位和行业,提升就业竞争力。

猎聘网作为一家知名的招聘平台,拥有庞大的招聘数据资源。理解和利用猎聘网的招聘数据,可以帮助我们深入了解不同行业的人才需求和就业趋势,为企业的人才战略提供有力支持。通过数据爬取和可视化的方法,我们可以将海量的数据转化为直观、易于理解的图表和图形,帮助决策者快速把握关键信息,做出准确的决策。

本报告的目的是介绍猎聘网招聘数据的爬取与可视化方法,通过对招聘数据的分析和可视化,为人力资源决策提供科学依据,提高招聘效率和成功率。同时,我们还希望能够推动数据爬取与可视化技术在招聘领域的应用和研究,促进人力资源管理的创新和发展。

3、爬取对象

爬取数据对象为[‘Java开发’, ‘数据挖掘’, ‘互联网产品经理’, ‘软件测试’, ‘图像算法工程师’],这五个关键字的检索结果,每个关键字共有四百条检索结果,总计2000条记录,最终成功爬取记录数为1581条,表结构如下图所示。

image-20230603155536056

4、功能描述

本次课设数据爬虫功能主要包括以下几个方面:

  • 数据收集:数据爬虫能够自动化地从目标网站上抓取数据。通过指定合适的URL和参数,爬虫可以访问网页并提取所需的信息,例如招聘信息、公司信息、职位要求、工作地点等。爬虫可以遍历多个页面或进行深度抓取,以获取更全面的数据。
  • 数据解析:爬虫可以解析从网页中提取的原始数据,并提取出有用的信息。这包括对HTML、XML等页面结构的解析,以及对文本、图像、链接等内容的提取和分析。通过数据解析,爬虫能够将抓取的数据转化为结构化的格式,以便后续的处理和分析。
  • 数据清洗:抓取的数据往往包含冗余、不完整或错误的信息。数据爬虫可以进行数据清洗,去除重复项、清理无效数据,并进行格式化和规范化,以确保数据的准确性和一致性。数据清洗可以提高后续数据处理和分析的效果。
  • 数据存储:抓取到的数据需要进行存储,以便后续的使用和分析。数据爬虫可以将清洗后的数据保存到合适的存储介质中,如数据库、文件或云存储服务。爬虫还可以管理数据存储的结构和索引,以方便数据的检索和查询。

5、数据爬取及存储流程

数据爬取及存储业务流程共包含以下步骤:

  1. 初始化:创建数据库、创建表、创建全局的数据列表(用于暂时存储爬取结果);
  2. 使用selenium爬取关键字检索结果中的岗位信息链接,并存入txt文件中;
  3. 岗位链接爬取完成之后读取岗位链接,然后通过requests依次爬取岗位页面;
  4. 使用XPath对爬取到的页面进行解析并将解析结果添加到数据列表(同时将岗位的详细信息保存到txt文件中,以备生成词云图);
  5. 页面解析完成后,遍历数据列表,将取出的数据依次插入到数据库表中,最后结束爬取.

流程图如下:

image-20230603155906824

6、爬虫目录结构介绍

爬虫代码总体包含六个方法别为 __init__()get_post_link()get_post_detail()save_data()over()run(),具体功能如下:

  1. __init__:该方法主要作用为创建全局信息(岗位列表、岗位链接列表、岗位数据列表)、创建数据库连接和表、读取用户标识库(User-Agent);

  2. get_post_link:该方法主要功能为使用selenium动态爬取关键字(岗位列表)检索结果的岗位链接,并将链接信息保存到同级目录下的“PostUrls”目录;

  3. get_post_detail:根据“PostUrls”目录下的url信息,使用requests依次爬取岗位详情页,并使用XPath对页面进行解析,将解析后的数据添加到岗位数据列表,以及将岗位详情字段保存到同级目录下得“PostIntroduceDatas”目录下以备生成岗位词云图;

  4. save_data:遍历岗位数据列表使用SQL语句依次将列表中的数据插入到job_database数据库的Jobs表中;

  5. over:该方法用于关闭数据库连接;

  6. run:运行方法,调用get_post_link()、get_post_detail()和over()方法,进行爬虫工作;

代码结构如下图:

image-20230603160026112

7、爬取过程截图

  • 爬取岗位链接截图

image-20230603160109684

  • 提取岗位数据截图

image-20230603160129133

8、爬虫源代码

import random
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.common.by import By
import requests
import sqlite3
from lxml import etree


class LiePin:
    def __init__(self):
        # 岗位列表
        self.driver = None
        self.post_list = ['Java开发', '数据挖掘', '互联网产品经理', '软件测试', '图像算法工程师']
        # 岗位链接列表
        self.all_link = []
        # 等待3三秒
        time.sleep(3)

        # 随机用户(User_Agent)
        with open('User_Agent_pool.txt', 'r', encoding='utf8') as fp:
            self.user_Agent = fp.readlines()
            self.user_Agent = [i.strip() for i in self.user_Agent]

        # 创建数据库连接对象
        self.conn = sqlite3.connect('job_database.db')
        # 创建游标对象
        self.cursor = self.conn.cursor()
        # 创建jobs表
        self.create_table_sql = "CREATE TABLE Jobs (信息ID INTEGER PRIMARY KEY AUTOINCREMENT, 岗位链接 VARCHAR, 搜索岗位名 VARCHAR, 岗位名称 VARCHAR, " \
                               "企业名称 VARCHAR, 薪资区间 VARCHAR, 工作地点 VARCHAR, 工作经验 VARCHAR, 学历要求 VARCHAR, 岗位介绍 VARCHAR, 其他待遇 VARCHAR , 企业经营范围 VARCHAR)"
        self.cursor.execute(self.create_table_sql)

    def get_post_link(self, post):
        # 创建浏览器对象
        self.driver = webdriver.Chrome()
        # 打开网页
        self.driver.get('https://www.liepin.com/zhaopin/')
        time.sleep(3)
        print("===========开始爬取", post, "岗位链接===========")
        # 定位搜索框并输入关键词
        search_box = self.driver.find_element(By.XPATH, "//div[@id='lp-search-bar-section']//input")
        search_box.send_keys(post)
        search_box.send_keys(Keys.RETURN)
        # 共爬取10页链接
        # 结果数据
        result = []
        for page in range(10):
            print("开始爬取第", page + 1, "页链接…………")
            # 等待页面加载完成
            time.sleep(3)
            # 读取当前页岗位数量
            divs = self.driver.find_elements(By.XPATH, "//div[@class='content-wrap']//div[@class='job-list-box']/div")
            for i in range(1, len(divs) + 1):
                # print(i)
                link = self.driver.find_element(By.XPATH, f"//div[@class='job-list-box']/div[{i}]//a").get_attribute("href")
                # 存储岗位链接信息
                result.append(str(link))
                # print("测试", result[0])
            time.sleep(3)
            # 爬取下一页
            if page == 9:
                break
            self.driver.find_element(By.XPATH, "//div[@class='list-pagination-box']//li["
                                               "@class='ant-pagination-next']/button").click()
        # 将链接列表保存至文件
        self.all_link.append(result)
        with open(f'PostUrls/{post}_url.txt', 'a', encoding='utf-8') as fp:
            for item in result:
                fp.write(item + '\n')

    # 爬取岗位详情信息
    def get_post_detail(self):
        print("==========================开始提取各岗位详情页信息==========================")

        for post in self.post_list:
            print("++++++++++++开始获取", post, "相关岗位详情信息++++++++++++")
            with open(f'PostUrls/{post}_url.txt', 'r', encoding='utf-8') as fp:
                urls = fp.readlines()
            with open(f'PostIntroduceDatas/{post}_detail.txt', 'a', encoding='utf-8') as fp:
                index = 0
                result = []
                for url in urls:
                    index += 1
                    print(f"提取{post}岗位,第", index, "条数据……")
                    time.sleep(1)
                    try:
                        # 发送GET请求
                        response = requests.get(url=url, headers={"User-Agent": random.choice(self.user_Agent)})
                        html_str = etree.HTML(response.text)
                        # 岗位链接
                        post_link = str(url)
                        # 搜索岗位名
                        search_name = post
                        # 岗位名称
                        post_name = html_str.xpath("//body/section[3]//div[@class='name-box']/span[1]")[0].text
                        # 企业名称
                        enterprise_name = html_str.xpath("//aside//div[@class='company-info-container']//div["
                                                         "contains(@class,'name')]")[0].text
                        # 企业经营范围
                        enterprise_scope = html_str.xpath("//aside//div[@class='register-info']/div[contains(@class,"
                                                          "'ellipsis-4')]/span[2]")[0].text
                        # 薪资区间
                        post_salary = html_str.xpath("//body/section[3]//div[@class='name-box']/span[@class='salary']")[0].text
                        # 工作地点
                        post_location = html_str.xpath("//body/section[3]//div[@class='job-properties']/span[1]")[0].text
                        # 工作经验
                        work_experience = html_str.xpath("//body/section[3]//div[@class='job-properties']/span[3]")[0].text
                        # 学历要求
                        educational_requirements = html_str.xpath("//body/section[3]//div["
                                                                  "@class='job-properties']/span[5]")[0].text
                        # 其他待遇
                        about_treatment = ''
                        for sub in html_str.xpath("//body/section[4]//div[@class='labels']/span"):
                            about_treatment += ' ' + sub.text
                        # 岗位介绍
                        post_introduce = html_str.xpath("//main//dl[1]/dd")[0].text
                        # 保存数据
                        # self.save_data(post_link, )
                        detail = {
                            "岗位链接": post_link,
                            "搜索岗位名": search_name,
                            "岗位名称": post_name,
                            "企业名称": enterprise_name,
                            "薪资区间": post_salary,
                            "工作地点": post_location,
                            "工作经验": work_experience,
                            "学历要求": educational_requirements,
                            "岗位介绍": post_introduce,
                            "其他待遇": about_treatment,
                            "企业经营范围": enterprise_scope
                        }
                        # 添加至总结果列表
                        result.append(detail)
                        # print(detail)
                        # 将岗位介绍信息写入txt文件,以备提取词云
                        fp.write(detail['岗位介绍'] + '\n\n')
                    except Exception as e:
                        with open('error_url/error_message.txt', 'a', encoding='utf-8') as f:
                            f.write("爬取失败url:" + url)
            # 将数据存入数据库
            print(f"+++++开始将{post}岗位数据存入数据库+++++")
            self.save_data(result)
        # 保存结果数据
        # self.save_data(result)

    # 保存数据
    def save_data(self, result):
        print("==========开始将数据存入数据库=========")
        print("共", len(result), "条数据,开始存入数据库…………")

        for item in result:
            try:
                insert_sql = f"INSERT INTO Jobs(岗位链接, 搜索岗位名, 岗位名称, 企业名称, 薪资区间, 工作地点, 工作经验, 学历要求, 岗位介绍, 其他待遇, 企业经营范围) " \
                             f"VALUES('{item['岗位链接']}', '{item['搜索岗位名']}', '{item['岗位名称']}', '{item['企业名称']}', '{item['薪资区间']}', '{item['工作地点']}', '{item['工作经验']}', '{item['学历要求']}', '{item['岗位介绍']}', '{item['其他待遇']}', '{item['企业经营范围']}')"
                self.cursor.execute(insert_sql)
            except Exception as e:
                print("当前记录异常,忽略……")
        # 提交事务
        self.conn.commit()
        print("数据存储完毕!")

    def over(self):
        # 关闭数据库连接
        self.conn.close()

    def run(self):
        # 爬取各岗位链接
        for post in self.post_list:
            self.get_post_link(post)
        self.get_post_detail()
        self.over()


if __name__ == '__main__':
    liepin = LiePin()
    liepin.run()
    print("数据采集完毕!")

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Python】猎聘网招聘数据爬虫(Python网络爬虫课设简要) 的相关文章

  • 即使页面未完全加载,我们也可以使用 Selenium 获取页面源吗(TimeoutException: Message: timeout)?

    即使遇到 TimeoutException Message timeout 也能获取页面源码吗 当我调用 driver page source 时 有时无法加载整页 但我只需要它的部分信息 尚未确定 所以我只想在任何情况下保存页面 是否可以
  • JavaScript 相当于 Python 的参数化 string.format() 函数

    这是 Python 示例 gt gt gt Coordinates latitude longitude format latitude 37 24N longitude 115 81W Coordinates 37 24N 115 81W
  • Kivy - 文本换行工作错误

    我正在尝试在 Kivy 1 8 0 应用程序中换行文本 当没有太多文字时 一切正常 但如果文本很长并且窗口不是很大 它只是剪切文本 这是示例代码 vbox BoxLayout orientation vertical size hint y
  • Python 2.7 将比特币私钥转换为 WIF 私钥

    作为一名编码新手 我刚刚完成了教程 教程是这样的 https www youtube com watch v tX XokHf nI https www youtube com watch v tX XokHf nI 我想用 1 个易于阅读
  • 希伯来语中的稀疏句子标记化错误

    尝试对希伯来语使用稀疏句子标记 import spacy nlp spacy load he doc nlp text sents list doc sents I get Warning no model found for he Onl
  • 将 numpy 数组写入文本文件的速度

    我需要将一个非常 高 的两列数组写入文本文件 而且速度非常慢 我发现如果我将数组改造成更宽的数组 写入速度会快得多 例如 import time import numpy as np dataMat1 np random rand 1000
  • 如何使用显式引用转储 YAML?

    递归引用非常适合ruamel yaml or pyyaml ruamel yaml dump ruamel yaml load A A id001 id001 然而 它 显然 不适用于普通引用 ruamel yaml dump ruamel
  • 为什么我的代码不能根据字典解码加密字符串?

    我有一本字典 其中包含代表字母的键和值 例如一个简单的 DICT CODE b g n a p o x d t y 我收到了一个加密代码 并将该字符串转换为一个列表 其中每个项目都是一个单词 我需要根据字典中的项目来解决它 代码示例是 wo
  • TF map_fn 或 while_loop 用于不同形状的张量列表

    我想处理不同形状的张量序列 列表 并输出另一个张量列表 考虑每个时间戳上具有不同隐藏状态大小的 RNN 就像是 输入 tf ones 1 2 2 tf ones 2 2 3 tf ones 3 2 1 输出 tf zeros 1 2 4 t
  • 如何在 PyCharm 4.5.2 中使用 PyPy 作为标准/默认解释器?

    如何在 PyCharm 4 5 2 中使用 PyPy 作为标准 默认解释器 一切都在 Ubunutu 14 10 下运行 并且 pypy 已经安装 您可以在项目的设置下进行配置 这个官方文档直接涵盖了 https www jetbrains
  • Selenium 和 TestNG 同时使用“dependsOn”和“priority =”问题

    我正在努力在 GUI 自动化测试中实现更好的工作流程控制 我首先从dependsOn开始 但很快发现缺点是如果一个测试失败 则套件的整个其余部分都不会运行 所以我改用 priority 但看到了意外的行为 一个例子 Test priorit
  • python 中的 Johansen 协整检验

    我找不到任何有关在处理统计和时间序列分析 pandas 和 statsmodel 的 Python 模块中执行 Johansen 协整检验的功能的参考 有谁知道是否有一些代码可以执行时间序列之间的协整测试 现在 这已在 Python 的 s
  • PySide6.1 与 matplotlib 3.4 不兼容

    当我只安装PySide6时 GUI程序运行良好 但是一旦我安装了matplotlib及其依赖包 包括pyqt5 则GUI程序将无法运行并输出以下错误消息 This application failed to start because no
  • 如何使用 Django 项目设置 SQLite?

    我已阅读 Django 文档 仅供参考 https docs djangoproject com en 1 3 intro tutorial01 https docs djangoproject com en 1 3 intro tutor
  • Python 类型安全吗?

    根据维基百科 https en wikipedia org wiki Type system Type safety and memory safety 如果一种语言不允许违反类型系统规则的操作或转换 计算机科学家就认为该语言是 类型安全的
  • Python 声音(“铃声”)

    我想让一个 python 程序在完成任务时通过发出嘟嘟声来提醒我 目前 我使用import os然后使用命令行语音程序说 进程完成 我更愿意它是一个简单的 铃 我知道有一个函数可以用于Cocoa apps NSBeep 但我认为这与此没有太
  • 检测 IDLE 的存在/如何判断 __file__ 是否未设置

    我有一个脚本需要使用 file 所以我了解到 IDLE 没有设置这个 有没有办法从我的脚本中检测到 IDLE 的存在 if file not in globals file is not set 如果你想做一些特别的事情 file 未设置
  • 处理大文件的最快方法?

    我有多个 3 GB 制表符分隔文件 每个文件中有 2000 万行 所有行都必须独立处理 任何两行之间没有关系 我的问题是 什么会更快 逐行阅读 with open as infile for line in infile 将文件分块读入内存
  • 如何在 robobrowser-python 中发出 POST 请求

    http robobrowser readthedocs org en latest api html http robobrowser readthedocs org en latest api html 我正在尝试使用 APIbrows
  • Python:高精度time.sleep

    你能告诉我如何在 Win32 和 Linux 上的 Python 2 6 中获得高精度睡眠函数吗 您可以在中使用浮点数sleep http docs python org library time html time sleep 该参数可以

随机推荐

  • git 操作命令

    git初始化仓库 git init 配置用户名和邮箱 git config global user name name git config global user email email 将代码储存到 git仓库中 将代码放入暂存区 gi
  • java运行bat命令得到某个windows文件的创建时间

    原文 java运行bat命令得到某个windows文件的创建时间 代码下载地址 http www zuidaima com share 1550463260150784 htm package com zuidaima util impor
  • java每日代码练习——成绩分层代码

    利用条件运算符的嵌套来完成此题 学习成绩 gt 90分的同学用A表示 60 89分之间的用B表示 60分以下的用C表示 代码如下 import java util Scanner public class zhimingyangtuo pu
  • [机器学习与scikit-learn-21]:算法-逻辑回归-多项式非线性回归PolynomialFeatures与代码实现

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 123447272 目录 第1章 sci
  • docker.service启动失败:Unit not found的原因及解决办法

    解决办法 删除 usr lib systemd system docker service的 UNIT 里包含的docker socket 然后systemctl daemon reload 最后systemctl start docker
  • 列表解析

    gt gt gt squared x 2 for x in range 4 gt gt gt for i in squared print i 0 1 4 9 gt gt gt sqdEvens x 2 for x in range 8 i
  • 【Vue.js】全局与局部自定义指令的区别

    示例中介绍了全局自定义指令与局部自定义指令的区别 全局自定义指令 可以在任何实例中应用 局部自定义指令 只能在本身的vue实例中应用 div p 局部自定义指令 p div
  • Windows下JDK安装与环境变量配置

    文章目录 每日一句正能量 前言 安装步骤 配置环境变量 验证环境变量是否配置成功 后记 每日一句正能量 生命 就像一场永无休止的苦役 不要惧怕和拒绝困苦 超越困苦 就是生活的强者 任何经历都是一种累积 累积的越多 人就越成熟 经历的越多 生
  • Java 开发工具类Pager

    import java util ArrayList import java util List 分页工具类 author user public class Pager private static final int DEFAULT P
  • IC卡16个扇区简介

    IC卡 Integrated Circuit Card 集成电路卡 也称智能卡 Smart card 智慧卡 Intelligent card 微电路卡 Microcircuit card 或微芯片卡等 它是将一个微电子芯片嵌入符合ISO
  • 【动态规划】62. 不同路径

    62 不同路径 一个机器人位于一个 m x n 网格的左上角 起始点在下图中标记为 Start 机器人每次只能向下或者向右移动一步 机器人试图达到网格的右下角 在下图中标记为 Finish 问总共有多少条不同的路径 示例 1 输入 m 3
  • Prism 框架

    Prism 框架应用 基础知识篇 Prism 框架概念 prism was the code name for the guidance formally known as the Composite Application Guidanc
  • JSON字符串解析成key-value获取键值对的值

    最近在做日志解析这块 记录一下 转为map 循环得到key value dt VENUS TDS V0700R0200B20150601 level 30 id 152321043 type Alert Log time 146795835
  • db2有MySQL那样的时间戳_Oracle、Db2、SqlServer、MySQL 数据库插入当前系统时间

    做易买网项目 由于对数据库插入系统时间不了解 常常遇到的问题 1 java sql SQLException ORA 01861 文字与格式字符串不匹配 原因 由于获取系统时间类型不对 应为systdate 下面介绍Oracle Db2 S
  • Firefly 问题集锦

    1 当打开Firefly与VS2010报这个错误的时候 显示下面这个错误 解决办法 打开 C Windows System32 drivers etc hosts文件 在文件末尾添加2行 注意 这两行前可能会被杀毒软件添加添加 号 添加后就
  • c# 操作MongoDB

    项目要求 将外部数据同步到mongodb 需要安装mongodb驱动包 MongoDB Driver 此处用到的版本是2 12 3 实现代码 using MongoDB Bson using MongoDB Driver using Sys
  • delete NULL是合法的!

    http bbs csdn net topics 390684584
  • 普通程序员和顶级程序员5个思维模式上的区分!

    细说硅谷普通程序员和顶级程序员5个思维模式上的区分 gineer 是一本很顶尖的书 作者为了这本书 采访了很多硅谷顶级科技公司的顶尖软件工程师 他发现这些给世界带来巨大影响的的工程师们竟然有几个共同点 我感觉大家有必要一起学习一下他们的这些
  • win8网络信息服务器,Win8.1怎么设置DNS服务器地址

    一 首先在Win8 1桌面右下角任务栏的网络图标中 右键鼠标 然后选择 打开网络和共享中心 如下图所示 二 进入Win8 1网络和共享中心后 我们点击已经连接的本地连接或者无线连接网络名称 如下图所示 注 由于笔者目前使用的是无线网络 因此
  • 【Python】猎聘网招聘数据爬虫(Python网络爬虫课设简要)

    Python 猎聘网招聘数据爬虫 Python网络爬虫课设简要 注 本文仅供学习交流使用 合肥学院 20信管 20302211009 项目文件可自行前往博客主页下载或联系作者qq 3416252112 爬取数据耗时约50分钟 1 背景介绍