java---爬虫

2023-05-16

提示:以下代码仅能用于学习使用,部分代码已脱敏


前言

为了帮助女朋友完成作业从没接触过爬虫的我被赶鸭子上架,硬着头皮code。索性是不负所托,虽然代码很垃圾但是所期望的功能也完整实现。下面进入正题希望可以帮助到有同样需求的同学。


一、技术栈

  		<dependency>
            <groupId>net.sourceforge.htmlunit</groupId>
            <artifactId>htmlunit</artifactId>
            <version>2.61.0</version>
        </dependency>
        
         <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.14.3</version>
        </dependency>
  • HtmlUnit可以理解为java版无界面浏览器,我们需要它来帮助我们获取HTML页面。因为boss的一些反爬虫机制直接使用httpclient等很麻烦很难直接获取到页面。
  • Java 的HTML解析器,在我们使用HtmlUnit拉取到HTML页面时需要借助此工具来解析从而获取有价值的数据

二、编码

1.创建HtmlUnit浏览器对象

有条件的同学可以到某宝买一下高匿IP,否则请求太快很容易被封掉IP还需要登录解封很麻烦。我这里因为需要的数据量不大就采用最笨的办法增大访问间隔并将登录信息传入cookie尽可能跳过安全监测慢慢爬取。同时我们也可以模拟为登录状态进行访问在我的测试下登录状态加延迟访问的手段下基本没有再次被反扒机制检测。我们主动登录后可以将一些安全验证的cookie添加到HtmlUnit进行模拟,详情可看下方代码我将所有可能用于安全验证的5个cookie都进行了模拟。从控制台也可以看到我们的设想是成功的,完美以登录状态爬取了数据,避免了频繁请求被检测。
在这里插入图片描述

 WebClient webClient = new WebClient(BrowserVersion.CHROME);
        // 设置webClient的相关参数
        webClient.setCssErrorHandler(new SilentCssErrorHandler());
        //设置ajax
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());
        //设置支持js
        webClient.getOptions().setJavaScriptEnabled(true);
        //CSS渲染禁止
        webClient.getOptions().setCssEnabled(false);
        //设置忽略证书
        webClient.getOptions().setUseInsecureSSL(true);
        //超时时间
        webClient.getOptions().setTimeout(50000);
        //设置js抛出异常:false
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        //允许重定向
        webClient.getOptions().setRedirectEnabled(true);
        //允许cookie
        webClient.getCookieManager().setCookiesEnabled(true);
        Cookie cookie = new Cookie("www.zhipin.com","acw_tc","0bdd344616516524703935440e01a51535ae8e05f3d512a762a10e8202c9d0D");
        Cookie cookie2 = new Cookie("www.zhipin.com","geek_zp_token","V1RNghE-L_31pqVtRvyhweLCi26j3VxCs~");
        Cookie cookie3 = new Cookie(".zhipin.com","wt2","DWOBanb0Gmjw7-c54klh6gUVY-IRiUKpX1G-1Kf60OdAV89YbYhlXhJxeKmZADThaivqy3_Kn9i2JRNh6KoKxnA~~");
        Cookie cookie4 = new Cookie(".zhipin.com","__zp_stoken__","3f39dZydrfWwRMTE%2FWhxWKicmChRII3sFVGoUWUtmf149HiMDLkdVZEcjVFFPNw8gAjsHfn9fKHRDX0EVLCA8XRtVEwcNPhtqKTF7WhR%2BbyNMXAJNFCogGyBDdS4lGisqQAI1ACRWXQMKbEU%3D");
        Cookie cookie5 = new Cookie("www.zhipin.com","wd_guid","98a38c8d-7706-4f05-b59d-bae37e5fc920");
         webClient.getCookieManager().addCookie(cookie);
        webClient.getCookieManager().addCookie(cookie2);
        webClient.getCookieManager().addCookie(cookie3);
        webClient.getCookieManager().addCookie(cookie4);
        webClient.getCookieManager().addCookie(cookie5);
        Ip ip = new Ip();
        WebClient connection = HtmlUnitUtils.getConnection(ip, webClient);
        // 模拟浏览器打开一个目标网址
//        HtmlPage page = connection.getPage("https://api.twitter.com/oauth/authorize?oauth_token=JrbVIAAAAAABASakAAABdsxFCaI");
        HtmlPage page = connection.getPage("https://www.zhipin.com/c101280600/?query=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0&page=2&ka=page-2");

2.解析html

这里我们拿到了整个页面的html代码,我们需要获得下图红框中的有用信息跟点击后进入的详情页
在这里插入图片描述

 HtmlPage page = connection.getPage("https://www.zhipin.com/c101280600/?query=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0&page=2&ka=page-2");
        Document document = Jsoup.parseBodyFragment(page.asXml());
        Elements elements = document.select("div.job-list ul li");

浏览器右键检查,我们来抽取下html代码。看html可以发现整个招聘信息其实就是列表ul标签组成的,所以我们只需要拿到ul下的li逐个遍历即可。document.select(“div.job-list ul li”)拿到的30个li。
在这里插入图片描述

3.获取具体数据字段

jsoup中为我们提供了很多方法,可以通过id,tag,class等获得元素节点在获取elements节点时记得要做一下数组非空判断不要像下方代码一样直接获取。并不是所有节点数据都百分百一样,应避免索引越界异常。

 elements.forEach(csm -> {
 			。。。。。。。
            Recruiting recruiting = new Recruiting();
            Elements elements1 = csm.getElementsByClass("job-name");
            String jobName = elements1.get(0).getElementsByTag("a").attr("title");
      		。。。。。。。
        });

比如上面脱敏代码展示,我们此时想要获取职位名称在拿到li后即可通过class元素选择器来拿到span标签。顺腾摸瓜拿到下面的a标签,通过attr()方法获取a标签中的title属性值。
在这里插入图片描述

4. 拼接跳转链接

在获取到上述所有信息后我们还需要获取下详细招聘要求,此数据需要点击跳转后获取。这里我们需要注意的点是,之前我们只需要请求一次就可以拿到整个页面的30条数据。但是,在获取详情时,每获取一条就必须得点击一次意味着请求一次后台接口。这里百分之99会被系统检测然后黑掉IP需要重新登陆解封。BOSS直接送你一个403,土豪请买一天的高匿IP。我这里通过增大请求间隔时间的方式也堪堪把数据爬取下来的因为只是完成作业不需要太过庞大的数据量。
在这里插入图片描述

跳转链接这里大家需要注意下,请求地址并不是直接跳转的。我们回到a标签可以看一下其中的属性值。
在这里插入图片描述
这里含有大量的安全验证字段需要我们拼接,至此我们获取到完整数据后即可写入数据库或者Excel等了。后续再使用布隆过滤器等进行去重数据清洗等。

  String link = csm.getElementsByClass("job-name").get(0).getElementsByTag("a").attr("href");
            String dataSecurityId = csm.getElementsByClass("job-name").get(0).getElementsByTag("a").attr("data-securityid");
            String  dataLid = csm.getElementsByClass("job-name").get(0).getElementsByTag("a").attr("data-lid");
            String ka = csm.getElementsByClass("job-name").get(0).getElementsByTag("a").attr("ka");
            try {
                String url = "https://www.zhipin.com" + link + "?ka=" + ka + "_blank" + "&lid=" + dataLid + "&securityId=" + dataSecurityId;
                TimeUnit.SECONDS.sleep(5);
                HtmlPage detail = connection.getPage(url);
                Document detailDocument = Jsoup.parseBodyFragment(detail.asXml());
                String detailElements = detailDocument.select("div.text").get(0).text();
                recruiting.setWorkDetail(detailElements);
                mongoOperations.insert(recruiting);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

在这里插入图片描述
mongodb持久化类:

@Document(collection = "recruiting")
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@ToString
public class Recruiting {

    //职位名称
    String jobName;

    //工作地区
    String jobArea;

    // 薪资情况
    String remuneration;

    // 工作经验
    String experience;

    //学历
    String education;

    // 公司名称
    String company;

    // 公司类型
    String companyyType;

    // 公司发展阶段
    String companyStage;

    // 公司规模
    String companyScale;

    // 职能标签
    List<String> tags;

    // 福利待遇简介
    String desc;

    //岗位要求详细信息
    String workDetail;

}

总结

上述爬虫方式只是最低级的一种方式,离商业爬虫还差了十万八千里,只是为了帮女朋友完成下作业。望勿嘲。代码已经脱敏只提供了关键部分,如果被boss403需要登录大家也可以了解下webdriver可以帮助我们完成登录验证https://blog.csdn.net/qq_45623864/article/details/121952242?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.pc_relevant_aa&utm_relevant_index=12
最终楼主如愿获取到了上千条招聘信息
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java---爬虫 的相关文章

  • 如何在测试套件中定义 JUnit 方法规则?

    我有一个类 它是 JUnit 测试类的 JUnit 套件 我想定义一个规则on the suite 这是可以做到的 但需要做一些工作 您还需要定义自己的 Suite 运行程序和测试运行程序 然后在测试运行程序中重写 runChild 使用以
  • MP3:一种以毫秒为单位获取任何给定字节位置的位置的方法?

    我创建了一个 servlet 它返回从客户端请求的任何给定字节位置开始的流 来自 MP3 文件 这允许客户端在任何给定字节位置立即开始播放 而无需进行任何本地查找 现在 我有一个滑块可以直观地显示进度 我正在使用当前字节位置来更新滑块 但是
  • 如何在 Eclipse 中用阿拉伯语读写

    我在 eclipse 中编写了这段代码来获取一些阿拉伯语单词 然后打印它们 public class getString public static void main String args throws Exception PrintS
  • 有没有好的方法来解析用户代理字符串?

    我有一个Java接收模块User Agent来自最终用户浏览器的字符串的行为需要略有不同 具体取决于浏览器类型 浏览器版本甚至操作系统 例如 FireFox 7 0 Win7 Safari 3 2 iOS9 我明白了User Agent由于
  • Java 泛型/类型调度问题

    考虑以下程序 import java util List import java util ArrayList public class TypeTest public static class TypeTestA extends Type
  • PropertySources 中各种源的优先级

    Spring引入了新的注释 PropertySources对于所有标记为的类 Configuration since 4 0 需要不同的 PropertySource作为论证 PropertySources PropertySource c
  • spring - 强制 @Autowired 字段的 cglib 代理

    我有混合堆栈 EJB 和 Spring 为了将 Spring 自动装配到 EJB 我使用SpringBeanAutowiringInterceptor 不确定这是否会影响我遇到的问题 在尝试通过以下方式自动装配 bean 时 Scope p
  • 场景生成器删除 fxml 文件中的导入

    我使用场景构建器 Gluon Scene Builder JavaFX Scene Builder 8 1 1 来创建应用程序的 UI 并使用 Eclipse 开发 JavaFX 现在 每次我在场景生成器中保存某些内容时 它都会从 fxml
  • Java替换特定字符

    这是我在这个网站上的第一个问题 所以我会尽量不要成为一个十足的菜鸟 我目前正在用java 创建刽子手游戏 所以我问你的问题是我们是否被赋予了 幽灵 这个词 并将 Ghost 替换为 hiddenWord ghost length for i
  • 具有多种值类型的 Java 枚举

    基本上我所做的是为国家编写一个枚举 我希望不仅能够像国家一样访问它们 而且还能够访问它们的缩写以及它们是否是原始殖民地 public enum States MASSACHUSETTS Massachusetts MA true MICHI
  • tomcat 过滤所有 web 应用程序

    问题 我想对所有网络应用程序进行过滤 我创建了一个过滤器来监视对 apache tomcat 服务器的请求 举例来说 它称为 MyFilter 我在 netbeans 中创建了它 它创建了 2 个独立的目录 webpages contain
  • 在 AKKA 中,对主管调用 shutdown 是否会停止其监督的所有参与者?

    假设我有一位主管连接了 2 位演员 当我的应用程序关闭时 我想优雅地关闭这些参与者 调用supervisor shutdown 是否会停止所有参与者 还是我仍然需要手动停止我的参与者 gracias 阻止主管 https github co
  • struts 教程或示例

    我正在尝试在 Struts 中制作一个登录页面 这个想法是验证用户是否存在等 然后如果有错误 则返回到登录页面 错误显示为红色 典型的登录或任何表单页面验证 我想知道是否有人知道 Struts 中的错误管理教程 我正在专门寻找有关的教程 或
  • 重写Object类的finalize()方法有什么用?

    据我所知 在java中如果我们想手动调用垃圾收集器 我们可以执行System gc 1 我们在重写的finalize 方法中做了哪些操作 2 如果我们想手动调用JVM垃圾收集器 是否需要重写finalize 方法 我们在重写的 Finali
  • 从一个文本文件中获取数据并将其移动到新的文本文件

    我有一个文件 里面有数据 在我的主要方法中 我读入文件并关闭文件 我调用另一种方法 在原始文件的同一文件夹内创建一个新文件 所以现在我有两个文件 原始文件和通过我调用的方法生成的文件 我需要另一种方法 从原始文件中获取数据并将其写入创建的新
  • Java 编码风格、局部变量与重复方法调用

    我更喜欢使用局部变量而不是多次调用同一方法 I prefer this Vehicle vehicle person getVehicle if vehicle instanceof Car Car car Car vehicle car
  • 如何将实例变量传递到 Quartz 作业中?

    我想知道如何在 Quartz 中外部传递实例变量 下面是我想写的伪代码 如何将 externalInstance 传递到此作业中 public class SimpleJob implements Job Override public v
  • 为什么 BufferedWriter 不写入文件?

    我有这个代码 String strings Hi You He They Tetrabenzene Caaorine Calorine File file new File G words txt FileWriter fWriter Bu
  • Java 推断泛型类型

    我正在寻找类似的推断捕获泛型类型的概念 类似于以下方法片段 但不是捕获泛型类型的类 public
  • java中如何找到class文件的包

    我正在编写一个使用 class 文件的 java 程序 我希望能够读取文件系统上的 class 文件 使用 InputStream 并确定它所在的包 该 class 文件可能不在一个好的包目录结构中 它可能位于某个随机位置 我怎样才能做到这

随机推荐

  • 11.24总结

    1 jsua oj 0 打算明后两天集中搞菜鸟杯题组 2 启航oj 5 今天上午满课下午都在敲代码 这真的是大一吗 有了昨天的刷题经验今天自己刷题快多了就是被那些提交语言折磨到窒息白白浪费了好多时间 主要学习了蛇形矩阵的算法根据题意判断从那
  • 11.25总结

    博客被吞了一遍 我吐了想一点前上床睡觉有这么难吗 虽然今天一天满课但是我还是学到了很多知识 今天启航oj 1 菜鸟杯补题 4 写了一篇关于党的19届六中全会的文章 主要学习了汉诺塔的数据变化原理 xff0c 递归 加深我对递归的理解 xff
  • 12.1日总结

    刷题数0 真的是挺无语的因为感觉指针链表栈的知识混成一团了 xff0c 只能各种百度 xff0c 最后发现书本里面的才是最香的 虽然没有做出来栈的题目但是大体的基本概念已经理清了 先从链表讲起 一说到结构体 xff0c 指针 xff0c 链
  • 12.2总结(纵使结局不如意,放弃实属下下签。)

    刷题数三 xff0c 菜鸟杯补题2 xff1b 启航栈1 xff1b 终于知道这两天为什么这么痛苦了 我一度难受到窒息因为我看的是链栈我看了两天硬是对这些题目无从下手 xff0c 因为他吧指针 结构体 链表 栈一起结合起来使用 我去搜各种博
  • 12.3日总结 单调栈

    今天就刷了两个题 xff0c 尝试了一个题 xff0c 主要看了单调栈 xff0c 单调栈分为两种一中是栈中元素从栈顶到栈顶呈从小到大的排序的栈这样的栈称为单调递增栈 另一种从栈顶到栈底数据从大到小称为单调递减栈 单调栈的应用一般可以用来求
  • 12.5总结

    开始着手于项目的编写 其实所有事情都是开头难 xff0c 项目也一样 xff0c 第一次写项目必定要接触到很多新东西 xff0c 今天主要遇到了两个新的头文件里面包含了写项目必备的几个函数 stdlib h里面定义了五种类型 一些宏和通用工
  • 搬运! Windbg调试命令详解

    转载注明 gt gt 作者 xff1a 张佩 原文 xff1a http www yiiyee cn Blog 1 概述 用户成功安装微软Windows调试工具集后 xff0c 能够在安装目录下发现四个调试器程序 xff0c 分别是 xff
  • 使用光盘安装Microsoft media foundation

    一 准备 系统 xff1a widnows server 2012 R2 Datacenter 准备文件 xff1a 安装光盘或iso 双击iso文件 xff0c windows server会自动虚拟出一个光驱 假如光驱或虚拟光驱的盘符为
  • 如何用MindManager将导图导出为HTML5交互式导图?

    最新版MindManager 2017中新增了一种导出方式 HTML5交互式导图 xff0c 相信很多人在了解MindManager 2017新功能的时候就已经知道了 本文 xff0c 小编将给大家演示 xff0c 如何将做好的思维导图导出
  • 判断两个IP是否属于同一个子网

    例如 xff1a 192 168 1 1 24和192 168 1 33 27 192 168 1 1 24的ip地址为192 168 1 1 xff0c 子网掩码为255 255 255 0 转化为二进制 xff1a IP地址为 xff1
  • 记录一次K8s-Flannel插件的坑

    版本 xff1a K8s版本1 17 6 部署方式 xff1a ansible 43 kubeadm部署 架构 xff1a master1 43 node2 43 registry私有仓库 执行kubectl apply f kube fl
  • opencv imencode和imdecode使用,用于网络传输图片

    这是C 43 43 版本的 程序首先读入一个图片 然后encode xff0c 之后把encode后的内容写入文件 xff08 实际应用可以发送到网络 xff09 第二步 xff0c 从文件读取encode的内容 然后解码decode 转换
  • 云计算&云存储

    云计算技术 云计算技术主要分为以下几个部分 xff1a 编程模式海量数据分布存储技术海量数据管理技术虚拟化技术云计算平台管理技术 云计算应用 云计算应用主要包含以下六个部分 xff1a 密码优先检查安全问题加密方法管理密码双重认证备份 云存
  • 用C语言实现字符串反转函数strrev的经典方法

    字符串反转函数strrev不是C语言标准库函数 xff0c 很多C语言编译器并没有提供对它的支持 xff0c 比如你在Linux下输入Shell命令man 3 strlen xff0c 屏幕上会显示 xff0c STRLEN 3 Linux
  • OSPFv3报文格式与作用分析

    OSPFv3报头 xff1a 实际抓包 xff1a 具体内容 xff1a Version xff1a 3 Type xff1a 报文类型 1 Hello 2 DD 3 LSR 4 LSU 5 LSAck Packet length xff1
  • IPv6基础知识

    概述 xff1a IPv6 xff08 Internet Protocol Version 6 xff09 是网络层协议的第二代标准协议 xff0c 也被称为IPng xff08 IP Next Generation xff09 它是Int
  • BGP在数据中心的应用1——数据中心网络介绍

    注 xff1a 本文根据 BGP in the Datacenter 整理 xff0c 有兴趣和英文阅读能力的朋友可以直接看原文 xff1a https www oreilly com library view bgp in the 978
  • 意法nucleo-h723zg原理图,stm32h723zg原理图

    兄弟们 xff1a 我之前一直都在找这个图 xff0c 废了老大的劲才找到 xff0c 并且找到就马上给大家分享了 xff0c 希望能顺手点个赞 Introduction xff1a The STM32H7 Nucleo 144 board
  • MAX30102学习笔记(上)

    MAX30102学习笔记 xff08 上 xff09 一 小简介 max30102是一个将脉搏血氧仪的心率检测仪融为一体的一个传感器模块 简单的说就是一个可以采集心率和血氧数据的小模块 xff0c 使用者只需将其佩戴于手指 xff0c 手腕
  • java---爬虫

    提示 xff1a 以下代码仅能用于学习使用 xff0c 部分代码已脱敏 前言 为了帮助女朋友完成作业从没接触过爬虫的我被赶鸭子上架 xff0c 硬着头皮code 索性是不负所托 xff0c 虽然代码很垃圾但是所期望的功能也完整实现 下面进入