实现省市区镇四级联动选择器(地址选择)
1.简介
由于学习要求,每次做注册,地址选择时,都需要省市区镇四级联动选择器 ,到网上下载很难找到合适的资源,即使有,但资源都是往年的,没有实时更新。
所以,我们将利用Java Jsoup爬虫技术和jQuery,html实现一个自己的现省市区镇四级联动选择器。
效果图
2.省市区镇数据的来源
使用Jsoup Java爬虫技术
jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
资源来自:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/
导入jar包
<!-- Java爬虫包-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>
<!-- 实体类包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.3</version>
</dependency>
主要代码
/**
* @author xieyongfeng
*/
public class CityAll {
private List<City> cityList = new ArrayList<>();
private List<City> cityList1 = new ArrayList<>();
private List<City> cityList2 = new ArrayList<>();
/**
* @return 地区表
*/
public List<Area> getCity(){
List<Area> areaList = new ArrayList<>();
try {
//构建请求头
Connection.Response execute = getHtml("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/index.html");
assert execute != null;
Document document = execute.parse();
//遍历省份
Elements provincetrs = document.getElementsByClass("provincetr");
int index=0;
for (Element provincetr : provincetrs) {
for (Element a : provincetr.getElementsByTag("a")) {
String[] split = a.getElementsByTag("a").eq(0).attr("href").split("\\.");
String cityId=split[0];
String url = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/"+a.getElementsByTag("a").eq(0).attr("href");
String cityName = a.getElementsByTag("a").eq(0).text();
//"网址:"+url+" 地区名:"+cityName;
//遍历citytr
List<Area> areaList1 = getArea(new City(url, cityName), "citytr","http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/");
areaList.add(new Area(cityId,cityName,areaList1));
System.out.print("------------------------------------省份:"+cityName+" id:"+cityId);
//遍历countytr
//cityList1.removeAll(cityList1);
cityList1.addAll(cityList);
cityList.removeAll(cityList);
for (int i = 0; i < cityList1.size(); i++) {
List<Area> areaList2 = getArea(cityList1.get(i), "countytr", "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/" + cityId + "/");
areaList.get(index).getAreaList().get(i).setAreaList(areaList2);
System.out.println(" --------------城市:"+cityList1.get(i).getCityName());
//遍历towntr
cityList2.removeAll(cityList2);
cityList2.addAll(cityList);
cityList.removeAll(cityList);
for (int j = 0; j < cityList2.size(); j++) {
if(cityList2.get(j).getUrl()==null||cityList2.get(j).getUrl().equals("")){
}else {
List<Area> areaList3 = getArea(cityList2.get(j), "towntr", "");
areaList.get(index).getAreaList().get(i).getAreaList().get(j).setAreaList(areaList3);
}
System.out.print(" 地区:"+cityList2.get(j).getCityName());
System.out.println();
}
}
index++;
cityList.removeAll(cityList);
cityList1.removeAll(cityList1);
cityList2.removeAll(cityList2);
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return areaList;
}
/**
* @param city
* @param className
* @param sufferUrl
* @return
*/
private List<Area> getArea(City city,String className,String sufferUrl){
List<Area> areaList = new ArrayList<>();
cityList.removeAll(cityList);
//遍历省份
try{
Connection.Response response = getHtml(city.getUrl());
Document document = response.parse();
//遍历city
String cityId=null;
String cityName=null;
String url=null;
Elements citytr = document.getElementsByClass(className);
for (Element element : citytr) {
//解析city
Elements td = element.getElementsByTag("td");
for (int i = 0; i < td.size(); i++) {
//获取用区划代码,city名
//判断是否有<a>标签
if(td.get(i).getElementsByTag("a").text().equals("")){
//否
//分别获取用区划代码与city名
if(i==0){
//获取用区划代码
cityId = td.get(0).text();
}else if (i==1){
//获取city名
cityName = td.get(1).text();
}
}else{
//是
//分别获取用区划代码与city名
if(i==0){
//获取用区划代码
cityId = td.get(0).getElementsByTag("a").text();
}else if (i==1){
//获取city名
cityName = td.get(1).getElementsByTag("a").text();
//获取url
url = sufferUrl+td.get(1).getElementsByTag("a").attr("href");
}
}
}
//cityId
//cityName
// url
//打包AreaList
areaList.add(new Area(cityId,cityName,new ArrayList<>()));
//打包cityList
cityList.add(new City(url,cityName));
}
}catch (Exception e){
System.out.println(e.getMessage());
}
return areaList;
}
/**
* @param url
* @return Connection
*/
private Connection.Response getHtml(String url){
//构建请求头
try {
return Jsoup.connect(url)
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
.header("Accept-Encoding", "gzip, deflate")
.header("Accept-Language", "zh-CN,zh;q=0.9")
.header("Cookie", "SF_cookie_1=37059734; _trs_uv=l0g4jh8f_6_eeaf; _trs_ua_s_1=l0g4jh8f_6_ky27")
.header("Referer", "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/")
.header("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Mobile Safari/537.36")
.method(Connection.Method.GET)
.execute();
} catch (IOException e) {
System.out.println(e.getMessage());
}
return null;
}
}
需要的实体类
/**
* @date 省份实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class City {
private String url;
private String cityName;
}
/**
* @date 地区实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Area {
private String areaId;
private String areaName;
private List<Area> areaList;
}
打包
//调用方法
List<Area> city = new CityAll().getCity();
//转为Json
String str= JSON.toJSON(city).toString();
System.out.println(str);
FileOutputStream fileOutputStream = null;
//保存至本地
try {
//地址
fileOutputStream = new FileOutputStream("D:\\图片\\city.json");
fileOutputStream.write(str.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
执行打包后,将会生成一个city.json文件。在主页搜索
省市区镇四级联动选择器
可下载资源包接下来就是html的数据处理,渲染。
html的数据处理,渲染
使用Jquery库,导入jquery.js文件
<script src="http://www.kaylee.cool:8080/xieyongfeng/jquery.js"></script>
使用jquery.ajax获取city.json文件
$.get({
url:"city.json", //文件地址
success: function (data) {
province=data;
provinceList();
}
});
html代码
<select id="province">
<option value="0">请选择省份..</option>
</select>
<span id="city-span"></span>
<span id="country-span"></span>
<span id="town-span"></span>
<br>
<hr>
<span id="outAddress"></span>
js代码
let province;
let city;
let country;
let town;
let provinceName;
let cityName;
let countryName;
let townName;
let address;
$.get({
url:"city.json", //文件地址
success: function (data) {
province=data;
provinceList();
}
});
//遍历省份
function provinceList() {
for(let i=0;i<province.length;i++){
//Dom操作 添加省份
$("#province").append("<option id='"+province[i].areaId+"'>"+province[i].areaName+"</option>");
}
//初始化
$("#city-span").html("");
$("#country-span").html("");
$("#town-span").html("");
}
//省份选择处理
$("#province:first").change(function(){
//初始化地址
address="";
$("#outAddress").html("");
//获取以选择的省份
provinceName=$("#province:first").val();
//遍历省份
for(let i=0;i<province.length;i++){
//判断对应省份
if(province[i].areaName===provinceName){
city = province[i].areaList;
break;
}
}
//遍历城市
$("#city-span").html("<select id='city'><option>请选择城市..</option></select>");
for (let i = 0; i < city.length; i++) {
//Dom操作 添加城市
$("#city").append("<option id='"+city[i].areaId+"'>"+city[i].areaName+"</option>");
}
reload_country();
//初始化
$("#country-span").html("");
$("#town-span").html("");
});
//重新加载js //城市选择处理
function reload_country() {
//城市选择处理
$("#city:first").change(function() {
//初始化地址
address="";
$("#outAddress").html("");
//获取以选择的城市
cityName=$("#city:first").val();
//遍历城市
for(let i=0;i<city.length;i++){
//判断对应城市
if(city[i].areaName===cityName){
country = city[i].areaList;
break;
}
}
//遍历地区
$("#country-span").html("<select id='country'><option>请选择地区..</option></select>");
for (let i = 0; i < country.length; i++) {
//Dom操作 添加城市
$("#country").append("<option id='"+country[i].areaId+"'>"+country[i].areaName+"</option>");
}
reload_town();
//初始化
$("#town-span").html("");
});
}
//重新加载js //地区选择处理
function reload_town() {
//地区选择处理
$("#country:first").change(function() {
//初始化地址
address="";
$("#outAddress").html("");
//获取以选择的地区
countryName=$("#country:first").val();
//遍历地区
for(let i=0;i<country.length;i++){
//判断对应地区
if(country[i].areaName===countryName){
town = country[i].areaList;
break;
}
}
//无城镇信息
if(town.length===0){
address=provinceName+" "+cityName+" "+countryName;
$("#outAddress").html(address);
return;
}
//遍历城镇
$("#town-span").html("<select id='town'><option>请选择城镇..</option></select>");
for (let i = 0; i < town.length; i++) {
//Dom操作 添加城镇
$("#town").append("<option id='"+town[i].areaId+"'>"+town[i].areaName+"</option>");
}
outAddress();
});
}
//输出地址
function outAddress() {
//获取城镇
$("#town:first").change(function() {
townName=$("#town:first").val();
//打印地址
address=provinceName+" "+cityName+" "+countryName+" "+townName;
$("#outAddress").html(address);
});
}
编写完成后,打开浏览器,测试
最终效果图
这样我们就拥有自己的
省市区镇四级联动选择器
了,当想更新数据时,将网址的2021更改就行了,http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/
2021
/
在主页搜索
省市区镇四级联动选择器
可下载资源包