Java 爬虫同步获取全国统计局省市区代码

引入jar包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.9</version>
</dependency>
<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>
xxljob定时任务
 @XxlJob("syncProvinceCitySchedule")
    public void execute() {
        JSONObject jobParam = JSON.parseObject(XxlJobHelper.getJobParam());
        //参数校验
        validData(jobParam);

        String website = jobParam.getString("website");
        String year = jobParam.getString("year");

        syncProvinceCityService.syncProvinceCity(website, year);

    }

    private void validData(JSONObject jobParam) {
        log.info("provinceCity xxljob request data = {}", jobParam.toJSONString());
        String website = jobParam.getString("website");
        String year = jobParam.getString("year");

        if (StringUtils.isBlank(website) || StringUtils.isBlank(year)) {
            throw new BizException("网址和年份不能为空!!");
        }
    }
代码实现
@Service
@Slf4j
public class SyncProvinceCityServiceImpl implements SyncProvinceCityService {

    public static final String http = "http://www.stats.gov.cn/";
    /**
     * 设置utf-8发现有部分字符有乱码
     */
    public static final String CHARSET = "UTF-8";
    //website 网址 year年份
    @Override
    public void syncProvinceCity(String website, String year) {
        String baseUrl =website + year + "/";
        log.info("国家统计局网址:{}", baseUrl);
        String url = baseUrl + "index.html";
        //如果需要设置代理
        //initProxy("10.10.10.200", "80");
        try {
            String str = getContent(url).toUpperCase();
            String[] arrs = str.split("<A");

            //读取原始json文件
            JSONObject jsonObject = provinceCityVerificationService.getJson();
            for (String s : arrs) {
                if (s.indexOf("HREF") != -1 && s.indexOf(".HTML") != -1) {
                    String pUrl = s.substring(7, s.indexOf("\">"));
                    String province = s.substring(s.indexOf("\">")+2, s.indexOf("<BR />"));
                    log.info("爬取省份:{}", province);
                    JSONObject cityJson = new JSONObject();
                    if(jsonObject.containsKey(province)){
                        cityJson = jsonObject.getJSONObject(province);
                    } else {
                        jsonObject.put(province, cityJson);
                    }
                    boolean success = false;
                    while(!success) {
                        try {
                            readCity(baseUrl, pUrl, cityJson);
                            success = true;
                        } catch (IOException e) {
                            log.error("读取国家统计局市数据异常:{}", e.getMessage());
                            success = false;
                            Thread.sleep(60000);
                        }
                    }

                }
            }
            log.info("读取国家统计局省市区数据:{}", jsonObject.toJSONString());
            saveJSON(jsonObject);
        } catch (Exception e) {
            log.error("读取国家统计局省数据异常:{}", e.getMessage());
        }

    }

    /**
     * 读取市的数据
     * @param url
     * @param cityJson
     */
    private void readCity(String baseUrl, String url, JSONObject cityJson) throws Exception {
        String content = getContent(baseUrl + url).toUpperCase();
        String[] citys = content.split("CITYTR");
        for(int c=1,len=citys.length; c<len; c++){
            String[] strs = citys[c].split("<A HREF=\"");
            String cityUrl = null;
            String areaid = "";
            String city = "";
            for(int si = 1; si < 3; si++){
                //取链接和编码
                if(si == 1){
                    cityUrl = strs[si].substring(0, strs[si].indexOf("\">"));
                    areaid = strs[si].substring(strs[si].indexOf("\">")+2, strs[si].indexOf("</A>"));
                }else{
                    city = strs[si].substring(strs[si].indexOf("\">")+2, strs[si].indexOf("</A>"));
                    log.info("爬取市:{}",city);
                }
            }
            JSONArray cityJsonArray = new JSONArray();
            if(cityJson.containsKey(city)){
                cityJsonArray = cityJson.getJSONArray(city);
            } else {
                cityJson.put(city, cityJsonArray);
            }

            boolean success = false;
            while(!success) {
                try {
                    readDist(baseUrl, cityUrl, cityJsonArray);
                    success = true;
                } catch (IOException e) {
                    log.error("读取国家统计局区数据异常:{}", e.getMessage());
                    success = false;
                    Thread.sleep(60000);
                }
            }
        }
    }

    /**
     * 读区/县的数据
     * @param url
     * @throws Exception
     */
    public void readDist(String baseUrl, String url, JSONArray cityJsonArray) throws Exception{
        String content = getContent(baseUrl + url).toUpperCase();
        String[] citys = content.split("COUNTYTR");
        for(int i=1; i<citys.length; i++){
            String cityUrl = null;
            String areaid = "";
            String district = "";
            //没超链接特殊处理
            if(citys[i].indexOf("<A HREF=\"")==-1){
                areaid = citys[i].substring(6, 18);
                district = citys[i].substring(citys[i].indexOf("</TD><TD>")+9,citys[i].lastIndexOf("</TD>"));
            }else{
                String[] strs = citys[i].split("<A HREF=\"");
                for(int si = 1; si<3; si++){
                    //取链接和编码
                    if(si == 1){
                        cityUrl = strs[si].substring(0, strs[si].indexOf("\">"));
                        areaid = strs[si].substring(strs[si].indexOf("\">")+2, strs[si].indexOf("</A>"));
                    }else{
                        district = strs[si].substring(strs[si].indexOf("\">")+2, strs[si].indexOf("</A>"));
                    }
                }
            }
            log.info("爬取区/县:{}", district);
            if(!cityJsonArray.contains(district)){
                cityJsonArray.add(district);
            }
        }
    }

    /**
     * 读镇的数据
     * @param url
     * @throws Exception
     */
    public static void readZhen(String prix,String url,String paretid) throws Exception{
        String content = getContent(baseUrl+prix+url).toUpperCase();
        String myPrix = (prix+url).substring(0, (prix+url).lastIndexOf("/")+1);
        String[] citys = content.split("TOWNTR");
        for(int i=1; i<citys.length; i++){
            String[] strs = citys[i].split("<A HREF='");
            String cityUrl = null;
            String areaid = "";
            String areaname = "";
            for(int si = 1; si<3; si++){
                if(si==1){//取链接和编码
                    cityUrl = strs[si].substring(0, strs[si].indexOf("'>"));
                    areaid = strs[si].substring(strs[si].indexOf("'>")+2, strs[si].indexOf("</A>"));
 
                }else{
                    areaname = strs[si].substring(strs[si].indexOf("'>")+2, strs[si].indexOf("</A>"));
                }
            }
        
        }
    }
 
    /**
     * 读村/街道的数据
     * @param url
     * @throws Exception
     */
    public static void readCun(String prix,String url,BufferedWriter bw) throws Exception{
        String content = getContent(baseUrl+prix+url).toUpperCase();
        String[] citys = content.split("VILLAGETR");
        for(int i=1; i<citys.length; i++){
            String[] strs = citys[i].split("<TD>");
 
      
        }
    }

    /**
     * 读取城市文件
     * @return
     */
    private JSONObject getJson(){
        try{
            InputStream inputStream = getClass().getResourceAsStream("/省市区.json");
            String json = new BufferedReader(
                    new InputStreamReader(inputStream, StandardCharsets.UTF_8))
                    .lines()
                    .collect(Collectors.joining("\n"));
            log.info("读取原始省市区json文件数据:{}", json);
            return JSONObject.parseObject(json);
        } catch (Exception e) {
            log.error("读取省市区json文件错误:{}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 将省市区数据写入中间库及redis
     * @param data 待写入数据
     *
     */
    public void saveJSON(JSONObject data) {
        //删除redis缓存
        RBucket<Object> bucket =RedisService.getBucket("key");
        bucket.delete();
        
        //保存中间库
        Mapper.insert(data);
        
        //保存redis
        RedisService.setMap("key", data, 30, TimeUnit.DAYS);
    }

   
    /**
     * 设置代理
     * @param host
     * @param port
     */
    public void initProxy(String host, String port) {
        System.setProperty("http.proxyType", "4");
        System.setProperty("http.proxyPort", port);
        System.setProperty("http.proxyHost", host);
        System.setProperty("http.proxySet", "true");
    }
}

省市区json文件样例:

{
	"四川省": {
		"广安市": ["华蓥市", "市辖区", "广安区", "前锋区", "岳池县", "武胜县", "邻水县"],
		"遂宁市": ["船山区", "安居区", "蓬溪县", "大英县", "射洪市", "市辖区", "射洪县"],
		"资阳市": ["乐至县", "市辖区", "雁江区", "安岳县", "简阳市"],
		"甘孜藏族自治州": ["白玉县", "色达县", "乡城县", "德格县", "得荣县", "炉霍县", "雅江县", "石渠县", "巴塘县", "丹巴县", "道孚县", "泸定县", "新龙县", "甘孜县", "理塘县", "九龙县", "稻城县", "康定市", "康定县"],
		"泸州市": ["泸县", "合江县", "叙永县", "古蔺县", "市辖区", "江阳区", "纳溪区", "龙马潭区"],
		"广元市": ["利州区", "昭化区", "朝天区", "旺苍县", "青川县", "剑阁县", "苍溪县", "市辖区", "元坝区", "元坝区"],
		"南充市": ["阆中市", "嘉陵区", "西充县", "高坪区", "市辖区", "蓬安县", "营山县", "仪陇县", "南部县", "顺庆区"],
		"绵阳市": ["市辖区", "涪城区", "梓潼县", "北川羌族自治县", "盐亭县", "安州区", "江油市", "平武县", "游仙区", "三台县", "安县"],
		"眉山市": ["青神县", "市辖区", "东坡区", "彭山区", "仁寿县", "洪雅县", "丹棱县", "彭山县"],
		"巴中市": ["南江县", "平昌县", "巴中经济开发区", "市辖区", "巴州区", "恩阳区", "通江县"],
		"乐山市": ["金口河区", "沙湾区", "井研县", "市辖区", "市中区", "犍为县", "沐川县", "马边彝族自治县", "五通桥区", "峨边彝族自治县", "峨眉山市", "夹江县"],
		"攀枝花市": ["仁和区", "米易县", "盐边县", "市辖区", "东区", "西区"],
		"自贡市": ["大安区", "沿滩区", "荣县", "富顺县", "市辖区", "自流井区", "贡井区"],
		"成都市": ["蒲江县", "市辖区", "青白江区", "成华区", "双流区", "新都区", "新津区", "武侯区", "青羊区", "郫都区", "邛崃市", "简阳市", "彭州市", "大邑县", "金堂县", "锦江区", "龙泉驿区", "温江区", "崇州市", "都江堰市", "金牛区", "新津县", "双流县", "郫县"],
		"内江市": ["威远县", "资中县", "内江经济开发区", "隆昌市", "市辖区", "市中区", "东兴区", "隆昌县"],
		"德阳市": ["什邡市", "绵竹市", "市辖区", "旌阳区", "罗江区", "中江县", "广汉市", "罗江县"],
		"阿坝藏族羌族自治州": ["壤塘县", "马尔康市", "理县", "茂县", "松潘县", "黑水县", "若尔盖县", "红原县", "金川县", "阿坝县", "九寨沟县", "小金县", "汶川县", "马尔康县"],
		"凉山彝族自治州": ["昭觉县", "越西县", "会理市", "木里藏族自治县", "冕宁县", "布拖县", "西昌市", "会东县", "盐源县", "德昌县", "宁南县", "甘洛县", "普格县", "金阳县", "雷波县", "美姑县", "喜德县", "会理县"],
		"雅安市": ["石棉县", "汉源县", "芦山县", "市辖区", "名山区", "荥经县", "天全县", "宝兴县", "雨城区"],
		"宜宾市": ["长宁县", "叙州区", "珙县", "南溪区", "市辖区", "翠屏区", "江安县", "高县", "兴文县", "屏山县", "筠连县", "宜宾县"],
		"达州市": ["万源市", "达州经济开发区", "市辖区", "大竹县", "通川区", "达川区", "开江县", "宣汉县", "渠县", "达县"]
	},
	"新疆维吾尔自治区": {
		"自治区直辖县级行政区划": ["铁门关市", "阿拉尔市", "昆玉市", "北屯市", "可克达拉市", "五家渠市", "新星市", "胡杨河市", "图木舒克市", "石河子市", "双河市"],
		"昌吉回族自治州": ["昌吉市", "阜康市", "呼图壁县", "玛纳斯县", "奇台县", "吉木萨尔县", "木垒哈萨克自治县"],
		"巴音郭楞蒙古自治州": ["尉犁县", "且末县", "轮台县", "和硕县", "若羌县", "库尔勒经济技术开发区", "库尔勒市", "和静县", "焉耆回族自治县", "博湖县"],
		"喀什地区": ["塔什库尔干塔吉克自治县", "莎车县", "麦盖提县", "疏勒县", "巴楚县", "泽普县", "喀什市", "疏附县", "岳普湖县", "伽师县", "英吉沙县", "叶城县"],
		"阿克苏地区": ["沙雅县", "拜城县", "阿克苏市", "库车市", "乌什县", "新和县", "温宿县", "柯坪县", "阿瓦提县", "库车县"],
		"乌鲁木齐市": ["米东区", "头屯河区", "新市区", "沙依巴克区", "达坂城区", "市辖区", "乌鲁木齐县", "天山区", "水磨沟区", "乌鲁木齐经济技术开发区", "乌鲁木齐高新技术产业开发区"],
		"哈密地区": ["巴里坤哈萨克自治县", "伊吾县", "哈密市"],
		"阿勒泰地区": ["阿勒泰市", "布尔津县", "富蕴县", "福海县", "哈巴河县", "青河县", "吉木乃县"],
		"哈密市": ["巴里坤哈萨克自治县", "伊吾县", "伊州区"],
		"塔城地区": ["额敏县", "托里县", "裕民县", "和布克赛尔蒙古自治县", "塔城市", "乌苏市", "沙湾市", "沙湾县"],
		"博尔塔拉蒙古自治州": ["精河县", "温泉县", "博乐市", "阿拉山口市"],
		"吐鲁番地区": ["吐鲁番市", "鄯善县", "托克逊县"],
		"吐鲁番市": ["托克逊县", "高昌区", "鄯善县"],
		"克拉玛依市": ["独山子区", "克拉玛依区", "白碱滩区", "乌尔禾区", "市辖区"],
		"伊犁哈萨克自治州": ["伊宁县", "特克斯县", "奎屯市", "霍城县", "察布查尔锡伯自治县", "尼勒克县", "霍尔果斯市", "新源县", "巩留县", "伊宁市", "昭苏县"],
		"克孜勒苏柯尔克孜自治州": ["阿合奇县", "乌恰县", "阿图什市", "阿克陶县"],
		"和田地区": ["策勒县", "于田县", "民丰县", "和田市", "和田县", "墨玉县", "皮山县", "洛浦县"]
	},
	"北京市": {
		"县": ["密云县", "延庆县", "密云县test", "密云县test"],
		"市辖区": ["石景山区", "丰台区", "朝阳区", "顺义区", "昌平区", "东城区", "海淀区", "平谷区", "门头沟区", "密云区", "房山区", "延庆区", "怀柔区", "通州区", "大兴区", "西城区"]
	},
	"台湾省": {
		"南投县": ["南投市", "草屯镇", "埔里镇", "竹山镇", "集集镇", "名间乡", "国姓乡", "鹿谷乡", "水里乡", "信义乡", "仁爱乡", "鱼池乡", "中寮乡"],
		"嘉义市": ["东区", "西区"],
		"花莲县": ["花莲市", "玉里镇", "凤林镇", "吉安乡", "新城乡", "寿丰乡", "秀林乡", "光复乡", "瑞穗乡", "富里乡", "万荣乡", "卓溪乡", "丰滨乡"],
		"宜兰县": ["宜兰市", "罗东镇", "苏澳镇", "头城镇", "冬山乡", "五结乡", "礁溪乡", "员山乡", "壮围乡", "三星乡", "大同乡", "南澳乡"],
		"澎湖县": ["马公市", "湖西乡", "白沙乡", "西屿乡", "望安乡", "七美乡"],
		"高雄市": ["凤山区", "三民区", "左营区", "前镇区", "楠梓区", "苓雅区", "小港区", "鼓山区", "大寮区", "冈山区", "仁武区", "林园区", "路竹区", "新兴区", "鸟松区", "大树区", "美浓区", "桥头区", "旗山区", "梓官区", "大社区", "茄萣区", "燕巢区", "湖内区", "阿莲区", "旗津区", "前金区", "盐埕区", "弥陀区", "内门区", "永安区", "六龟区", "杉林区", "田寮区", "甲仙区", "桃源区", "那玛夏区", "茂林区"],
		"屏东县": ["屏东市", "潮州镇", "东港镇", "恒春镇", "内埔乡", "万丹乡", "新园乡", "长治乡", "里港乡", "盐埔乡", "高树乡", "枋寮乡", "九如乡", "万峦乡", "佳冬乡", "林边乡", "竹田乡", "崁顶乡", "琉球乡", "麟洛乡", "南州乡", "新埤乡", "车城乡", "满州乡", "三地门乡", "来义乡", "玛家乡", "枋山乡", "泰武乡", "牡丹乡", "狮子乡", "春日乡", "雾台乡"],
		"台北市": ["大安区", "内湖区", "士林区", "文山区", "北投区", "中山区", "信义区", "松山区", "万华区", "中正区", "大同区", "南港区"],
		"台南市": ["永康区", "安南区", "东区", "北区", "南区", "中西区", "新营区", "仁德区", "归仁区", "安平区", "佳里区", "善化区", "麻豆区", "新化区", "新市区", "关庙区", "安定区", "白河区", "学甲区", "盐水区", "西港区", "下营区", "后壁区", "七股区", "六甲区", "官田区", "柳营区", "东山区", "将军区", "玉井区", "北门区", "大内区", "楠西区", "南化区", "山上区", "左镇区", "龙崎区"],
		"新竹市": ["东区", "北区", "香山区"],
		"桃园市": ["桃园区", "中坜区", "平镇区", "八德区", "杨梅区", "芦竹区", "龟山区", "龙潭区", "大溪区", "大园区", "观音区", "新屋区", "复兴区"],
		"彰化县": ["彰化市", "员林市", "和美镇", "鹿港镇", "溪湖镇", "二林镇", "田中镇", "北斗镇", "福兴乡", "花坛乡", "社头乡", "秀水乡", "伸港乡", "大村乡", "永靖乡", "埔心乡", "芳苑乡", "埔盐乡", "埤头乡", "溪州乡", "田尾乡", "芬园乡", "线西乡", "大城乡", "二水乡", "竹塘乡"],
		"苗栗县": ["头份市", "苗栗市", "竹南镇", "苑里镇", "后龙镇", "通霄镇", "卓兰镇", "公馆乡", "铜锣乡", "三义乡", "大湖乡", "造桥乡", "头屋乡", "南庄乡", "西湖乡", "三湾乡", "泰安乡", "狮潭乡"],
		"台东县": ["台东市", "卑南乡", "成功镇", "太麻里乡", "关山镇", "东河乡", "池上乡", "鹿野乡", "长滨乡", "大武乡", "兰屿乡", "海端乡", "绿岛乡", "金峰乡", "延平乡", "达仁乡"],
		"基隆市": ["安乐区", "七堵区", "信义区", "中正区", "中山区", "仁爱区", "暖暖区"],
		"嘉义县": ["朴子市", "太保市", "大林镇", "布袋镇", "民雄乡", "水上乡", "中埔乡", "竹崎乡", "新港乡", "东石乡", "六脚乡", "梅山乡", "义竹乡", "鹿草乡", "溪口乡", "番路乡", "阿里山乡", "大埔乡"],
		"新竹县": ["竹北市", "竹东镇", "新埔镇", "关西镇", "湖口乡", "新丰乡", "芎林乡", "宝山乡", "横山乡", "尖石乡", "北埔乡", "峨眉乡", "五峰乡"],
		"云林县": ["斗六市", "虎尾镇", "西螺镇", "斗南镇", "北港镇", "土库镇", "麦寮乡", "古坑乡", "莿桐乡", "口湖乡", "二仑乡", "元长乡", "水林乡", "仑背乡", "台西乡", "四湖乡", "大埤乡", "林内乡", "东势乡", "褒忠乡"],
		"新北市": ["板桥区", "新庄区", "中和区", "三重区", "新店区", "土城区", "永和区", "芦洲区", "汐止区", "树林区", "淡水区", "三峡区", "林口区", "莺歌区", "五股区", "泰山区", "瑞芳区", "八里区", "深坑区", "三芝区", "万里区", "金山区", "贡寮区", "石门区", "双溪区", "石碇区", "坪林区", "乌来区", "平溪区"],
		"台中市": ["北屯区", "西屯区", "大里区", "太平区", "南屯区", "丰原区", "东区", "南区", "西区", "北区", "中区", "潭子区", "大雅区", "沙鹿区", "清水区", "龙井区", "大甲区", "乌日区", "神冈区", "雾峰区", "梧栖区", "大肚区", "后里区", "东势区", "外埔区", "新社区", "大安区", "石冈区", "和平区"]
	},
	"内蒙古自治区": {
		"鄂尔多斯市": ["鄂托克前旗", "康巴什区", "鄂托克旗", "伊金霍洛旗", "市辖区", "东胜区", "杭锦旗", "乌审旗", "达拉特旗", "准格尔旗"],
		"呼伦贝尔市": ["扎兰屯市", "市辖区", "鄂伦春自治旗", "陈巴尔虎旗", "扎赉诺尔区", "牙克石市", "鄂温克族自治旗", "阿荣旗", "莫力达瓦达斡尔族自治旗", "满洲里市", "新巴尔虎左旗", "额尔古纳市", "新巴尔虎右旗", "根河市", "海拉尔区"],
		"锡林郭勒盟": ["东乌珠穆沁旗", "西乌珠穆沁旗", "多伦县", "锡林浩特市", "苏尼特左旗", "太仆寺旗", "苏尼特右旗", "镶黄旗", "正蓝旗", "正镶白旗", "二连浩特市", "阿巴嘎旗", "乌拉盖管委会"],
		"乌海市": ["海勃湾区", "海南区", "乌达区", "市辖区"],
		"兴安盟": ["阿尔山市", "科尔沁右翼前旗", "科尔沁右翼中旗", "扎赉特旗", "突泉县", "乌兰浩特市"],
		"阿拉善盟": ["额济纳旗", "内蒙古阿拉善高新技术产业开发区", "阿拉善左旗", "阿拉善右旗", "内蒙古阿拉善经济开发区"],
		"呼和浩特市": ["土默特左旗", "市辖区", "玉泉区", "清水河县", "武川县", "托克托县", "赛罕区", "和林格尔县", "呼和浩特经济技术开发区", "回民区", "新城区", "呼和浩特金海工业园区"],
		"巴彦淖尔市": ["市辖区", "临河区", "五原县", "磴口县", "乌拉特前旗", "乌拉特中旗", "乌拉特后旗", "杭锦后旗"],
		"包头市": ["白云鄂博矿区", "土默特右旗", "达尔罕茂明安联合旗", "市辖区", "青山区", "包头稀土高新技术产业开发区", "东河区", "昆都仑区", "石拐区", "九原区", "固阳县"],
		"乌兰察布市": ["兴和县", "察哈尔右翼前旗", "四子王旗", "丰镇市", "市辖区", "察哈尔右翼中旗", "察哈尔右翼后旗", "凉城县", "化德县", "卓资县", "商都县", "集宁区"],
		"赤峰市": ["巴林左旗", "阿鲁科尔沁旗", "巴林右旗", "翁牛特旗", "敖汉旗", "红山区", "林西县", "元宝山区", "松山区", "克什克腾旗", "喀喇沁旗", "市辖区", "宁城县"],
		"通辽市": ["开鲁县", "霍林郭勒市", "科尔沁左翼后旗", "通辽经济技术开发区", "科尔沁左翼中旗", "库伦旗", "奈曼旗", "科尔沁区", "扎鲁特旗", "市辖区"]
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值