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

文章目录

  • 一、主要目标
  • 二、开发环境
  • 三、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)# 详情页urldetail_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)# 将数据写入csvcsv.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)# 详情页urldetail_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)# 将数据写入csvcsv.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.mzph.cn/news/104667.shtml

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

相关文章

软件TFN 2K的分布式拒绝攻击(DDos)实战详解

写在前头 本人写这篇博客的目的,并不是我想成为黑客或者鼓励大家做损坏任何人安全和利益的事情。因科研需要,我学习软件TFN 2K的分布式拒绝攻击,只是分享自己的学习过程和经历,有助于大家更好的关注到网络安全及网络维护上。 需要…

JavaScript(CSS)动画引擎汇总

汇总记录前端实现动画相关的库 1、animejs animejs是一个轻量级的JavaScript动画库,具有简单但功能强大的API。 它适用于CSS属性,SVG,DOM属性和JavaScript对象。 官网anime.js • JavaScript animation engine anime.js - a Collection by…

小华HC32F448串口使用

目录 1. 串口GPIO配置 2. 串口波特率配置 3. 串口接收超时配置 4. 串口中断注册 5. 串口初始化 6. 串口数据接收处理 7. DMA接收配置和处理 1. 串口GPIO配置 端口号和Pin脚号跟STM32没什么区别。 串口复用功能跟STM32大不一样。 如下图,选自HC32F448 表 2…

CodeForces每日好题10.14

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

超低延时 TCP/UDP IP核

实现以太网协议集当中的ARP、ICMP、UDP以及TCP协议 一、概述 TCP_IP核是公司自主开发的使用FPGA逻辑搭建的用于10G以太网通信IP。该IP能够实现以太网协议集当中的ARP、ICMP、UDP以及TCP协议。支持连接10G/25G以太网PHY,组成高速网络通信系统。该IP上传、下传数据B…

极简的MapReduce实现

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

【Candence报错】Discrepancy #i in TASK

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

css 星星闪烁加载框

今天带来的是普灵普灵的loader闪烁加载框 效果如下 开源精神给我们带来了源码 ,源码如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

SpringMVC的请求处理

请求映射路径的配置 请求映射路径的配置主要是通过RequestMapping注解实现的 相关注解作用使用位置RequestMapping设置控制器方法访问路径的资源&#xff0c;可以接收任何请求方法和类上GetMapping设置控制器方法访问路径的资源&#xff0c;可接收GET请求方法和类上PostMappin…

Step 1 搭建一个简单的渲染框架

Step 1 搭建一个简单的渲染框架 万事开头难。从萌生到自己到处看源码手抄一个mini engine出来的想法&#xff0c;到真正敲键盘去抄&#xff0c;转眼过去了很久的时间。这次大概的确是抱着认真的想法&#xff0c;打开VS从零开始抄代码。不知道能坚持多久呢。。。 本次的主题是搭…

idea(添加jsp文件模板)

初始jsp模板代码&#xff1a; <%-- Created by IntelliJ IDEA. User: ${USER} Date: ${DATE} Time: ${TIME} To change this template use File | Settings | File Templates. --%> <% page contentType"text/html;charsetUTF-8" language&q…

局域网上IP多播与IP单播关于MAC地址的区别

IP单播进行到局域网上的时候&#xff1a; 网际层使用IP地址进行寻址&#xff0c;各路由器收到IP数据报后&#xff0c;根据其首部中的目的IP地址的网络号部分&#xff0c;基于路由表进行查表转发。 查表转发的结果可指明IP数据报的下一跳路由器的IP地址&#xff0c;但无法指明…

SpringCloud小项目——订单积分商城 使用Nacos、Open Feign、Gateway、Sentinel技术栈

目录 引出小项目要求创建极简数据库表订单表&#xff0c;订单明细表商品表积分表 相关微服务积分微服务产品微服务订单微服务调用积分和订单微服务 网关微服务登陆认证通过网关实现对外提供接口API走网关功能 sentinel相关使用Sentinel限流&#xff0c;流量整形Sentinel降级服务…

Python正则表达式

正则表达式 当处理文本数据时&#xff0c;正则表达式是一种强大的工具&#xff0c;它允许我们根据特定的模式来匹配、搜索和处理字符串。 正则表达式由一系列字符和特殊字符组成&#xff0c;用于描述文本模式。这些模式可以包含普通字符&#xff08;如字母、数字和标点符号&a…

kafka 开启认证授权

前言 1、前面自己写了一篇关于各个环境各个模式的安装的文章&#xff0c;大家可以去看看 kafka各种环境安装(window,linux,docker,k8s),包含KRaft模式 2、使用版本 kafka_2.13-3.4.1 3、kafka验证方式&#xff0c;有两大类如下&#xff0c;文档内容在 kafka官方文档的 第七节…

蓝桥杯每日一题2023.10.14

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

编译linux的设备树

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

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

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

论文学习——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&#xff08;专…

数据中心机房供电配电及能效管理系统设计

安科瑞虞佳豪壹捌柒陆壹伍玖玖零玖叁 摘要&#xff1a;现代的数据中心中都包括大量的计算机&#xff0c;对于这种场所的电力供应&#xff0c;都要求供电系统需要在所有的时间都有效&#xff0c;这就不同于一般建筑的供配电系统&#xff0c;它是一个交叉的系统&#xff0c;涉及…