Java爬虫 爬取某招聘网站招聘信息

news2024/9/22 17:31:42

Java爬虫 爬取某招聘网站招聘信息

  • 一、系统介绍
  • 二、功能展示
    • 1.需求爬取的网站内容
    • 2.实现流程
    • 2.1数据采集
    • 2.2页面解析
    • 2.3数据存储
  • 三、获取源码

一、系统介绍

系统主要功能:本项目爬取的XX招聘网站

二、功能展示

1.需求爬取的网站内容

在这里插入图片描述

2.实现流程

爬虫可以分为三个模块:数据采集,数据解析,数据保存

项目结构:
在这里插入图片描述

2.1数据采集

​ 数据采集主要是通过HttpClient去请求url,获取网页源码。
(注:除了HttpClient,还可以用HttpUtil,具体使用方式可以百度得到,这里贴出两种工具的使用代码,实现的功能是一样的)
在pom.xml配置相关依赖
HttpClient:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.9</version>
</dependency>

HttpUtil:

<dependency>
    <groupId>net.sourceforge.htmlunit</groupId>
    <artifactId>htmlunit</artifactId>
    <version>2.27</version>
</dependency>

两种工具看个人喜好选择,本项目选择的是HttpClient.建议使用htmlunit,htmlunit爬内容相对齐全。
HTTPClient与HttpUtil的使用方法
HTTPClient

package com.master.controller;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

public class HttpClientDownPage {
    //设置代理,模范浏览器
    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36";
    public static String sendGet(String url){
        //1.生成httpclient,相当于该打开一个浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //设置请求和传输超时时间
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
        CloseableHttpResponse response = null;
        String html = null;
        //2.创建get请求,相当于在浏览器地址栏输入 网址
        HttpGet request = new HttpGet(url);
        try {
            request.setHeader("User-Agent",USER_AGENT);
            request.setConfig(requestConfig);
            //3.执行get请求,相当于在输入地址栏后敲回车键
            response = httpClient.execute(request);
            //4.判断响应状态为200,进行处理
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                //5.获取响应内容
                HttpEntity httpEntity = response.getEntity();
                html = EntityUtils.toString(httpEntity, "GBK");
            } else {
                //如果返回状态不是200,比如404(页面不存在)等,根据情况做处理,这里略
                System.out.println("返回状态不是200");
                System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //6.关闭
            HttpClientUtils.closeQuietly(response);
            HttpClientUtils.closeQuietly(httpClient);
        }
        return html;
    }
}

HttpUtil

package com.master.controller;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

public class HttpUtilDownPage {
    //新建一个模拟谷歌Chrome浏览器的浏览器客户端对象
    private static final WebClient webClient = new WebClient(BrowserVersion.CHROME);

    public static String sendGet(String url){
        //当JS执行出错的时候是否抛出异常, 这里选择不需要
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        //当HTTP的状态非200时是否抛出异常, 这里选择不需要
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
        webClient.getOptions().setActiveXNative(false);
        //是否启用CSS, 因为不需要展现页面, 所以不需要启用
        webClient.getOptions().setCssEnabled(false);
        //很重要,启用JS
        webClient.getOptions().setJavaScriptEnabled(true);
        //很重要,设置支持AJAX
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());
        HtmlPage page = null;
        try {
            page = webClient.getPage(url);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            webClient.close();
        }
        //异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束
        webClient.waitForBackgroundJavaScript(30000);
        //直接将加载完成的页面转换成xml格式的字符串
        String pageXml = page.asXml();
        return pageXml;
    }
}



上面两种方法都可请求到页面源码信息,这里用的是字符串接收下来。

(注:如果使用HttpClient,有些网页无法获取到全部的页面代码信息,可换成HttpUtil尝试,如果还是不行,那可能是该网站采取了一些反爬措施,需要小伙伴自己动脑解决了)

2.2页面解析

页面源码请求下来了,那么就轮到页面解析模块出厂了。

​ 我们看到的网页,本质上都是由一个个标签嵌套组合而成,再加上js,css等渲染成一个美观的页面,但是我们需要的的数据,所以摒除绚丽的外观,我们只需要解析出目标数据所在的标签就行了。

​ 解析页面的方法也有多种,有htmlcleaner,Jsoup等,这里使用的是Jsoup,HTMLCleaner使用标签的Xpath解析,Xpath可以在浏览器中 进行一下操作 ctrl+shift+c,然后找到目标标签,点击鼠标右键,选择copy,会有cpoy Xpath选项即可,具体玩转需要小伙伴自己去探索,因为笔者也不懂。。。

​ 使用Jsoup,在springboot中只需配置相关依赖便可使用

 <!--Jsoup-->
 <dependency>
     <groupId>org.jsoup</groupId>
     <artifactId>jsoup</artifactId>
     <version>1.11.3</version>
 </dependency>

将获取的网页信息通过Jsoup.parse(content)方法转化成Document对象,传到解析模块,解析模块相关代码:

    private void paraseList(Document document) throws InterruptedException {
        //根据网页标签解析源码
        Elements elements = document.getElementsByClass("sojob-item-main clearfix");
        for(Element element:elements){
            Elements elements1 = element.select("h3");
            String job = elements1.attr("title");
            Elements elements2 = element.select(".condition");
            String all = elements2.attr("title");
            String[] a = all.split("_");
            String salary = a[0];
            String address = a[1];
            String require = a[2]+a[3];
            Elements elements3 = (element.select(".temptation")).select("span");
            String welfare = elements3.text();
            //公司名称
            Elements elements4 = (element.select(".company-name")).select("a");
            String companyname = elements4.text();
            Job jobs = new Job();
            //kay是字段名 value是字段值
            jobs.setJob(job);
            jobs.setSalary(salary);
            jobs.setAddress(address);
            jobs.setCompanyname(companyname);
            jobs.setRequire(require);
            jobs.setWelfare(welfare);
            list.add(jobs);
        }
    }

这里是解析页面,获取想要的职位信息,将解析的数据封装到QCPage中,效果图如下
在这里插入图片描述

2.3数据存储

​数据解析完,就差数据存储了。
笔者采用了excel存储

    public void saveXls(List list,String name) {
        //第一步,创建一个workbook对应一个excel文件
        HSSFWorkbook workbook = new HSSFWorkbook();
        //第二部,在workbook中创建一个sheet对应excel中的sheet
        HSSFSheet sheet = workbook.createSheet("招聘表");
        //第三部,在sheet表中添加表头第0行,老版本的poi对sheet的行列有限制
        HSSFRow row = sheet.createRow(0);
        //第四步,创建单元格,设置表头
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("招聘公司");
        cell = row.createCell(1);
        cell.setCellValue("岗位名称");
        cell = row.createCell(2);
        cell.setCellValue("岗位薪资");
        cell = row.createCell(3);
        cell.setCellValue("工作地点");
        cell = row.createCell(4);
        cell.setCellValue("岗位要求");
        cell = row.createCell(5);
        cell.setCellValue("福利待遇");

        //第五步,写入实体数据,实际应用中这些数据从数据库得到,对象封装数据,集合包对象。对象的属性值对应表的每行的值
        for (int i = 0; i < list.size(); i++) {
            HSSFRow row1 = sheet.createRow(i + 1);
            //创建单元格设值
            row1.createCell(0).setCellValue(((Job) list.get(i)).getCompanyname());
            row1.createCell(1).setCellValue(((Job) list.get(i)).getJob());
            row1.createCell(2).setCellValue(((Job) list.get(i)).getSalary());
            row1.createCell(3).setCellValue(((Job) list.get(i)).getAddress());
            row1.createCell(4).setCellValue(((Job) list.get(i)).getRequire());
            row1.createCell(5).setCellValue(((Job) list.get(i)).getWelfare());
        }

        File file = new File("D:/"+name+".xls");
        if (file.exists()) {
            file.delete();
        }
        //将文件保存到指定的位置
        try {
            file.createNewFile();
            FileOutputStream fos = new FileOutputStream(file);
            workbook.write(fos);
            System.out.println("写入成功");
            workbook.close();
        } catch ( IOException e) {
            e.printStackTrace();
        }
    }

效果
在这里插入图片描述

三、获取源码

点击下载
Java爬虫 爬取某招聘网站招聘信息

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

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

相关文章

[Kettle] Kettle界面介绍

启动Kettle后&#xff0c;弹出Kettle的欢迎界面 有关界面的构成和说明如下所示 ①标题栏&#xff1a;显示界面标题名称 ②菜单栏&#xff1a;分别有【文件】|【编辑】|【视图】|【执行】|【工具】|【帮助】六个菜单栏 ③工具图标栏&#xff1a;显示图形化的常用和重要的菜单项…

SAP MM采购定价过程字段解析

下面我们针对每一个字段进行解释和用途分析 &#xff1a; 1、 步骤&#xff1a;代表了创建PO时&#xff0c;哪个条件类型放到前面&#xff0c;哪个放到后面&#xff0c;如果步骤号相同&#xff0c;那就以谁先选择出来谁就在前面。 2、 计数&#xff1a;没有任何实际意义&a…

DaVinci:神奇遮罩

调色页面&#xff1a;神奇遮罩Color&#xff1a;Magic Mask神奇遮罩 Magic Mask基于人工智能技术&#xff0c;在检视器中绘制一个笔画&#xff0c;就能识别出笔画所在的对象&#xff0c;并以此自动创建遮罩。先确定要对画面上的物体还是人体做遮罩。若是对人体做遮罩&#xff0…

【闲来无聊写个几个小特效——五角星,小光圈,探照灯】

五角星&#xff0c;见过吧&#xff0c;如果是你&#xff0c;你如何使用代码写一个五角星呢&#xff1f;思考一下&#xff0c;你会说&#xff0c;先这样在那样就好啦&#xff0c;可是真正上手的时候却修修改改磕磕绊绊来看一下今天的五角星如何用几行代码实现 1.绘制五角星 四行…

Pytorch进行自定义Dataset 和 Dataloader 原理

1、自定义加载数据 在pytorch中&#xff0c;数据集对象被抽象为Dataset类&#xff0c;实现自定义的数据集需要继承Dataset&#xff0c;并实现相应的方法。 在学习Pytorch的教程时&#xff0c;加载数据许多时候都是直接调用torchvision.datasets里面集成的数据集&#xff0c;直…

GO第 4 章:运算符

第 4 章 运算符 4.1 运算符的基本介绍 运算符是一种特殊的符号&#xff0c;用以表示数据的运算、赋值和比较等 运算符是一种特殊的符号&#xff0c;用以表示数据的运算、赋值和比较等 算术运算符 赋值运算符 比较运算符/关系运算符 逻辑运算符 位运算符 其它运算 4.2 …

Java开发环境安装

总步骤 第一步&#xff1a;安装JDK&#xff08;Java Development Kit&#xff0c;Java软件开发工具包&#xff09; 第二步&#xff1a;安装IDEA&#xff08;是Java语言的集成开发环境&#xff09; 一、安装JDK Windows下最简单的Java环境安装指南 - 大博哥VV6 - 博客园 (cnblo…

微信小程序框架

框架 小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。 整个小程序框架系统分为两部分&#xff1a;逻辑层&#xff08;App Service&#xff09;和 视图层&#xff08;View&#xff09;。小程序提供了自己的视图层描述语言…

【Linux】进程创建、进程终止和进程等待

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;进程创建&…

力扣刷题记录——231. 2 的幂、228. 汇总区间、242. 有效的字母异位词

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《231. 2 的幂、228. 汇总区间、242. 有效的字母异位词》。…

【王道操作系统】2.2.4 作业进程调度算法(FCFS先来先服务、SJF短作业优先、HRRN高响应比优先)

作业进程调度算法(FCFS先来先服务、SJF短作业优先、HRRN高响应比优先) 文章目录作业进程调度算法(FCFS先来先服务、SJF短作业优先、HRRN高响应比优先)1.先来先服务(FCFS)2.短作业优先(SJF)3.高响应比优先(HRRN)4.三种算法的对比和总结1.先来先服务(FCFS) 先来先服务调度算法(F…

区间选点 and 最大不相交区间

区间选点 题目描述 给定 N 个闭区间 [ai,bi]&#xff0c;请你在数轴上选择尽量少的点&#xff0c;使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入输出及样例 最大不相交区间 题目描述 给定 N 个闭区间 [ai,bi]&…

ArcGIS基础实验操作100例--实验32计算栅格行列号

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验32 计算栅格行列号 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&am…

GPU存储器架构-- 全局内存 本地内存 寄存器堆 共享内存 常量内存 纹理内存

上表表述了各种存储器的各种特性。作用范围栏定义了程序的哪个部分能使用该存储器。而生存期定义了该存储器中的数据对程序可见的时间。除此之外&#xff0c;Ll和L2缓存也可以用于GPU程序以便更快地访问存储器。 总之&#xff0c;所有线程都有一个寄存器堆&#xff0c;它是最快…

【PDPTW】python调用guribo求解PDPTW问题(Li Lim‘s benchmark)之二

原文连接&#xff1a;知乎《使用Python调用Gurobi求解PDPTW问题&#xff08;Li & Lim’s benchmark&#xff09;》 分析文章&#xff1a;文章目录修改utlis.pytest.py运行DataPath"lc101.txt"修改 以及修改公示约束&#xff08;8&#xff09;与代码不符合的问题…

【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.13 抗锯齿

本节对应的视频讲解&#xff1a;B_站_视_频 https://www.bilibili.com/video/BV1YP4y1B7Ex 本节讲解抗锯齿效果 前面实现的效果中&#xff0c;仔细观看能看到明显的锯齿的效果&#xff0c;如下&#xff1a; 此时&#xff0c;可以增加抗锯齿的效果。 1. 关联信号槽 首先&…

22年12月日常实习总结

12月结束了&#xff0c;8月末开始准备的日常实习也算是告一段落了 准备了2个多月&#xff0c;面试了一个月&#xff0c;也拿了一些offer 算是小有感触&#xff0c;遂写下此文&#xff0c;供还在准备或者要准备日常实习的同学参考。 个人背景及投递的日常实录在这篇文章里 24…

RegNet——颠覆常规神经网络认知的卷积神经网络(网络结构详解+详细注释代码+核心思想讲解)——pytorch实现

RegNet的博客的准备我可谓是话费了很多的时间&#xff0c;参考了诸多大佬的资料&#xff0c;主要是网上对于这个网络的讲解有点少&#xff0c;毕竟这个网络很新。网上可以参考的资料太少&#xff0c;耗费了相当多的时间&#xff0c;不过一切都是值得的&#xff0c;毕竟学完之后…

第二证券|下周解禁市值超980亿元,多家机构参与解禁股评级

宁德年代迎来431.8亿元解禁。 下周A股解禁市值超980亿元 证券时报数据宝统计&#xff0c;1月3日至6日&#xff0c;A股商场将有53家上市公司迎来限售股解禁。以个股最新价计算&#xff0c;53股解禁市值合计981.68亿元。 从解禁规模来看&#xff0c;宁德年代和中国移动居前&…

4.搭建配置中心-使用SpringCloud Alibaba-Nacos

naocs除了做服务注册、发现&#xff0c;还可以做为配置中心&#xff0c;使用分以下几步 1.pom引入nacos-config依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> &…