python爬取boss直聘数据(selenium+xpath)

news2024/11/24 14:43:47

文章目录

  • 一、主要目标
  • 二、开发环境
  • 三、selenium安装和驱动下载
  • 四、主要思路
  • 五、代码展示和说明
    • 1、导入相关库
    • 2、启动浏览器
    • 3、搜索框定位
    • 创建csv文件
    • 招聘页面数据解析(XPATH)
    • 总代码
    • 效果展示
  • 六、总结

一、主要目标

以boss直聘为目标网站,主要目的是爬取下图中的所有信息,并将爬取到的数据进行持久化存储。(可以存储到数据库中或进行数据可视化分析用web网页进行展示,这里我就以csv形式存在了本地)

在这里插入图片描述

二、开发环境

python3.8
pycharm
Firefox

三、selenium安装和驱动下载

环境安装: pip install selenium

版本对照表(火狐的)
https://firefox-source-docs.mozilla.org/testing/geckodriver/Support.html

浏览器驱动下载
https://registry.npmmirror.com/binary.html?path=geckodriver/

火狐浏览器下载
https://ftp.mozilla.org/pub/firefox/releases/

四、主要思路

  1. 利用selenium打开模拟浏览器,访问boss直聘首页(绕过cookie反爬)
  2. 定位搜索按钮输入某职位,点击搜索
  3. 在搜索结果页面,解析出现的职位信息,并保存
  4. 获取多个页面,可以定位跳转至下一页的按钮(但是这个跳转我一直没成功,于是我就将请求url写成了动态的,直接发送一个新的url来代替跳转)

五、代码展示和说明

1、导入相关库

# 用来将爬取到的数据以csv保存到本地
import csv
from time import sleep
# 使用selenium绕过cookie反爬
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.common.by import By
# 使用xpath进行页面数据解析
from lxml import etree

2、启动浏览器

(有界面)

# 传入浏览器的驱动
ser = Service('./geckodriver.exe')
# 实例化一个浏览器对象
bro = webdriver.Firefox(service=ser)
# 设置隐式等待 超时时间设置为20s
bro.implicitly_wait(20)
# 让浏览器发起一个指定url请求
bro.get(urls[0])

(无界面)

# 1. 初始化配置无可视化界面对象
options = webdriver.FirefoxOptions()
# 2. 无界面模式
options.add_argument('-headless')
options.add_argument('--disable-gpu')

# 让selenium规避被检测到的风险
options.add_argument('excludeSwitches')

# 传入浏览器的驱动
ser = Service('./geckodriver.exe')

# 实例化一个浏览器对象
bro = webdriver.Firefox(service=ser, options=options)

# 设置隐式等待 超时时间设置为20s
bro.implicitly_wait(20)

# 让浏览器发起一个指定url请求
bro.get(urls[0])

3、搜索框定位

进入浏览器,按F12进入开发者模式
在这里插入图片描述
然后分析下图可知,搜索框和搜索按钮都有唯一的class值
在这里插入图片描述
然后输入搜索内容,并跳转,代码如下

# 定位搜索框 .ipt-search
search_tag = bro.find_element(By.CSS_SELECTOR, value='.ipt-search')
# 输入搜索内容
search_tag.send_keys("")

# 定位搜索按钮    .代表的是当前标签下的class
btn = bro.find_element(By.CSS_SELECTOR, value='.btn-search')
# 点击搜索按钮
btn.click()

创建csv文件

一开始编码为utf-8,但在本地打开内容是乱码,然后改成utf-8_sig就ok了

# f = open("boos直聘.csv", "w", encoding="utf-8", newline="")
f = open("boos直聘.csv", "w", encoding="utf-8_sig", newline="")
csv.writer(f).writerow(["职位", "位置", "薪资", "联系人", "经验", "公司名", "类型", "职位技能", "福利", "详情页"])

招聘页面数据解析(XPATH)

通过分析可知,招聘数据全在ul标签下的li标签中
在这里插入图片描述
我们要获取的信息有这些,接下来就要进入li标签中,一个一个去分析
在这里插入图片描述
其中职位名称在span标签中,而span标签的class有唯一的值job-name
其它数据分析方式和这个相同
在这里插入图片描述
数据解析代码如下

def parse():
    # 临时存放获取到的信息
    jobList = []
    # 提取信息
    page_text = bro.page_source
    # 将从互联网上获取的源码数据加载到tree对象中
    tree = etree.HTML(page_text)
    job = tree.xpath('//div[@class="search-job-result"]/ul/li')
    for i in job:
        # 职位
        job_name = i.xpath(".//span[@class='job-name']/text()")[0]
        # 位置
        jobArea = i.xpath(".//span[@class='job-area']/text()")[0]
        # 联系人
        linkman_list = i.xpath(".//div[@class='info-public']//text()")
        linkman = "·".join(linkman_list)
        # 详情页url
        detail_url = prefix + i.xpath(".//h3[@class='company-name']/a/@href")[0]
        # print(detail_url)
        # 薪资
        salary = i.xpath(".//span[@class='salary']/text()")[0]
        # 经验
        job_lable_list = i.xpath(".//ul[@class='tag-list']//text()")
        job_lables = " ".join(job_lable_list)
        # 公司名
        company = i.xpath(".//h3[@class='company-name']/a/text()")[0]
        # 公司类型和人数等
        companyScale_list = i.xpath(".//div[@class='company-info']/ul//text()")
        companyScale = " ".join(companyScale_list)
        # 职位技能
        skill_list = i.xpath("./div[2]/ul//text()")
        skills = " ".join(skill_list)
        # 福利 如有全勤奖补贴等
        try:
            job_desc = i.xpath(".//div[@class='info-desc']/text()")[0]
            # print(type(info_desc))
        except:
            job_desc = ""
            # print(type(info_desc))
        # print(job_name, jobArea, salary, linkman, salaryScale, name, componyScale, tags, info_desc)
        # 将数据写入csv
        csv.writer(f).writerow(
            [job_name, jobArea, salary, linkman, job_lables, company, companyScale, skills, job_desc, detail_url])
        # 将数据存入数组中
        jobList.append({
            "jobName": job_name,
            "jobArea": jobArea,
            "salary": salary,
            "linkman": linkman,
            "jobLables": job_lables,
            "company": company,
            "companyScale": companyScale,
            "skills": skills,
            "job_desc": job_desc,
            "detailUrl": detail_url,
        })

    return {"jobList": jobList}

总代码

import csv
from time import sleep
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.common.by import By
from lxml import etree

# 指定url
urls = ['https://www.zhipin.com/', 'https://www.zhipin.com/web/geek/job?query={}&page={}']
prefix = 'https://www.zhipin.com'

# 1. 初始化配置无可视化界面对象
options = webdriver.FirefoxOptions()
# 2. 无界面模式
options.add_argument('-headless')
options.add_argument('--disable-gpu')

# 让selenium规避被检测到的风险
options.add_argument('excludeSwitches')

# 传入浏览器的驱动
ser = Service('./geckodriver.exe')

# 实例化一个浏览器对象
bro = webdriver.Firefox(service=ser, options=options)
# bro = webdriver.Firefox(service=ser

# 设置隐式等待 超时时间设置为20s
# bro.implicitly_wait(20)

# 让浏览器发起一个指定url请求
bro.get(urls[0])

sleep(6)

# 定位搜索框 .ipt-search
search_tag = bro.find_element(By.CSS_SELECTOR, value='.ipt-search')
# 输入搜索内容
search_tag.send_keys("")

# 定位搜索按钮    .代表的是当前标签下的class
btn = bro.find_element(By.CSS_SELECTOR, value='.btn-search')
# 点击搜索按钮
btn.click()
sleep(15)

# f = open("boos直聘.csv", "w", encoding="utf-8", newline="")
f = open("boos直聘.csv", "w", encoding="utf-8_sig", newline="")
csv.writer(f).writerow(["职位", "位置", "薪资", "联系人", "经验", "公司名", "类型", "职位技能", "福利", "详情页"])


def parse():
    # 临时存放获取到的信息
    jobList = []
    # 提取信息
    page_text = bro.page_source
    # 将从互联网上获取的源码数据加载到tree对象中
    tree = etree.HTML(page_text)
    job = tree.xpath('//div[@class="search-job-result"]/ul/li')
    for i in job:
        # 职位
        job_name = i.xpath(".//span[@class='job-name']/text()")[0]
        # 位置
        jobArea = i.xpath(".//span[@class='job-area']/text()")[0]
        # 联系人
        linkman_list = i.xpath(".//div[@class='info-public']//text()")
        linkman = "·".join(linkman_list)
        # 详情页url
        detail_url = prefix + i.xpath(".//h3[@class='company-name']/a/@href")[0]
        # print(detail_url)
        # 薪资
        salary = i.xpath(".//span[@class='salary']/text()")[0]
        # 经验
        job_lable_list = i.xpath(".//ul[@class='tag-list']//text()")
        job_lables = " ".join(job_lable_list)
        # 公司名
        company = i.xpath(".//h3[@class='company-name']/a/text()")[0]
        # 公司类型和人数等
        companyScale_list = i.xpath(".//div[@class='company-info']/ul//text()")
        companyScale = " ".join(companyScale_list)
        # 职位技能
        skill_list = i.xpath("./div[2]/ul//text()")
        skills = " ".join(skill_list)
        # 福利 如有全勤奖补贴等
        try:
            job_desc = i.xpath(".//div[@class='info-desc']/text()")[0]
            # print(type(info_desc))
        except:
            job_desc = ""
            # print(type(info_desc))
        # print(job_name, jobArea, salary, linkman, salaryScale, name, componyScale, tags, info_desc)
        # 将数据写入csv
        csv.writer(f).writerow(
            [job_name, jobArea, salary, linkman, job_lables, company, companyScale, skills, job_desc, detail_url])
        # 将数据存入数组中
        jobList.append({
            "jobName": job_name,
            "jobArea": jobArea,
            "salary": salary,
            "linkman": linkman,
            "jobLables": job_lables,
            "company": company,
            "companyScale": companyScale,
            "skills": skills,
            "job_desc": job_desc,
            "detailUrl": detail_url,
        })

    return {"jobList": jobList}


if __name__ == '__main__':
    # 访问第一页
    jobList = parse()
    query = ""
    # 访问剩下的九页
    for i in range(2, 11):
        print(f"第{i}页")
        url = urls[1].format(query, i)
        bro.get(url)
        sleep(15)

        jobList = parse()

    # 关闭浏览器
    bro.quit()

效果展示

在这里插入图片描述

六、总结

不知道是boss反爬做的太好,还是我个人太菜(哭~)
我个人倾向于第二种
这个爬虫还有很多很多的不足之处,比如在页面加载的时候,boss的页面会多次加载(这里我很是不理解,我明明只访问了一次,但是他能加载好多次),这就导致是不是ip就会被封…
再比如,那个下一页的点击按钮,一直点不了,不知有没有路过的大佬指点一二(呜呜呜~)
在这里插入图片描述

# 下一页标签定位 ui-icon-arrow-right
next_tag = bro.find_element(By.CSS_SELECTOR, value='.ui-icon-arrow-right')
# action = ActionChains(bro)
# # 点击指定的标签
# action.click(next_tag).perform()
# sleep(0.1)
# # 释放动作链
# action.release().perform()

总之boss的信息爬取,我还是无法做到完全自动化😭

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1091877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Candence报错】Discrepancy #i in TASK

问题描述 Candence LVS仿真提示网络不匹配 问题解决 检查原理图和Layout 注意:

穿越功耗墙,我们该从哪些方面提升“性能”?

目录 背景 功耗:CPU 的“人体极限” 并行优化,理解阿姆达尔定律 总结延伸 背景 我们知道 CPU 的性能时,我们提到了这样一个公式: 程序的 CPU 执行时间 指令数CPIClock Cycle Time 这么来看,如果要提升计算机的…

tracy 学习

https://github.com/wolfpld/tracy 适用于游戏和其他应用的实时、纳秒分辨率、远程控制、支持采样和帧率检测 Tracy 支持分析 CPU(为 C、C 和 Lua 集成提供直接支持。同时,互联网上存在许多其他语言的第三方绑定,例如 Rust 、Zig、C # 、 OC…

【git】gitlab安装、备份

gitlab官网 官网:官网 中文官网:中文官网 作为一个英文不好的程序员,所以我都去中文网站去看了。下面也是带着大家去走走 安装gitlab 我不想写具体的安装方法,直接去逛网看下面是我的截图。步骤非常详细。 安装文档地址&…

Apacheb Shiro 1.2.4反序列化漏洞(CVE-2016-4437)

Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437) 1 在线漏洞解读: https://vulhub.org/#/environments/shiro/CVE-2016-4437/2 环境搭建 cd /home/kali/vulhub/shiro/CVE-2016-4437启动: sudo docker-compose up -d # 拉取下载并启动sud…

谢邀,ADconf安全大会

儒道易行 道虽远,行则易至;儒虽难,坚为易成 文笔生疏,措辞浅薄,望各位大佬不吝赐教,万分感谢。 免责声明:由于传播或利用此文所提供的信息、技术或方法而造成的任何直接或间接的后果及损失&am…

Linux:mongodb数据库源码包安装(4.4.25版本)

环境 系统:centos7 本机ip:192.168.254.1 准备的mongodb包 版本 : 4.4.25 全名称:mongodb-linux-x86_64-rhel70-4.4.25.tgz 下载源码包 Download MongoDB Community Server | MongoDBhttps://www.mongodb.com/try/downloa…

02.机器学习原理(复习)

目录 机器学习的本质机器学习的类型Regression/回归Classification/分类Structured Learning/结构化学习 ML的三板斧设定范围设定标准监督学习半监督学习其他 达成目标小结达成目标设定标准设定范围 部分截图来自原课程视频《2023李宏毅最新生成式AI教程》,B站自行搜…

竞赛选题 深度学习OCR中文识别 - opencv python

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习OCR中文识别系统 ** 该项目较为新颖,适合作为竞赛课题方向,…

编译linux的设备树

使用make dtbs命令时 在arch/arm 的目录Makefile文件中有 boot : arch/arm/boot prepare 和scripts是空的 在文件scripts/Kbuild.include中 变量build : -f $(srctree)/scripts/Makefile.build obj 在顶层Makefile中 $(srctree):. 展开后-f ./scripts/Mak…

恢复Windows 11经典右键菜单:一条命令解决显示更多选项问题

恢复Windows 11经典右键菜单:一条命令解决显示更多选项问题 恢复Windows 11经典右键菜单:一条命令解决显示更多选项问题为什么改变?恢复经典右键菜单 我是将军我一直都在,。! 恢复Windows 11经典右键菜单:一…

docker入门加实战—Docker镜像和Dockerfile语法

docker入门加实战—Docker镜像和Dockerfile语法 镜像 镜像就是包含了应用程序、程序运行的系统函数库、运行配置等文件的文件包。构建镜像的过程其实就是把上述文件打包的过程。 镜像结构 我们要从0部署一个Java应用,大概流程是这样: 准备Linux运行环…

CodeForces每日好题10.14

给你一个字符串 让你删除一些字符让它变成一个相邻的字母不相同的字符串,问你最小的删除次数 以及你可以完成的所有方/案数 求方案数往DP 或者 组合数学推公式上面去想,发现一个有意思的事情 例如1001011110 这个字符串你划分成1 00 1 0 1111 0 每…

论文学习——Class-Conditioned Latent Diffusion Model For DCASE 2023

文章目录 引言正文AbstractIntroductionSystem Overview2.1 Latent Diffusion with sound-class-based conditioning以声音类别为条件的潜在扩散模型2.2 Variational Autoencoder and neural vocoder变分自编码器和神经声码器FAD-oriented Postprocessing filter(专…

JOSEF约瑟 HJY-E1A/4D电压继电器 欠电压动作 整定范围10~242V 二转换

系列型号 HJY-E1A/3D数字式交流电压继电器; HJY-E1A/3J数字式交流电压继电器; HJY-E1B/3D数字式交流电压继电器; HJY-E1B/3J数字式交流电压继电器; HJY-E2A/3D数字式交流电压继电器; HJY-E2A/3J数字式交流电压继…

极简的MapReduce实现

目录 1. MapReduce概述 2. 极简MapReduce内存版 3. 复杂MapReduce磁盘版 4. MapReduce思想的总结 1. MapReduce概述 以前写过一篇 MapReduce思想 ,这次再深入一点,简单实现一把单机内存的。MapReduce就是把它理解成高阶函数,需要传入map和…

蓝桥杯每日一题2023.10.14

年号字串 - 蓝桥云课 (lanqiao.cn) 题目描述 我们发现每个字母都与26紧密相关&#xff0c;其%26的位置就是最后一个字母&#xff0c;由于最开始将0做为了1故在写答案时需要注意细节问题 #include<bits/stdc.h> using namespace std; char s[] "ABCDEFGHIJKLMNOPQ…

电源集成INN3270C-H215-TL、INN3278C-H114-TL、INN3278C-H215-TL简化了反激式电源转换器的设计和制造。

一、概述 InnoSwitch™3-CP系列IC极大地简化了反激式电源转换器的设计和制造&#xff0c;特别是那些需要高效率和/或紧凑尺寸的产品。InnoSwitch3-CP系列将初级和次级控制器以及安全额定反馈集成到单个IC中。 InnoSwitch3-CP系列器件集成了多种保护功能&#xff0c;包括线路过…

【git篇】git的使用

文章目录 1. Git介绍与安装1. Git简介2. 下载安装程序3. 设置用户名和邮箱 2. Git的基本使用1. 创建版本库2. 文件管理1. 提交文件2. 查看状态3. 查看提交日志4. 版本回退 3. 原理解析1. Git区的划分2. 撤销修改3. 删除文件 4. 分支管理1. 基本原理2. 创建分支3. 合并分支4. 删…

处理死锁策略2

一、避免死锁-动态策略 1.概述 安全序列-能使每个进程才能顺利完成的分配资源的序列&#xff0c;可有多种&#xff0c;此时系统处于安全状态下&#xff0c;系统一定不会发生死锁。 不安全状态-找不到一个安全序列时&#xff0c;系统处于不安全状态下&#xff0c;系统可能会发…