爬虫实战(三) 用Python爬取拉勾网

article/2025/7/11 5:58:47

0、前言

最近博主面临着选方向的困难(唉,选择困难症患者 >﹏<),所以希望了解一下目前不同岗位的就业前景

这时,就不妨写个小爬虫,爬取一下 拉勾网 的职位数据,并用图形化的方法展示出来,一目了然

整体的 思路 是采用 selenium 模拟浏览器的行为,具体的步骤如下:

  1. 初始化
  2. 爬取数据,这里分为两个部分:一是爬取网页数据,二是进行翻页操作
  3. 保存数据,将数据保存到文件中
  4. 数据可视化

整体的 代码结构 如下:

class Lagou:# 初始化def init(self):pass# 爬取网页数据def parse_page(self):pass# 进行翻页操作def turn_page(self):pass# 爬取数据,调用 parse_page 和 turn_pagedef crawl(self):pass# 保存数据,将数据保存到文件中def save(self):pass# 数据可视化def draw(self):passif __name__ == '__main__':obj = Lagou()obj.init()obj.crawl()obj.save()obj.draw()

好,下面我们一起来看一下整个爬虫过程的详细分析吧!!

1、初始化

在初始化的部分,我们完成的工作需要包括以下四个方面:

  1. 准备全局变量
  2. 启动浏览器
  3. 打开起始 URL
  4. 设置 cookie

(1)准备全局变量

所谓的全局变量,是指在整个爬虫过程中都需要用到的变量,这里我们定义两个全局变量:

  • data:储存爬取下来的数据
  • isEnd:判断爬取是否结束

(2)启动浏览器

启动浏览器的方式大致可以分为两种,一是普通启动,二是无头启动

在普通启动时,整个爬取过程可以可视化,方便调试的时候发现错误

from selenium import webdriver
self.browser = webdriver.Chrome()

而无头启动可以减少渲染时间,加快爬取过程,一般在正式爬取时使用

from selenium import webdriver
opt = webdriver.chrome.options.Options()
opt.set_headless()
self.browser = webdriver.Chrome(chrome_options = opt)

(3)打开起始 URL

首先,我们打开拉勾网的首页(URL:https://www.lagou.com/)

在这里插入图片描述

在输入框中输入【python】进行搜索,可以发现网页跳转到如下的 URL:

https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=

然后,我们再次尝试在输入框中输入【爬虫】进行搜索,网页跳转到如下 URL:

https://www.lagou.com/jobs/list_爬虫?labelWords=&fromSearch=true&suginput=

从中,我们不难发现规律,对 URL 进行泛化后可以得到下面的结果(这个也就是我们的起始 URL):

https://www.lagou.com/jobs/list_{position}?labelWords=&fromSearch=true&suginput=

其中,参数 position 就是我们在输入框中输入的内容(需要进行 URL 编码)

(4)设置 cookie

由于拉勾网对未登录用户的访问数量做了限制,所以在浏览一定数量的网页后,网页会自动跳转登陆界面:

在这里插入图片描述

这时,爬虫就不能正常工作了(当时博主就是在这个地方卡了好久,一直没找出原因)

为了解决上面的问题,我们可以使用 cookie 进行模拟登陆

方便起见,可以直接在浏览器中手动获取 cookie,然后将 cookie 信息添加到 browser 中

(5)初始化部分完整代码

# 初始化
def init(self):# 准备全局变量self.data = list()self.isEnd = False# 启动浏览器、初始化浏览器opt = webdriver.chrome.options.Options()opt.set_headless()self.browser = webdriver.Chrome(chrome_options = opt)self.wait = WebDriverWait(self.browser,10)# 打开起始 URLself.position = input('请输入职位:')self.browser.get('https://www.lagou.com/jobs/list_' + urllib.parse.quote(self.position) + '?labelWords=&fromSearch=true&suginput=')# 设置 cookiecookie = input('请输入cookie:')for item in cookie.split(';'):k,v = item.strip().split('=')self.browser.add_cookie({'name':k,'value':v})

2、爬取数据

在这一部分,我们需要完成以下的两个工作:

  1. 爬取网页数据
  2. 进行翻页操作

(1)爬取网页数据

在起始页面中,包含有我们需要的职位信息(可以使用 xpath 进行匹配):

  • 链接://a[@class="position_link"]

  • 职位://a[@class="position_link"]/h3

  • 城市://a[@class="position_link"]/span/em

  • 月薪、经验与学历://div[@class="p_bot"]/div[@class="li_b_l"]

  • 公司名称://div[@class="company_name"]/a

这里,我们需要使用 try - except - else 异常处理机制去处理异常,以保证程序的健壮性

在这里插入图片描述

在这里插入图片描述

(2)进行翻页操作

我们通过模拟点击【下一页】按钮,进行翻页操作

这里,我们同样需要使用 try - except - else 去处理异常

在这里插入图片描述

(3)爬取数据部分完整代码

# 爬取网页数据
def parse_page(self):try:# 链接link = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//a[@class="position_link"]')))link = [item.get_attribute('href') for item in link]# 职位position = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//a[@class="position_link"]/h3')))position = [item.text for item in position]# 城市city = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//a[@class="position_link"]/span/em')))city = [item.text for item in city]# 月薪、经验与学历ms_we_eb = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//div[@class="p_bot"]/div[@class="li_b_l"]')))monthly_salary = [item.text.split('/')[0].strip().split(' ')[0] for item in ms_we_eb]working_experience = [item.text.split('/')[0].strip().split(' ')[1] for item in ms_we_eb]educational_background = [item.text.split('/')[1].strip() for item in ms_we_eb]# 公司名称company_name = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//div[@class="company_name"]/a')))company_name = [item.text for item in company_name]except TimeoutException:self.isEnd = Trueexcept StaleElementReferenceException:time.sleep(3)self.parse_page()else:temp = list(map(lambda a,b,c,d,e,f,g: {'link':a,'position':b,'city':c,'monthly_salary':d,'working_experience':e,'educational_background':f,'company_name':g}, link, position, city, monthly_salary, working_experience, educational_background, company_name))self.data.extend(temp)# 进行翻页操作
def turn_page(self):try:pager_next = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'pager_next')))except TimeoutException:self.isEnd = Trueelse:pager_next.click()time.sleep(3)# 爬取数据,调用 parse_page 和 turn_page 方法
def crawl(self):count = 0while not self.isEnd :count += 1print('正在爬取第 ' + str(count) + ' 页 ...')self.parse_page()self.turn_page()print('爬取结束')

3、保存数据

接下来,我们将数据储存到 JSON 文件中

# 将数据保存到文件中
def save(self):with open('lagou.json','w',encoding='utf-8') as f:for item in self.data:json.dump(item,f,ensure_ascii=False)

这里,有两个需要注意的地方:

  • 在使用 open() 函数时,需要加上参数 encoding='utf-8'
  • 在使用 dump() 函数时,需要加上参数 ensure_ascii=False

4、数据可视化

数据可视化有利于更直观地展示数据之间的关系,根据爬取的数据,我们可以画出如下 4 个直方图:

  • 工作经验-职位数量
  • 工作经验-平均月薪
  • 学历-职位数量
  • 学历-平均月薪

这里,我们需要用到 matplotlib 库,需要注意一个中文编码的问题,可以使用以下的语句解决:

plt.rcParams['font.sans-serif'] = ['SimHei']

# 数据可视化
def draw(self):count_we = {'经验不限':0,'经验应届毕业生':0,'经验1年以下':0,'经验1-3年':0,'经验3-5年':0,'经验5-10年':0}total_we = {'经验不限':0,'经验应届毕业生':0,'经验1年以下':0,'经验1-3年':0,'经验3-5年':0,'经验5-10年':0}count_eb = {'不限':0,'大专':0,'本科':0,'硕士':0,'博士':0}total_eb = {'不限':0,'大专':0,'本科':0,'硕士':0,'博士':0}for item in self.data:count_we[item['working_experience']] += 1count_eb[item['educational_background']] += 1try:li = [float(temp.replace('k','000')) for temp in item['monthly_salary'].split('-')]total_we[item['working_experience']] += sum(li) / len(li)total_eb[item['educational_background']] += sum(li) / len(li)except:count_we[item['working_experience']] -= 1count_eb[item['educational_background']] -= 1# 解决中文编码问题plt.rcParams['font.sans-serif'] = ['SimHei']# 工作经验-职位数量plt.title(self.position)plt.xlabel('工作经验')plt.ylabel('职位数量')x = ['经验不限','经验应届毕业生','经验1-3年','经验3-5年','经验5-10年']y = [count_we[item] for item in x]plt.bar(x,y)plt.show()# 工作经验-平均月薪plt.title(self.position)plt.xlabel('工作经验')plt.ylabel('平均月薪')x = list()y = list()for item in ['经验不限','经验应届毕业生','经验1-3年','经验3-5年','经验5-10年']:if count_we[item] != 0:x.append(item)y.append(total_we[item]/count_we[item])plt.bar(x,y)plt.show()# 学历-职位数量plt.title(self.position)plt.xlabel('学历')plt.ylabel('职位数量')x = ['不限','大专','本科','硕士','博士']y = [count_eb[item] for item in x]plt.bar(x,y)plt.show()# 学历-平均月薪plt.title(self.position)plt.xlabel('学历')plt.ylabel('平均月薪')x = list()y = list()for item in ['不限','大专','本科','硕士','博士']:if count_eb[item] != 0:x.append(item)y.append(total_eb[item]/count_eb[item])plt.bar(x,y)plt.show()

5、大功告成

(1)完整代码

至此,整个爬虫过程已经分析完毕,完整的代码如下:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.common.exceptions import StaleElementReferenceException
import urllib.parse
import time
import json
import matplotlib.pyplot as pltclass Lagou:# 初始化def init(self):self.data = list()self.isEnd = Falseopt = webdriver.chrome.options.Options()opt.set_headless()self.browser = webdriver.Chrome(chrome_options = opt)self.wait = WebDriverWait(self.browser,10)self.position = input('请输入职位:')self.browser.get('https://www.lagou.com/jobs/list_' + urllib.parse.quote(self.position) + '?labelWords=&fromSearch=true&suginput=')cookie = input('请输入cookie:')for item in cookie.split(';'):k,v = item.strip().split('=')self.browser.add_cookie({'name':k,'value':v})# 爬取网页数据def parse_page(self):try:link = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//a[@class="position_link"]')))link = [item.get_attribute('href') for item in link]position = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//a[@class="position_link"]/h3')))position = [item.text for item in position]city = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//a[@class="position_link"]/span/em')))city = [item.text for item in city]ms_we_eb = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//div[@class="p_bot"]/div[@class="li_b_l"]')))monthly_salary = [item.text.split('/')[0].strip().split(' ')[0] for item in ms_we_eb]working_experience = [item.text.split('/')[0].strip().split(' ')[1] for item in ms_we_eb]educational_background = [item.text.split('/')[1].strip() for item in ms_we_eb]company_name = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//div[@class="company_name"]/a')))company_name = [item.text for item in company_name]except TimeoutException:self.isEnd = Trueexcept StaleElementReferenceException:time.sleep(3)self.parse_page()else:temp = list(map(lambda a,b,c,d,e,f,g: {'link':a,'position':b,'city':c,'monthly_salary':d,'working_experience':e,'educational_background':f,'company_name':g}, link, position, city, monthly_salary, working_experience, educational_background, company_name))self.data.extend(temp)# 进行翻页操作def turn_page(self):try:pager_next = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'pager_next')))except TimeoutException:self.isEnd = Trueelse:pager_next.click()time.sleep(3)# 爬取数据def crawl(self):count = 0while not self.isEnd :count += 1print('正在爬取第 ' + str(count) + ' 页 ...')self.parse_page()self.turn_page()print('爬取结束')# 保存数据def save(self):with open('lagou.json','w',encoding='utf-8') as f:for item in self.data:json.dump(item,f,ensure_ascii=False)# 数据可视化def draw(self):count_we = {'经验不限':0,'经验应届毕业生':0,'经验1年以下':0,'经验1-3年':0,'经验3-5年':0,'经验5-10年':0}total_we = {'经验不限':0,'经验应届毕业生':0,'经验1年以下':0,'经验1-3年':0,'经验3-5年':0,'经验5-10年':0}count_eb = {'不限':0,'大专':0,'本科':0,'硕士':0,'博士':0}total_eb = {'不限':0,'大专':0,'本科':0,'硕士':0,'博士':0}for item in self.data:count_we[item['working_experience']] += 1count_eb[item['educational_background']] += 1try:li = [float(temp.replace('k','000')) for temp in item['monthly_salary'].split('-')]total_we[item['working_experience']] += sum(li) / len(li)total_eb[item['educational_background']] += sum(li) / len(li)except:count_we[item['working_experience']] -= 1count_eb[item['educational_background']] -= 1# 解决中文编码问题plt.rcParams['font.sans-serif'] = ['SimHei']# 工作经验-职位数量plt.title(self.position)plt.xlabel('工作经验')plt.ylabel('职位数量')x = ['经验不限','经验应届毕业生','经验1-3年','经验3-5年','经验5-10年']y = [count_we[item] for item in x]plt.bar(x,y)plt.show()# 工作经验-平均月薪plt.title(self.position)plt.xlabel('工作经验')plt.ylabel('平均月薪')x = list()y = list()for item in ['经验不限','经验应届毕业生','经验1-3年','经验3-5年','经验5-10年']:if count_we[item] != 0:x.append(item)y.append(total_we[item]/count_we[item])plt.bar(x,y)plt.show()# 学历-职位数量plt.title(self.position)plt.xlabel('学历')plt.ylabel('职位数量')x = ['不限','大专','本科','硕士','博士']y = [count_eb[item] for item in x]plt.bar(x,y)plt.show()# 学历-平均月薪plt.title(self.position)plt.xlabel('学历')plt.ylabel('平均月薪')x = list()y = list()for item in ['不限','大专','本科','硕士','博士']:if count_eb[item] != 0:x.append(item)y.append(total_eb[item]/count_eb[item])plt.bar(x,y)plt.show()if __name__ == '__main__':obj = Lagou()obj.init()obj.crawl()obj.save()obj.draw()

(2)运行过程

下面,我们一起来运行代码看看!

在运行代码时,程序会要求输入【职位】和【cookie】,其中,cookie 的获取方法如下:

进入 拉勾网首页,并登陆

在这里插入图片描述

使用快捷键 Ctrl+Shift+IF12 打开开发者工具

在输入框中输入【职位 (这里的示例为 python)】进行搜索,抓包分析,可以看到 cookie 信息就包含在其中

在这里插入图片描述

完整的运行过程如下:

在这里插入图片描述

(3)运行结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


http://chatgpt.dhexx.cn/article/MRp5lKxV.shtml

相关文章

python爬取拉勾网公司信息(您操作太频繁,请稍后访问)

最近爬取拉勾网上的公司信息碰到了很多问题,但是都一一解决了。作为一个招聘网站,他的反爬措施做的还是很好的。 为了调查招聘网站上有多少公司,以及公司信息,并把公司信息存入MongoDB数据库中。 先上运行成功代码: …

2022年爬取拉勾网详情页面地址信息

众所周知,拉勾网的反爬机制一直做的很好,前些年还可以通过找到网页源代码找到岗位详情页面的地址,而现在拉勾网的详情页面地址直接没了,这就很奇怪,那么鼠标点击他又是如何跳转到别的页面 点开源代码中,每一…

django+拉勾网招聘数据可视化

django拉勾网招聘数据可视化,此系统有详细的录屏,下面只是部门截图,需要看完整录屏联系博主 系统开发语言python,框架为django,数据库mysql,分为爬虫和可视化分析

Python爬虫实战:爬取拉勾网并对其进行数据分析

###整体的 思路 是采用 selenium 模拟浏览器的行为,具体的步骤如下: 初始化爬取数据,这里分为两个部分:一是爬取网页数据,二是进行翻页操作保存数据,将数据保存到文件中数据可视化 ###整体的 代码结构 如…

什么你还不知道招聘信息,小唐来教你——最新2021爬取拉勾网招聘信息(二)

文章目录 前言一、准备我们的库二、数据清洗三、核密度图及词云制作四、完整代码五、扩展 上一篇:什么你还不知道招聘信息,小唐来教你——最新2021爬取拉勾网招聘信息(一) 下一篇:没有拉! 前言 既然我们上…

No.4 拉勾网职位搜索信息爬取

一、简介 网址:https://www.lagou.com/jobs/list_/p-city_0?&clfalse&fromSearchtrue&labelWords&suginput 效果:信息 使用框架:requests 难度系数:✩✩✩ 二、教程 今天我们要为我们的工作写爬虫&#xf…

什么你还不知道招聘信息,小唐来教你——最新2021爬取拉勾网招聘信息(一)

文章目录 前言一、准备我们的库二、分析分析三、 代码四、数据展示小唐的心路历程 上一篇:没有啦! 下一篇:什么你还不知道招聘信息,小唐来教你——最新2021爬取拉勾网招聘信息(二) 前言 有是小唐的数据分析…

拉勾网的反爬介绍和解决方法(更新时间:2019/2/20)

拉勾网的反爬介绍和解决方法(更新时间:2019/2/20) 目录直达: 文章目录 拉勾网的反爬介绍和解决方法(更新时间:2019/2/20)1. 前言2. 简述3. 反爬介绍3.1、对于职位的详情页和公司的详情页的反爬…

应对反爬如何爬取拉勾网信息(非常详细)

目录 前期准备请求头Cookies问题手动提取Cookies和自动Cookies相结合自动提取Cookies实现 手动提取Cookies实现 页面分析代码实现 前期准备 我们知道百度其实就是一个爬虫,但是对方的服务器是没有对百度进行反爬的,所以为了防止对方服务器的反爬&#x…

【Python】模拟登陆并抓取拉勾网信息(selenium+phantomjs)

环境 python3.5pip install seleniumphantomjs-2.1.1pip install pyquery 代码 # -*- coding:utf-8 -*-# 防止print中文出错 import time import sys import io sys.stdout io.TextIOWrapper(sys.stdout.buffer, encodinggb18030)from pyquery import PyQuery as pq from se…

Python爬虫实战,requests模块,Python实现拉勾网求职信息数据分析与可视化

前言 利用requests爬取拉勾网求职信息数据分析与可视化,废话不多说。 让我们愉快地开始吧~ 开发工具 **Python版本:**3.6.4 相关模块: requests模块; re模块; os模块 jieba模块; pandas模块 num…

爬虫学习之17:爬取拉勾网网招聘信息(异步加载+Cookie模拟登陆)

很多网站需要通过提交表单来进行登陆或相应的操作,可以用requests库的POST方法,通过观测表单源代码和逆向工程来填写表单获取网页信息。本代码以获取拉勾网Python相关招聘职位为例作为练习。打开拉钩网,F12进入浏览器开发者工具,可…

python成功爬取拉勾网——初识反爬(一个小白真实的爬取路程,内容有点小多)

python成功爬取拉勾网(一个小白的心里路程) 最开始想爬取拉钩是因为半年前上python实验课的时候,老师给了两个任务,一个时爬取糗百的笑话内容,另一个时爬取拉勾网的职位信息,当时因为课时紧张的缘故&#…

爬虫实例二:爬取拉勾网招聘信息

爬虫实例二:爬取拉勾网招聘信息 如果是第一次看本教程的同学,可以先从一开始: 爬虫实例一:爬取豆瓣影评 欢迎关注微信公众号:极简XksA 微信账号:xksnh888 转载请先联系微信号:zs820553471 …

python爬虫之爬取拉勾网

这次要爬取拉勾网,拉勾网的反爬做的还是很不错的啊,因为目标网站是Ajax交互的我一开始是直接分析json接口来爬取的,但是真的很麻烦,请求头一旦出点问题就给识别出来了后续我就改了一下方法用selenium来模拟浏览器去获取 招聘求职…

爬虫练习六:爬取拉勾招聘信息

1. 明确需求 1. 初学爬虫时,看着各路大佬以拉勾网为案例进行爬虫讲解,自己也这样尝试。结果因为个人水平实在太低,很快就触发反爬虫机制,甚至连个人的账号都被封禁。所以这次想要重新挑战一下,爬取拉勾展示的招聘数据。…

用接口登录拉勾网

前段时间一直忙于公司项目的测试工作导致一周多没有撸代码,所以今天通过悠悠是博客学习了一下如何让用接口登录拉勾网 下面介绍一下吧!分享下经验以及心得,,虽然我知道也没什么人会看! 首先呢要先登录拉钩网的网站&am…

拉勾网登录问题

拉钩登录问题,在参考别人的博客后,解决啦 class lagouSpider(CrawlSpider):name lagouallowed_domains [www.lagou.com]start_urls [https://www.lagou.com/]agent "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/" \"537.36 (…

selenium实例登陆拉勾网 外加手动验证验证码

selenium模拟登陆拉钩网 from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import os, json, time from urllib import parse from lxml import etree from fake_…

python -- 拉勾网爬虫模拟登录

入门爬虫一段时间,最近在做一个拉勾网的数据爬虫分析,项目也快接近尾声了,于是抽个时间写一下这个项目中遇到的一些问题。 目前拉勾网的反爬虫机制还是可以的,一开始用scrapy shell 分析拉勾网,发现拉勾网要校验usera…