只听过 Python 做爬虫?不瞒你说 Java 也很强

python,java · 浏览次数 : 0

小编点评

网络爬虫技术是一种自动化程序,它们可以根据预定的规则从互联网上提取网页数据,并从中提取有价值的信息。Java技术在处理复杂网页和生成结构化数据方面表现出色。 **网页分析** 网页分析是网络爬虫的第一步,需要识别网页的结构和内容。以国家省市区信息为例,网页通常呈现为table表格,包含tr和td标签。市级以上信息通常以黑体字加粗显示,而区或县级地区则以常规字体显示。此外,省级信息有一个特定的样式标签,而市级信息除了这个样式外,还有一个span占位符标签。 **编写爬虫程序** 编写爬虫程序涉及创建一个Maven Java项目并添加相关依赖。使用Jsoup库解析HTML文档,定位目标数据,并将其封装到实体类中。程序通过抓取网页信息,解析并提取所需数据,最后将数据写入数据库。 **写入数据库** 将抓取到的数据写入数据库是网络爬虫的重要环节。这涉及到创建数据库表,定义数据结构,并将抓取到的数据批量插入到数据库中。对于直辖市等特殊行政区域,需要单独处理并标记为市级类型。 **总结** 网络爬虫技术是互联网数据采集的重要组成部分,Java语言为其提供了强大的支持。通过结合Jsoup等工具包和Maven等构建工具,可以高效地实现网页数据的抓取和存储。同时,合法合规地使用技术是每个开发者应遵守的原则。

正文

网络爬虫技术,早在万维网诞生的时候,就已经出现了,今天我们就一起来揭开它神秘的面纱!

一、摘要

说起网络爬虫,相信大家都不陌生,又俗称网络机器人,指的是程序按照一定的规则,从互联网上抓取网页,然后从中获取有价值的数据,随便在网上搜索一下,排在前面基本都是 pyhton 教程介绍。

的确,pyhton 在处理网页方面,有着开发简单、便捷、性能高效的优势!

但是我们 java 也不赖,在处理复杂的网页方面,需要解析网页内容生成结构化数据或者对网页内容精细的解析时,java 可以说更胜一筹!

下面我们以爬取国家省市区信息为例,使用 java 技术来实现,过程主要分三部:

  • 第一步:目标网页分析
  • 第二步:编写爬虫程序,对关键数据进行抓取
  • 第三步:将抓取的数据写入数据库

废话不多说,直接开撸!

二、网页分析

网络爬虫,其实不是一个很难的技术,只是需要掌握的技术内容比较多,只会 java 技术是远远不够,还需要熟悉 html 页面属性!

以爬取国家省市区信息为例,我们可以直接在百度上搜索国家省市区,点击进入全国行政区划信息查询平台

民政数据菜单栏下,找到最新的行政区域代码公示栏。

点击进去,展示结果如下!

可以很清楚的看到,这就是我们要获取省市区代码的网页信息。

可能有的同学会问,这么直接干合不合法

国家既然已经公示了,我们直接拿来用就可以,完全合法!而且国家省市区代码是一个公共字典,在很多业务场景下必不可少!

当我们找到了目标网页之后,我们首先要做的就是对网页进行分析,打开浏览器调试器,可以很清晰的看到它是一个table表格组成的数据。

熟悉 html 标签的同学,想必已经知道了它的组成原理。

其实table是一个非常简单的 html 标签,主要有trtd组成,其中tr代表行,td代表列,例如用table标签画一个学生表格,代码如下:

<table>
    <!-- 定义表格头部 -->
    <tr>
        <td>编号</td>
        <td>姓名</td>
    </tr>
    <!-- 定义表格内容 -->
    <tr>
        <td>100</td>
        <td>张三</td>
    </tr>
    <tr>
        <td>101</td>
        <td>李四</td>
    </tr>
</table>

展示结果如下:

了解了table标签之后,我们再对网页进行详细分析。

首先对整个内容进行观察,很容易的看到,市级以上(包括市级),都是黑体字加粗的,区或者县级地区,都是常规!

出现这个现象,其实是由样式标签CSS来控制的,点击北京市,找到对应的代码位置,从图中我们可以很清晰的看到,市级对应的样式classxl7030796,区或者县级地区对应的样式classxl7130796

除此之外,我们继续来看看省和市级的区别!

可以很清晰的看到,市级相比省级信息,多了一个span占位符标签。

于是,我们可以得出如下结论:

  • 省级信息,样式标签为xl7030796
  • 市级信息,样式标签为xl7030796,同时包含span占位符标签
  • 区或者县级信息,样式标签为xl7130796

等会会通过这些规律信息来从网页信息中抓取省、市、区信息。

三、编写爬虫程序

3.1、创建项目

新建一个基于 maven 工程 java 项目,在pom.xml工程中引入如下 jar 包!

<!--解析HTML-->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.2</version>
</dependency>

3.2、编写爬取程序

  • 先创建一个实体数据类,用于存放抓取的数据
public class ChinaRegionsInfo {

    /**
     * 行政区域编码
     */
    private String code;

    /**
     * 行政区域名称
     */
    private String name;

    /**
     * 行政区域类型,1:省份,2:城市,3:区或者县城
     */
    private Integer type;

    /**
     * 上一级行政区域编码
     */
    private String parentCode;

    //省略get、set
}
  • 然后,我们来编写爬取代码,将抓取的数据封装到实体类中
//需要抓取的网页地址
private static final String URL = "http://www.mca.gov.cn//article/sj/xzqh/2020/202006/202008310601.shtml";

public static void main(String[] args) throws IOException {
    List<ChinaRegionsInfo> regionsInfoList = new ArrayList<>();
    //抓取网页信息
    Document document = Jsoup.connect(URL).get();
    //获取真实的数据体
    Element element = document.getElementsByTag("tbody").get(0);
    String provinceCode = "";//省级编码
    String cityCode = "";//市级编码
    if(Objects.nonNull(element)){
        Elements trs = element.getElementsByTag("tr");
        for (int i = 3; i < trs.size(); i++) {
            Elements tds = trs.get(i).getElementsByTag("td");
            if(tds.size() < 3){
                continue;
            }
            Element td1 = tds.get(1);//行政区域编码
            Element td2 = tds.get(2);//行政区域名称
            if(StringUtils.isNotEmpty(td1.text())){
                if(td1.classNames().contains("xl7030796")){
                    if(td2.toString().contains("span")){
                        //市级
                        ChinaRegionsInfo chinaRegions = new ChinaRegionsInfo();
                        chinaRegions.setCode(td1.text());
                        chinaRegions.setName(td2.text());
                        chinaRegions.setType(2);
                        chinaRegions.setParentCode(provinceCode);
                        regionsInfoList.add(chinaRegions);
                        cityCode = td1.text();
                    } else {
                        //省级
                        ChinaRegionsInfo chinaRegions = new ChinaRegionsInfo();
                        chinaRegions.setCode(td1.text());
                        chinaRegions.setName(td2.text());
                        chinaRegions.setType(1);
                        chinaRegions.setParentCode("");
                        regionsInfoList.add(chinaRegions);
                        provinceCode = td1.text();
                    }

                } else {
                    //区或者县级
                    ChinaRegionsInfo chinaRegions = new ChinaRegionsInfo();
                    chinaRegions.setCode(td1.text());
                    chinaRegions.setName(td2.text());
                    chinaRegions.setType(3);
                    chinaRegions.setParentCode(StringUtils.isNotEmpty(cityCode) ? cityCode : provinceCode);
                    regionsInfoList.add(chinaRegions);
                }
            }
        }
    }
    //打印结果
    System.out.println(JSONArray.toJSONString(regionsInfoList));
}

运行程序,输出结果如下:

json解析结果如下:

至此,网页有效数据已经全部抓取完毕!

四、写入数据库

在实际的业务场景中,我们需要做的不仅仅只是抓取出有价值的数据,最重要的是将这些数据记录数据库,以备后续的业务可以用的上!

例如,当我们在开发一个给员工发放薪资系统的时候,其中的社保、公积金,可能每个城市都不一样,这个时候就会到国家省市区编码。

因此,我们可以将抓取的国家省市区编码写入数据库!

在上面,我们已经将具体的省市区数据结构封装成数组对象,写入过程也很简单。

  • 首先,创建一张国家行政地域信息表china_regions
CREATE TABLE `china_regions` (
  `id` bigint(20) unsigned NOT NULL COMMENT '主键ID',
  `code` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '行政地域编码',
  `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '行政地域名称',
  `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '行政地域类型,1:省份,2:城市,3:区域',
  `parent_code` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '上一级行政编码',
  `is_delete` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除 1:已删除;0:未删除',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_code` (`code`) USING BTREE,
  KEY `idx_name` (`name`) USING BTREE,
  KEY `idx_type` (`type`) USING BTREE,
  KEY `idx_parent_code` (`parent_code`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='国家行政地域信息表';
  • 搭建一个springboot工程,通过mybatis-plus组件,一键生成代码

  • 最后,配置好数据源,重新封装数组对象,调用批量插入方法,即可插入操作
chinaRegionsService.saveBatch(regionsInfoList);
  • 插入执行完之后,数据库结果如下

至此,大部分工作基本已经完成!

但是,细心的你,可能会发现还有数据问题,因为我们国家在省级区域上,还有一个直辖市的概念,以北京市为例,在数据库中type类型为1,表示省级类型,但是它的子级是一个区,中间还掉了一层市级类型

因此,我们还需要对这些直辖市类型的数据进行修复,查询出所有的直辖市类型的城市。

对这些编号的城市,单独处理,中间加一层市级类型!

至此,国家省市区编码数据字典,全部处理完毕!

五、总结

本篇主要以爬取国家省市区编号为例,以 java 技术为背景进行讲解,在整个爬取过程中,最重要的一部分就是网页分析,找出规律,然后通过jsoup工具包解析网页,获取其中的有效数据。

同时,技术是一把双面刀,希望同学们在合法合规的环境下,正当使用!

六、参考

1、2020年行政区划代码

写到最后

不会有人刷到这里还想白嫖吧?点赞对我真的非常重要!在线求赞。加个关注我会非常感激!

本文已整理到技术笔记中,此外,笔记内容还涵盖 Spring、Spring Boot/Cloud、Dubbo、JVM、集合、多线程、JPA、MyBatis、MySQL、微服务等技术栈。

需要的小伙伴可以点击 技术笔记 获取!

与只听过 Python 做爬虫?不瞒你说 Java 也很强相似的内容:

只听过 Python 做爬虫?不瞒你说 Java 也很强

网络爬虫技术,早在万维网诞生的时候,就已经出现了,今天我们就一起来揭开它神秘的面纱! 一、摘要 说起网络爬虫,相信大家都不陌生,又俗称网络机器人,指的是程序按照一定的规则,从互联网上抓取网页,然后从中获取有价值的数据,随便在网上搜索一下,排在前面基本都是 pyhton 教程介绍。 的确,pyhton

GitHub上狂揽62Kstars的程序员做饭指南

写在前面 作为一名程序员,我们经常会在全球最大的同性交友网站 GitHub上寻找一些优质的开源项目来学习,以提升自己的专业技能。 今天给大家推荐的是一个GitHub上狂揽61K⭐⭐的开源项目。项目名叫做HowToCook,只听名字,大家应该能想到这是一个教程序员怎么做饭的项目。 作为一个程序员,你会

川普真会说中文?连嘴型都同步,VideoReTalking AI数字人下载介绍

你能想到这种画面吗?霉霉在节目中用普通话接受采访,特朗普在老家用中文脱口秀,蔡明老师操着一口流利的英文调侃潘长江老师.. 这听起来似乎很魔幻,可如今全部由VideoReTalking实现了 你只需要传入一个视频文件和音频文件,它会生成一个新的视频,在这个视频里,不仅人物的嘴型会与音频同步,就连表情也

实现Quartz.NET的HTTP作业调度

Quartz.NET作为一个开源的作业调度库,广泛应用于.NET应用程序中,以实现复杂的定时任务,本次记录利用Quartz.NET实现HTTP作业调度,通过自定义HTTP作业,实现对外部API的定时调用和如何管理这些作业,包括创建、修改、暂停、恢复和删除作业。 1.首先定义了一个HttpJob类,该

将html页面转成pdf下载保存(html2canvas + jspdf或者Print调出打印功能导出pdf)

方案1:html2canvas + jspdf (缺点:清晰度不高) 安装插件: 亲测可用 yarn add html2canvas yarn add jspdf import html2canvas from 'html2canvas'; import jspdf from 'jspdf'; /*

Nginx 简单应用(Windows os)

实际问题如下: 我的电脑上有vm虚拟机,我有两个网络,一个叫137,一个叫102 ,我现在vm的网络是102的网络(137不允许被vm使用),但是别人都是137的网络,如何让137的局域网访问我的vm中的网站/应用 我的解决办法是使用Nginx来将vm中的102网络反向代理到宿主机上(137), 比

流程编排及可视化

这里只介绍liteflow的简单基础使用以及作者对liteflow进行可视化扩展的相关阐述

SpringMVC源码(1)-文件上传请求

我们文件上传接口只需要在方法参数上写MultipartFile类,mvc就可以帮我们把上传的文件封装为这个类的对 象供我们非常方便的操作,那它是怎么做的呢?我们一起来看看 我们发的请求默认都是由DispatcherServlet类的doDispatch()来处理,这个方法的逻辑处理的第一步就是处理文

算法金 | 只需十四步:从零开始掌握Python机器学习(附资源)

大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 1. 引言 1.1 教程目的与读者定位 "启程"往往是最具挑战性的一步,特别是在面临众多选择时,人们往往难以做出决策。本教程旨在帮助那些几乎没有Python机器学习基础的初学者成长为知识

「AntV」X6 自定义vue节点(vue3)

官方文档 本篇文档只讲解vue3中如何使用,vue2的可以参考下官方文档 安装插件 @antv/x6-vue-shape 添加vue组件 既然使用vue节点,那么我们就需要准备一个vue的组件,这个组件就是节点的一些样式,根据你们的ui自行写代码即可 节点名称