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

一、摘要

说起网络爬虫,相信大家都不陌生,又俗称网络机器人,指的是程序按照一定的规则,从互联网上抓取网页,然后从中获取有价值的数据,随便在网上搜索一下,排在前面基本都是 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 也很强的更多相关文章

  1. 用python做爬虫的例子

    主要就是用了两个库,urllib和BeautifulSoup. 作用是从HTML中解析出解梦的查询词和具体的解释. # -*- coding: utf-8 -*- import urllib, url ...

  2. Python爬虫之用Selenium做爬虫

    我们在用python做爬虫的时候,除了直接用requests的架构,还有Scrapy.Selenium等方式可以使用,那么今天我们就来聊一聊使用Selenium如何实现爬虫. Selenium是什么? ...

  3. Python做简单爬虫(urllib.request怎么抓取https以及伪装浏览器访问的方法)

    一:抓取简单的页面: 用Python来做爬虫抓取网站这个功能很强大,今天试着抓取了一下百度的首页,很成功,来看一下步骤吧 首先需要准备工具: 1.python:自己比较喜欢用新的东西,所以用的是Pyt ...

  4. 使用python做最简单的爬虫

    使用python做最简单的爬虫 --之心 #第一种方法import urllib2 #将urllib2库引用进来response=urllib2.urlopen("http://www.ba ...

  5. 12岁的少年教你用Python做小游戏

    首页 资讯 文章 频道 资源 小组 相亲 登录 注册       首页 最新文章 经典回顾 开发 设计 IT技术 职场 业界 极客 创业 访谈 在国外 - 导航条 - 首页 最新文章 经典回顾 开发 ...

  6. Python 正则表达式 (python网络爬虫)

    昨天 2018 年 01 月 31 日,农历腊月十五日.20:00 左右,152 年一遇的月全食.血月.蓝月将今晚呈现空中,虽然没有看到蓝月亮,血月.月全食也是勉强可以了,还是可以想像一下一瓶蓝月亮洗 ...

  7. Python数据挖掘(爬虫强化)

    (我喜欢雨天,因为雨天我可以回到童年踩水花!哈!) 2018年 --7月--12日 : 多云又暴雨 T—T 前言 我要把爬虫的终极利器介绍一下,这个只要是我们肉眼能看到的,就算在源码中或者在json中 ...

  8. python 网络爬虫概念与HTTP(s)协议

    1. 爬虫相关概念 1.1 定义 爬虫就是通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程 1.2 主流语言实现爬虫优劣 php:可以实现爬虫.但是php在实现爬虫中支持多线程和多进程方面 ...

  9. 爬虫(二)Python网络爬虫相关基础概念、爬取get请求的页面数据

    什么是爬虫 爬虫就是通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程. 哪些语言可以实现爬虫    1.php:可以实现爬虫.php被号称是全世界最优美的语言(当然是其自己号称的,就是王婆 ...

  10. python beautifulsoup爬虫

    爬虫这个听起来很 hack 的名字,是我学习 python 的诱因.当 python 基础学习到一定程度(基本语法,数据类型掌握) 就可以开启自己的小爬虫了.毕竟实践才是提高的最快途径.废话说完了,下 ...

随机推荐

  1. 每天5分钟复习OpenStack(十三)存储缓存技术Bcache

    Ceph作为一个分布式存储,在项目中常见的形态有两者,一种是采用 SSD 或NVME 磁盘做Ceph的日志盘,使用SATA磁盘来做数据盘.这样的好处是比较经济实惠.另一种则是全部采用 SSD 或NVM ...

  2. 修复 VisualStudio 构建时没有将 NuGet 的 PDB 符号文件拷贝到输出文件夹

    本文告诉大家如何修复 VisualStudio 构建时没有将 NuGet 的 PDB 符号文件拷贝到输出文件夹的问题.如果 VisualStudio 构建时没有将 NuGet 的 PDB 符号文件拷贝 ...

  3. 2018-11-19-win10-uwp-使用-Azure-DevOps-自动构建

    title author date CreateTime categories win10 uwp 使用 Azure DevOps 自动构建 lindexi 2018-11-19 15:26:4 +0 ...

  4. Spring Boot应用中如何动态指定数据库,实现不同用户不同数据库的场景

    当在 Spring Boot 应用程序中使用Spring Data JPA 进行数据库操作时,配置Schema名称是一种常见的做法.然而,在某些情况下,模式名称需要是动态的,可能会在应用程序运行时发生 ...

  5. netcore5下js请求跨域

    后端代码如下: using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System ...

  6. NASM中的ALIGN ALIGNB SECTALIGN

    ALIGN与ALIGNB NASM中的ALIGN与ALIGNB是用来字节对齐的,它们接收2个参数,第一个参数是必须的,表示对齐的字节数(必须是2的幂),第二个参数是可选的,表示为了对齐而进行填充的内容 ...

  7. 7月 Splashtop上线了这些新功能 快来看鸭

    经过我们的攻城狮天天努力,我们的软件又得到了升级和完善,上线了一些有用的新功能和增强功能,快来看看吧. Splashtop已为Splashtop Business Access,Splashtop远程 ...

  8. VisualStduio如何自定义代码片段

    什么是代码片段 代码片段又叫CodeSnippet,可以用来快捷补全代码.其实我们经常使用这个功能. 比如for循环,输入for会弹出这个窗口 我们选择第二个for,再按两次Tab键,编辑器就会自动生 ...

  9. 关于MySQL数据库大字符串存取 类型选择

    摘自:https://blog.csdn.net/weixin_40485506/article/details/83588169 关于MySQL数据库存储大字符串类型长度 根据所要存取字符长度及My ...

  10. 【前端】css js 全屏 esc退出全屏 滚动条隐藏 兼容火狐,文字超出容器长度省略号显示

    全屏 if (docElm.requestFullscreen) { docElm.requestFullscreen(); } else if (docElm.msRequestFullscreen ...