全国免费咨询:

13245491521

VR图标白色 VR图标黑色
X

中高端软件定制开发服务商

与我们取得联系

13245491521     13245491521

2024-07-11_「转」写个爬虫,爬取 Boss 直聘全部前端岗位

您的位置:首页 >> 新闻 >> 行业资讯

写个爬虫,爬取 Boss 直聘全部前端岗位 我们在找工作的时候,都会用 boss 直聘、拉钩之类的 APP 投简历。 根据职位描述筛选出适合自己的来投。 此外,职位描述也是我们简历优化的方向,甚至是平时学习的方向。 所以我觉得招聘网站的职位描述还是挺有价值的,就想把它们都爬取下来存到数据库里。 今天我们一起来实现下。 爬取数据我们使用 Puppeteer 来做,然后用 TypeORM 把爬到的数据存到 mysql 表里。 创建个项目: mkdir jd-spider cd jd-spider npm init -y 进入项目,安装 puppeteer: npm install --save puppeteer 我们要爬取的是 boss 直聘的网站数据。 首先,进入搜索页面,选择全国范围,搜索前端: 然后职位列表的每个点进去查看描述,把这个岗位的信息和描述抓取下来: 创建 test.js importpuppeteerfrom'puppeteer'; constbrowser=awaitpuppeteer.launch({ headless:false, defaultViewport:{ width:0, height:0 } }); constpage=awaitbrowser.newPage(); awaitpage.goto('https://www.zhipin.com/web/geek/job'); awaitpage.waitForSelector('.job-list-box'); awaitpage.click('.city-label',{ delay:500 }); awaitpage.click('.city-list-hotli:first-child',{ delay:500 }); awaitpage.focus('.search-input-boxinput'); awaitpage.keyboard.type('前端',{ delay:200 }); awaitpage.click('.search-btn',{ delay:1000 }); 调用 launch 跑一个浏览器实例,指定 headless 为 false 也就是有界面。 defaultView 设置 width、height 为 0 是网页内容充满整个窗口。 然后就是自动化的流程了: 首先进入职位搜索页面,等 job-list-box 这个元素出现之后,也就是列表加载完成了。 就点击城市选择按钮,选择全国。 然后在输入框输入前端,点击搜索。 然后跑一下。 跑之前在 package.json 设置 type 为 module,也就是支持 es module 的 import: node ./test.js 它会自动打开一个浏览器窗口: 然后执行自动化脚本: 这样,下面的列表数据就是可以抓取的了。 不过这里其实没必要这么麻烦,因为只要你 url 里带了 city 和 query 的参数,会自动设置为搜索参数: 所以直接打开这个 url 就可以: importpuppeteerfrom'puppeteer'; constbrowser=awaitpuppeteer.launch({ headless:false, defaultViewport:{ width:0, height:0 } }); constpage=awaitbrowser.newPage(); awaitpage.goto('https://www.zhipin.com/web/geek/job?query=前端&city=100010000'); awaitpage.waitForSelector('.job-list-box'); 然后我们要拿到页数,用来访问列表的每页数据。 怎么拿到页数呢? 其实就是拿 options-pages 的倒数第二个 a 标签的内容: importpuppeteerfrom'puppeteer'; constbrowser=awaitpuppeteer.launch({ headless:false, defaultViewport:{ width:0, height:0 } }); constpage=awaitbrowser.newPage(); awaitpage.goto('https://www.zhipin.com/web/geek/job?query=前端&city=100010000'); awaitpage.waitForSelector('.job-list-box'); constres=awaitpage.$eval('.options-pagesa:nth-last-child(2)',el={ returnparseInt(el.textContent) }); console.log(res); $eval 第一个参数是选择器,第二个参数是对选择出的元素做一些处理后返回。 跑一下: 页数没问题。 然后接下来就是访问每页的列表数据了。 就是在 url 后再带一个 page 的参数: 然后,我们遍历访问每页数据,拿到每个职位的信息: importpuppeteerfrom'puppeteer'; constbrowser=awaitpuppeteer.launch({ headless:false, defaultViewport:{ width:0, height:0 } }); constpage=awaitbrowser.newPage(); awaitpage.goto('https://www.zhipin.com/web/geek/job?query=前端&city=100010000'); awaitpage.waitForSelector('.job-list-box'); consttotalPage=awaitpage.$eval('.options-pagesa:nth-last-child(2)',e={ returnparseInt(e.textContent) }); constallJobs= for(leti=1;i=totalPage;i++){ awaitpage.goto('https://www.zhipin.com/web/geek/job?query=前端&city=100010000&page='+ awaitpage.waitForSelector('.job-list-box'); constjobs=awaitpage.$eval('.job-list-box',el={ return[...el.querySelectorAll('.job-card-wrapper')].map(item={ return{ job:{ name:item.querySelector('.job-name').textContent, area:item.querySelector('.job-area').textContent, salary:item.querySelector('.salary').textContent }, link:item.querySelector('a').href, company:{ name:item.querySelector('.company-name').textContent, } } }) allJobs.push(...jobs); } console.log(allJobs); 具体的信息都是从 dom 去拿的: 跑一下试试: 可以看到,它会依次打开每一页,然后把职位数据爬取下来。 做到这一步还不够,我们要点进去这个链接,拿到 jd 的描述。 for(leti=0;iallJobs.length;i++){ awaitpage.goto(allJobs[i].link); try{ awaitpage.waitForSelector('.job-sec-text'); constjd=awaitpage.$eval('.job-sec-text',el={ returnel.textContent allJobs[i].desc= console.log(allJobs[i]); }catch(e){} } try catch 是因为有的页面可能打开会超时导致中止,这种就直接跳过好了。 跑一下: 它同样会自动打开每个岗位详情页,拿到职位描述的内容,并打印在控制台。 接下来只要把这些存入数据库就好了。 我们新建个 nest 项目: npm install -g @nestjs/cli nest new boss-jd-spider 用 docker 把 mysql 跑起来: 从 docker 官网下载 docker desktop,这个是 docker 的桌面端: 跑起来后,搜索 mysql 镜像(这步需要科学上网),点击 run: 输入容器名、端口映射、以及挂载的数据卷,还要指定一个环境变量: 端口映射就是把宿主机的 3306 端口映射到容器里的 3306 端口,这样就可以在宿主机访问了。 数据卷挂载就是把宿主机的某个目录映射到容器里的 /var/lib/mysql 目录,这样数据是保存在本地的,不会丢失。 而 MYSQL_ROOT_PASSWORD 的密码则是 mysql 连接时候的密码。 跑起来后,我们用 GUI 客户端连上,这里我们用的是 mysql workbench,这是 mysql 官方提供的免费客户端: 连接上之后,点击创建 database: 指定名字、字符集为 utf8mb4,然后点击右下角的 apply。 创建成功之后在左侧就可以看到这个 database 了: 当然,现在还没有表。 我们在 Nest 里用 TypeORM 连接 mysql。 安装用到的包: npm install --save @nestjs/typeorm typeorm mysql2 mysql2 是数据库驱动,typeorm 是我们用的 orm 框架,而 @nestjs/tyeporm 是 nest 集成 typeorm 用的。 在 AppModule 里引入 TypeORM,指定数据库连接配置: TypeOrmModule.forRoot({ type:"mysql", host:"localhost", port:3306, username:"root", password:"guang", database:"boss-spider", synchronize:true, logging:true, entities:[], poolSize:10, connectorPackage:'mysql2', extra:{ authPlugin:'sha256_password', } }), 然后创建个 entity: src/entities/Job.ts import{Column,Entity,PrimaryGeneratedColumn}from"typeorm"; @Entity() exportclassJob{ @PrimaryGeneratedColumn() id:number; @Column({ length:30, comment:'职位名称' }) name:string; @Column({ length:20, comment:'区域' }) area:string; @Column({ length:10, comment:'薪资范围' }) salary:string; @Column({ length:600, comment:'详情页链接' }) link:string; @Column({ length:30, comment:'公司名' }) company:string; @Column({ type:'text', comment:'职位描述' }) desc:string; } 链接可能很长,所以设置为 600,而职位描述就更长了,直接设置 text 就行,它可以存储大段文本。 在 AppModule 引入: 把服务跑起来: npm run start:dev TypeORM会自动建表: 然后我们加个启动爬虫的接口: @Get('start-spider') startSpider(){ this.appService.startSpider(); return'爬虫已启动'; } 安装 puppeteer: npm install --save puppeteer 在 AppService 里实现 startSpider: import{Injectable}from'@nestjs/common'; importpuppeteerfrom'puppeteer'; @Injectable() exportclassAppService{ getHello():string{ return'HelloWorld!'; } asyncstartSpider(){ constbrowser=awaitpuppeteer.launch({ headless:false , defaultViewport:{ width:0, height:0 } constpage=awaitbrowser.newPage(); awaitpage.goto('https://www.zhipin.com/web/geek/job?query=前端&city=100010000'); awaitpage.waitForSelector('.job-list-box'); consttotalPage=awaitpage.$eval('.options-pagesa:nth-last-child(2)',e={ returnparseInt(e.textContent) constallJobs= for(leti=1;i=totalPage;i++){ awaitpage.goto('https://www.zhipin.com/web/geek/job?query=前端&city=100010000&page='+ awaitpage.waitForSelector('.job-list-box'); constjobs=awaitpage.$eval('.job-list-box',el={ return[...el.querySelectorAll('.job-card-wrapper')].map(item={ return{ job:{ name:item.querySelector('.job-name').textContent, area:item.querySelector('.job-area').textContent, salary:item.querySelector('.salary').textContent }, link:item.querySelector('a').href, company:{ name:item.querySelector('.company-name').textContent } } }) allJobs.push(...jobs); } //console.log(allJobs); for(leti=0;iallJobs.length;i++){ awaitpage.goto(allJobs[i].link); try{ awaitpage.waitForSelector('.job-sec-text'); constjd=awaitpage.$eval('.job-sec-text',el={ returnel.textContent allJobs[i].desc= console.log(allJobs[i]); }catch(e){} } } } 这里原封不动的把之前的爬虫逻辑复制了过来,只是把 headless 设置为了 true,因为我们不需要界面。 浏览器访问下: 爬虫跑的没啥问题。 不过这个过程中 boss 可能会检测到你访问频率过高,会让你做下是不是真人的验证: 这个就是验证码点点就好了。 然后我们把数据存到数据库里: 用 EntityManager 来 save 就好了: @Inject(EntityManager) privateentityManager:EntityManager; constjob=newJob(); job.name=allJobs[i].job.name; job.area=allJobs[i].job.area; job.salary=allJobs[i].job.salary; job.link=allJobs[i].link; job.company=allJobs[i].company.name; job.desc=allJobs[i].desc; awaitthis.entityManager.save(Job,job); 再跑下: 去数据库里看下: 这样,你就可以对这些职位描述做一些搜索,分析之类的了。 比如搜索职位描述中包含 react 的岗位: SELECT*FROM`boss-spider`.jobwhere`desc`like"%React%"; 这样,爬虫就做完了。 如果想在前端实时看到爬取到的数据,可以通过 SSE 来实时返回: 这样用: 这里我们就不改了。 案例代码上传了 nest 小册仓库:https://github.com/QuarkGluonPlasma/nestjs-course-code/tree/main/boss-jd-spider 总结 我们通过 puppeteer 实现了对 BOSS 直聘网站的前端职位的爬取,并用 Nest + TypeORM 把数据保存到了数据库里。 这样就可以在本地对这些职位数据做一些处理或分析了。 更多内容可以看我的小册《Nest 通关秘籍》 阅读原文

上一篇:2024-07-17_如何布光,是优秀摄影师应该掌握的基本方法 下一篇:2023-11-17_【招聘】回未广告、黑芒营销策划、ZHIDE 智得,热招中~

TAG标签:

18
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设网站改版域名注册主机空间手机网站建设网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。
项目经理在线

相关阅读 更多>>

猜您喜欢更多>>

我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!

不达标就退款

高性价比建站

免费网站代备案

1对1原创设计服务

7×24小时售后支持

 

全国免费咨询:

13245491521

业务咨询:13245491521 / 13245491521

节假值班:13245491521()

联系地址:

Copyright © 2019-2025      ICP备案:沪ICP备19027192号-6 法律顾问:律师XXX支持

在线
客服

技术在线服务时间:9:00-20:00

在网站开发,您对接的直接是技术员,而非客服传话!

电话
咨询

13245491521
7*24小时客服热线

13245491521
项目经理手机

微信
咨询

加微信获取报价