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

python爬取boss直聘数据(selenium+xpath),第1张

一、主要目标

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

python爬取boss直聘数据(selenium+xpath),在这里插入图片描述,第2张

二、开发环境

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进入开发者模式
python爬取boss直聘数据(selenium+xpath),在这里插入图片描述,第3张
然后分析下图可知,搜索框和搜索按钮都有唯一的class值
python爬取boss直聘数据(selenium+xpath),在这里插入图片描述,第4张
然后输入搜索内容,并跳转,代码如下

# 定位搜索框 .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标签中
python爬取boss直聘数据(selenium+xpath),在这里插入图片描述,第5张
我们要获取的信息有这些,接下来就要进入li标签中,一个一个去分析
python爬取boss直聘数据(selenium+xpath),在这里插入图片描述,第6张
其中职位名称在span标签中,而span标签的class有唯一的值job-name
其它数据分析方式和这个相同
python爬取boss直聘数据(selenium+xpath),在这里插入图片描述,第7张
数据解析代码如下

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()

效果展示

python爬取boss直聘数据(selenium+xpath),在这里插入图片描述,第8张

六、总结

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

# 下一页标签定位 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.outofmemory.cn/yw/13518433.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024-01-22
下一篇 2024-01-27

发表评论

登录后才能评论

评论列表(0条)

保存