2024年用scrapy爬取BOSS直聘的操作

SCrapy框架实现对BOSS直聘的爬取

文章目录

  • SCrapy框架实现对BOSS直聘的爬取
    • 对SCrapy框架的一个简单认识
      • Scrapy 组件的作用
      • Scrapy 数据流
    • 1. 测试反爬
    • 2. 定义一个下载中间件类,截取spiders的请求(中间件直接截取请求,并且返回给Spider进行数据解析)
    • 数据解析操作

对SCrapy框架的一个简单认识

在这里插入图片描述

Scrapy 组件的作用

  1. Engine(引擎):负责控制系统所有组件之间的数据流,并在发生某些操作时触发事件。它是整个爬虫的核心。

  2. Scheduler(调度器):接收引擎的请求,对请求去重并放入队列中。当引擎请求新的请求时,将队列中的请求按顺序返回给引擎。

  3. Downloader(下载器):负责获取网页数据并将其返回给引擎,引擎再将数据传给 Spiders(爬虫)。

  4. Spiders(爬虫):解析响应,从中提取出 Items(项目)和新的 Requests(请求)。

  5. Item Pipeline(项目管道):处理爬虫提取的项目,包括清理、验证和存储项目。

  6. Downloader middlewares(下载器中间件):处理从引擎到下载器的请求和从下载器到引擎的响应,用于在这些过程中修改或替换请求和响应。

  7. Spider middlewares(爬虫中间件):处理爬虫的输入(响应)和输出(项目和请求),可以对这些数据进行修改、添加或删除。

Scrapy 数据流

  1. 初始请求

    • Scrapy 会实例化一个 Crawler 对象,在该对象中创建 Spider 对象和 Engine 对象。
    • 通过 Engine 对象打开 Spider,并生成第一个 request(请求)。
  2. 请求处理流程

    • 步骤 1:Engine 从 Spiders 获取初始请求。
    • 步骤 2:Engine 把请求给调度器,并询问下一次请求。
    • 步骤 3:Scheduler 对 URL 去重,放到队列中等待,并把下一个 request 返回给 Engine。
    • 步骤 4:Engine 把从调度器返回的 request 经过下载中间件交给下载器。
    • 步骤 5:Downloader 下载页面后生成一个 Response(响应),并通过下载器中间件将其发送到 Engine。
    • 步骤 6:Engine 接收响应,并通过爬虫中间件将其发送到爬虫进行处理。
    • 步骤 7:爬虫接收到响应,解析处理响应,提取出 Items 和 新的 Requests,再通过爬虫中间件提交给 Engine。
    • 步骤 8:Engine 把接收到的 Items 提交给 Item Pipeline,把接收到的 Requests 提交给调度器。
  3. 重复过程

    • 重复上述步骤,直到 Scheduler 中没有请求为止。

拿到一个网站爬取需求首先需要进行分析网站的反爬措施,再根据反爬漏洞想到对应的解决方法

1. 测试反爬

import time
from random import randint, choice
import requestsurl = 'https://ja.58.com/job.shtml?utm_source=sem-baidu-pc&spm=u-2few7p4vh988mb62t1.2few8w827wgt4eurg.kd_201345177084.cr_43861026238.ac_20304970.cd_11302497077865040299'user_agents = ['Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.0.0','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36 Edg/100.0.0.0'
]headers = {'User-Agent': choice(user_agents)
}response = requests.get(url=url, headers=headers)with open('test.html', 'w', encoding='utf-8') as f:f.write(response.text)# 随机延时 1 到 5 秒
time.sleep(randint(1, 5))

在这里插入图片描述

可知直接爬取会被屏蔽,但是正常打开没有问题

在这里插入图片描述

因此想到用来selenium库来进行打开操作同时获取cookie保存

 def getcookie(self, url, cookies):driver = webdriver.Chrome()driver.get(url)time.sleep(6)dict_cookies = driver.get_cookies()json_cookies = json.dumps(dict_cookies)with open(cookies, "w") as fp:fp.write(json_cookies)print('Cookies保存成功!')driver.quit()
def load_cookies(self):with open(self.cookie_file, "r") as fp:cookies = json.load(fp)for cookie in cookies:if 'domain' in cookie:del cookie['domain']self.driver.add_cookie(cookie)

2. 定义一个下载中间件类,截取spiders的请求(中间件直接截取请求,并且返回给Spider进行数据解析)

class SeleniumMiddleware:query = ""city_id = ""def __init__(self):self.cookie_file = 'boss_cookies.json'# 检查文件是否存在,如果不存在则创建一个空文件if not os.path.exists(self.cookie_file):with open(self.cookie_file, 'w') as f:passself.getcookie('https://www.zhipin.com/web/geek/job-recommend', self.cookie_file)self.driver = webdriver.Chrome()def getcookie(self, url, cookies):#此处省略def load_cookies(self):#此处省略def process_request(self, request, spider):try:if request.meta.get('first_request', True):qe = input('请搜索岗位和城市id(空格隔开):').split(' ')self.query = qe[0]self.city_id = qe[1]target_url = f"https://www.zhipin.com/web/geek/job?query={self.query}&city={self.city_id}&page=1"q: str = self.queryc = self.city_idrequest.meta['first_request'] = Falseelse:page = int(request.meta.get('page_number'))target_url = f"https://www.zhipin.com/web/geek/job?query={self.query}&city={self.city_id}&page={page}"print(f"Fetching URL: {target_url}")self.driver.get(target_url)self.load_cookies()self.driver.refresh()WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, "job-card-wrapper")))data = self.driver.page_sourcereturn HtmlResponse(url=request.url, body=data, encoding='utf-8', request=request)except Exception as e:print(f"An error occurred: {e}")return HtmlResponse(url=request.url, status=500, request=request)def __del__(self):if self.driver:self.driver.quit()

请求代码

  WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, "job-card-wrapper")))

因为boss直聘具有反爬操作,很多时候能够检测出来不是正常用户,需要用该方法反复进行请求操作直到html页面中能够获取我们想要的标签内容(这个标签下的很多数据都是我们需要进行爬取操作的数据)

数据解析操作

使用Xpath来进行,同时对空数据进行处理

import scrapy
from ..items import BossItemclass BossSpider(scrapy.Spider):name = "boss"allowed_domains = ["www.zhipin.com"]start_urls = ["https://www.zhipin.com/"]page = 1def parse(self, response):with open('test.html', 'w', encoding='utf-8') as f:f.write(response.text)# 改进的XPath表达式li_list = response.xpath('//li[@class="job-card-wrapper"]')print(f"Number of items found: {len(li_list)}===============================================")for li in li_list:title = li.xpath(".//span[@class='job-name']/text()").extract_first() or ''salary = li.xpath(".//span[@class='salary']/text()").extract_first() or ''area = li.xpath(".//span[@class='job-area']/text()").extract_first() or ''# 确保提取job_lable_list的正确性job_lable_list = li.xpath(".//ul[@class='tag-list']//text()").extract()if len(job_lable_list) >= 2:experience = job_lable_list[0] or ''education = job_lable_list[1] or ''else:experience = ''education = ''company = li.xpath(".//h3[@class='company-name']/a/text()").extract_first() or ''# 确保提取company_message的正确性company_message = li.xpath(".//ul[@class='company-tag-list']//text()").extract()company_type = company_message[0] if company_message else ''# 提取boon字段boon = li.xpath('.//div[@class="job_card_footer"]//div[@class="info-desc"]/text()').extract()boon = boon[0] if boon else None# 技能skill_list = li.xpath(".//div[@class='job-card-footer clearfix']//ul[@class='tag-list']/li/text()").extract() or []skill = "|".join(skill_list)# 创建BossItem对象并传递数据book = BossItem(title=title,address=area,salary=salary,experience=experience,education=education,company=company,companyType=company_type,skill_list=skill,)yield bookif self.page < 10:self.page += 1next_url = f"https://www.zhipin.com/web/geek/job?query=java&city=101210100&page={self.page}"yield scrapy.Request(url=next_url,callback=self.parse,meta={'page_number': self.page, 'first_request': False})

spider/boss.py中代码的注意事项

        if self.page < 10:self.page += 1next_url = f"https://www.zhipin.com/web/geek/job?query=java&city=101210100&page={self.page}"yield scrapy.Request(url=next_url,callback=self.parse,meta={'page_number': self.page, 'first_request': False})

注意:此代码next_url传过去不会真正的被下载器中间件处理,而是为了防止不报错而进行的(不知道哪错了)

中间件部分代码

 if request.meta.get('first_request', True):qe = input('请搜索岗位和城市id(空格隔开):').split(' ')self.query = qe[0]self.city_id = qe[1]target_url = f"https://www.zhipin.com/web/geek/job?query={self.query}&city={self.city_id}&page=1"q: str = self.queryc = self.city_idrequest.meta['first_request'] = Falseelse:page = int(request.meta.get('page_number'))target_url = f"https://www.zhipin.com/web/geek/job?query={self.query}&city={self.city_id}&page={page}"

由于csdn下载代码需要开启vip具体代码实现可以访问我的github:

2240774934/Crawler_instances: 最新BOSS直聘爬取以及其他常见网站爬取 (github.com)

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

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

相关文章

甲流疫情死亡率【菜蛋题解】

描述 甲流并不可怕&#xff0c;在中国&#xff0c;它的死亡率并不是很高。请根据截止2009年12月22日各省报告的甲流确诊数和死亡数&#xff0c;计算甲流在各省的死亡率。 输入描述 输入仅一行&#xff0c;有两个整数&#xff0c;第一个为确诊数&#xff0c;第二个为死亡数。…

Kubernetes云原生存储解决方案openebs部署实践-3.10.0版本(helm部署)

Kubernetes云原生存储解决方案openebs部署实践-3.10.0版本&#xff08;helm部署&#xff09; 记录在k8s 1.19.0集群环境下安装openebs 3.10.0。 环境信息如下&#xff1a; [rootk8s-master ~]# cat /etc/centos-release CentOS Linux release 7.9.2009 (Core) [rootk8s-mast…

【最新鸿蒙应用开发】——用户信息封装

用户管理工具封装 1. 为什么要封装 在进行如下登录功能时&#xff0c; 通常需要将一些用户信息以及token进行持久化保存&#xff0c;以方便下次进行数据请求时携带这些用户信息来进行访问后端数据。下面分享一下鸿蒙当中实用的持久化封装操作。 2. 步骤 封装用户信息管理工具…

Docker系列-Docker镜像分层原理

Docker镜像的分层原理是其实现高效、灵活和可复用性的关键。以下是对Docker镜像分层原理的详细说明&#xff1a; 一、基本概念 Docker镜像是一种轻量级、可执行的独立软件包&#xff0c;它包含运行某个软件所需要的所有内容&#xff0c;如代码、运行时库、环境变量和配置文件…

Mybatis Plus 自动填充注解 @TableField(fill = FieldFill.INSERT_UPDATE)

第一步&#xff1a;在需要自动填充的位置加上注解 通过在创建时间和修改时间上添加 fill 填充字段 进行自动填充 第二步&#xff1a;要想实现自动填充还需要实现MetaObjectHandler接口&#xff0c;在这里实现自动填充的逻辑 Component public class MyMetaObjectHandler …

tinyshop项目部署

参考软件测试之测试用例设计&#xff08;四&#xff09;_管理后台 测试用例-CSDN博客 1、下载xampp 2、修改apache和mysql的端口分别为4431 &#xff0c;8013和3306 3、访问页面&#xff1a;输入ip:端口号&#xff0c;出现以下页面即成功 4、安装tinyshop商城 将解压的tinys…

动态住宅代理IP详细解析

在大数据时代的背景下&#xff0c;代理IP成为了很多企业顺利开展的重要工具。代理IP地址可以分为住宅代理IP地址和数据中心代理IP地址。选择住宅代理IP的好处是可以实现真正的高匿名性&#xff0c;而使用数据中心代理IP可能会暴露自己使用代理的情况。 住宅代理IP是指互联网服务…

Transformation(转换)开发-switch/case组件

一、switch/case组件-条件判断 体育老师要做一件非常重要的事情&#xff1a;判断学生是男孩还是女孩、或者是蜘蛛&#xff0c;然后让他们各自到指定的队伍中 体育老师做的事情&#xff0c;我们同样也会在Kettle中会经常用来。在Kettle中&#xff0c;switch/case组件可以来做类似…

Java 中的字符串替换方法详解:replace, replaceAll 和 replaceFirst

在Java中&#xff0c;字符串的替换是一种常见的操作&#xff0c;特别是在处理文本和格式化输出时。Java提供了几种不同的方法来实现字符串替换&#xff0c;其中包括 replace, replaceAll 和 replaceFirst。本文将详细讨论这些方法的用法、区别以及示例。 1. replace(CharSeque…

被裁了(9年)

那年&#xff08;2015年&#xff09;我刚毕业有一年多&#xff08;20出头&#xff09;&#xff0c;阴差阳错来到了现在的单位。 那时互联网腾起&#xff0c;单位也迅速发展&#xff0c;部门从起初的不到30号人发展到500人&#xff1b;A轮、B轮.....D轮&#xff0c;一轮轮的融资…

【等保2.0的内容有哪些?】

“在“等保2.0”的基础上&#xff0c;分别增加了云计算安全、移动互联安全、物联网安全、工控系统安全、大数据安全5个拓展需求。 《中华人民共和国刑法》第253条&#xff0c;非法将公民个人资料卖给他人&#xff0c;并处罚金。 违反国家相关法律法规&#xff0c;将其在执行公…

vue2使用use注册自定义指令实现输入控制与快捷复制

使用场景 在一些form表单填写内容的时候&#xff0c;要限制输入的内容必须是数值、浮点型&#xff0c;本来el-input-number就可以实现&#xff0c;但是它本身带那个数值控制操作&#xff0c;等一系列感觉不舒服的地方。如果只是使用el-input该多好&#xff0c;只要监听一下输入…

实习总结 --- 资源位业务

测试范围 测试风险 端风险与服务端风险 — 预防措施&#xff1a;注重埋点规范、使用自动化提效、进行配置检查、做好监控建设。 资源位投放方式 方式一&#xff1a;通过麦哲伦平台投放&#xff0c;麦哲伦1.0和2.0均在使用中 方式二&#xff1a;组件化的方式投放。组件化是指…

如何理解康威定律在软件开发中的应用?

康威定律&#xff08;Conways Law&#xff09;在软件开发中的应用&#xff0c;可以帮助我们理解和优化软件系统的架构&#xff0c;同时也可以指导我们如何组织和管理开发团队。以下是对康威定律在软件开发中的具体应用和理解&#xff1a; 1. 系统架构与组织结构匹配 康威定律…

pycharm无法添加python解释器的解决方法

出现该错误的原因是先前创建过重名的解释器&#xff08;虚拟环境&#xff09;&#xff0c;在pycharm配置中没有完全删除干净。解决方法如下&#xff1a; 首先在文件->设置界面&#xff0c;找到解释器设置。 然后先按图所示点击全部显示虚拟环境&#xff1a; 接着将无法添…

JavaScript 中的 CustomEvent

在 JavaScript 中&#xff0c;CustomEvent 是一种可以让开发者自定义事件的机制。它允许你定义一个具有自定义名称和数据的事件&#xff0c;并将其分发到文档中的任何元素上。这在某些情况下比使用原生事件更为灵活和便捷。 创建 CustomEvent 要创建一个 CustomEvent&#xf…

如何快速掌握一门编程语言

学习一门新的编程语言可能是一个具有挑战性的过程&#xff0c;但通过一些系统的方法&#xff0c;可以大大加快这个过程。 目录 第一步&#xff1a;通过书籍和视频课程掌握基本语法1. **学习编程语言的基础知识**2. **掌握字符串处理**3. **掌握正则表达式和解析器**4. **掌握面…

大数据开发如何快速进阶

目录 1. 个人经验与心得分享1.1 试错的价值与机会把握1.2 投入产出比的考量1.3 刻意练习与技能提升1.4 目标设定与职业规划1.5 自我驱动与成长1.6 第一性原理的应用 2. 大数据开发领域的挑战与机遇2.1 技术革新的挑战2.2 数据治理的难题2.3 人才短缺的问题2.4 投入产出比的考量…

Android InputStage事件处理流程

InputStage事件处理流程 对于java层的按键分发从ViewRootImpl.java的WindowInputEventReceiver中的onInputEvent开始&#xff0c;InputStage将输入事件的处理分成若干个阶段&#xff08;Stage&#xff09;, 如果当前有输入法窗口&#xff0c;则事件处理从 NativePreImeInputSt…

权限类漏洞解析——功能权限篇

上一篇【一文理解权限类漏洞产生的原因之未授权篇】有讲过未授权漏洞产生的原因&#xff0c;但是在我实际的挖洞过程中&#xff0c;其实遇见很少&#xff0c;我有印象的好像只有几个非核心站点的中危。 但是对于另一类权限漏洞&#xff0c;功能及数据权限相关的漏洞就不一样了…