java整合Mybatis-plus爬取国家统计局省市区街道社区信息进行存储
通过链接进入查询,选择对应的年份,查询各省市区信息。那如何通过java代码进行爬取信息进行数据存储呢?之前有类似需求,并进行了一个笔记整理,如下:
- 引入Jsoup pom依赖
<!-- JSOUP 解析-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
- 创建数据库-实体类(根据需要我只存储街道编号和名字)
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for t_street
-- ----------------------------
DROP TABLE IF EXISTS `t_street`;
CREATE TABLE `t_street` (
`code` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`areaCode` varchar(255) DEFAULT NULL COMMENT '区编号',
`provinceCode` varchar(255) DEFAULT NULL COMMENT '省编号',
`cityCode` varchar(255) DEFAULT NULL COMMENT '市编号',
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- 实体类
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_street")
@ApiModel(value="TStreet", description="")
public class TStreet implements Serializable {
private static final long serialVersionUID=1L;
private String code;
private String name;
@TableField(value = "areaCode")
private String areaCode;
@TableField(value = "provinceCode")
private String provinceCode;
@TableField(value = "cityCode")
private String cityCode;
}
@TableField(Mybatis-plus默认设置了驼峰形式,此注解value对应数据库字段)
- 代码实现
package com.carshow.admin.controller.test;
import com.carshow.admin.pojo.model.TStreet;
import com.carshow.admin.service.IStreetService;
import com.carshow.common.web.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author xw
* @description
* @date 2022/3/21 16:18
*/
@Api(tags = "街道接口")
@RestController
@RequestMapping("/api/v1/street")
@Slf4j
@AllArgsConstructor
public class StreetController {
private IStreetService streetService;
// 固定写法:国家统计局的首页链接
private static final String link = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/";
@ApiOperation(value = "获取街道信息")
@GetMapping("query")
public void query() throws IOException {
// 爬取省份
Document document = Jsoup.connect(link).get();
Elements provincetrAll = document.select(".provincetr");
for(Element provincetr : provincetrAll){
for(Element td:provincetr.children()){
Elements a = td.select("a");
String href = a.attr("href");
// 省名
String name = a.text();
/**
* 可进行省信息存储操作,测试只查询广东省
*/
if(name.equals("广东省")){
getShi(href);
}
}
}
}
// 爬取市
private void getShi(String shiHref) throws IOException {
Document document = Jsoup.connect(link+shiHref).get();
Elements citytrAll = document.select(".citytr");
for(Element citytr:citytrAll){
Element codetd = citytr.child(0);
Element nametd = citytr.child(1);
String href = codetd.select("a").attr("href");
String code = codetd.select("a").text();
String name = nametd.select("a").text();
/**
* 可进行市区信息存储操作,测试只查询深圳市
*/
if(name.equals("深圳市")){
getQu(href,code);
}
}
}
// 爬取区
private void getQu(String countryHref,String cityCode) throws IOException {
Document document = Jsoup.connect(link+countryHref).get();
Elements countryAll = document.select(".countytr");
// 这里的sort没有从0开始增加,是因为市下的第一级为市辖区,该级下无子级,用不着采集。所以直接跳过。
long sort = -1 ;
for(Element countrytr:countryAll){
sort++;
if(sort>0){
Element codetd = countrytr.child(0);
Element nametd = countrytr.child(1);
String href = codetd.select("a").attr("href");
String code = codetd.select("a").text();
String name = nametd.select("a").text();
/**
* 可进行区信息存储操作
*/
getJiedao(href,code);
}
}
}
// 爬取乡镇(街道)
private void getJiedao(String jiedaoHref,String countryCode) throws IOException {
Document document = Jsoup.connect(link+countryCode.substring(0,2)+"/"+jiedaoHref).get();
Elements townAll = document.select(".towntr");
long sort = 0 ;
for(Element towntr:townAll){
Element codetd = towntr.child(0);
Element nametd = towntr.child(1);
String href = codetd.select("a").attr("href");
String code = codetd.select("a").text();
String name = nametd.select("a").text();
/**
* 可进行街道信息存储操作
*/
TStreet street = new TStreet();
street.setCode(code);
street.setName(name);
street.setAreaCode(StringUtils.substring(code,0,6));
street.setProvinceCode(StringUtils.substring(code,0,2));
street.setCityCode(StringUtils.substring(code,0,4));
//也可使用批量插入操作
streetService.save(street);
// getShequ(href,code);
}
}
// 爬取村(社区)
private static void getShequ(String shequHref,String townCode) throws IOException {
String a = townCode.substring(0,2);
String b = townCode.substring(2,4);
Document document = Jsoup.connect(link+a+"/"+b+"/"+shequHref).get();
Elements villagetrAll = document.select(".villagetr");
long sort = 0;
for(Element villagetr:villagetrAll){
Element codetd = villagetr.child(0);
Element nametd = villagetr.child(2);
String code = codetd.text();
String name = nametd.text();
/**
* 可进行社区信息存储操作
*/
}
}
}
所对应的service和mapper为mybatis-plus自动构建
- 测试(因为我只进行存储了街道信息,所以访问测试以及结果如下)
- 请求的时间会比较长,需要耐心等待
- 结果