安卓天气预报项目(二)之获取中国天气网所有的城市编号

  • Post author:
  • Post category:其他




获取天气预报的数据



所有省份数据

数据来自网络

于是我们瞄准好中国天气网,使用java获得网页内容.

首先我们要获得所有的省份,以及各个省份下的市,以及各个市下面对应的区; 在app打开的一瞬间,得到数据,存放到数据库.



方案一 (失败)

首先我打算找一个中国天气网的api接口,尝试着看看能不能获得所有的城市;

在这里插入图片描述
https://j.i8tq.com/weather2020/search/city.js

果不其然里面是一个城市的以json格式存储.

用Eclispe爬取一下看看

String urlInfo="https://j.i8tq.com/weather2020/search/city.js";
try {
	url=new URL(urlInfo);
    HttpURLConnection connection=(HttpURLConnection)url.openConnection();
    connection.setRequestMethod("GET");
	connection.connect();
 	connection.setReadTimeout(10000);
 	InputStream is=connection.getInputStream();
	BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
	StringBuilder sb=new StringBuilder();
	String line;
	while ((line = br.readLine()) != null) 
		sb.append(line);
	is.close();
	br.close();
	FileWriter f=new FileWriter(new File("城市json.txt"),true);
	BufferedWriter bf=new BufferedWriter(f);bf.write(data);bf.close();
	String data=sb.toString();
	System.out.println(data);
	}catch(Exceptione e){

	}

打印一下网页数据 这里只展示部分数据

{
	"北京": {
		"北京": {
			"北京": {
				"AREAID": "101010100",
				"NAMECN": "北京"
			},
			"海淀": {
				"AREAID": "101010200",
				"NAMECN": "海淀"
			},
			"朝阳": {
				"AREAID": "101010300",
				"NAMECN": "朝阳"
			},
			"顺义": {
				"AREAID": "101010400",
				"NAMECN": "顺义"
			}
		}
	}	
}

想要通过json进行解析都非常麻烦,需要所有城市都拿取一遍 因为不是数组的格式,而是一个一个单独的对象,解析所有城市不太可能.

{
    "city_data": [
        {
            "浙江省": [
                {
                    "温州市": [
                        {
                            "x县": [
                                {
                                    "AREAID": "101010100",
                                    "NAMECN": "北京"
                                }
                            ]
                        },
                        
                        {
                            "y县": [
                                {
                                    "AREAID": "101010101",
                                    "NAMECN": "北京"
                                }
                            ]
                        }
                    ]
                },
                {
                    "杭州市": [
                        {
                            "xx县": [
                                {
                                    "AREAID": "101010100",
                                    "NAMECN": "北京"
                                }
                            ]
                        },
                        {
                            "yy县": [
                                {
                                    "AREAID": "101010101",
                                    "NAMECN": "北京"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

尝试自己把json内容改成数组的格式 但是无法确定 右括号 ] 的位置;

无法使用gson格式进行加载,因为两个省份和市的的名字重复,并且需要建立所有的区的对象,数据量较大.



方案二(启发)

只能靠前辈们留下的数据了

https://blog.csdn.net/ljheee/article/details/54134621?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-8&spm=1001.2101.3001.4242

有前辈们从以前的接口里面爬到了数据.xml !!

可以通过直接解析xml文件直接获得所有的省份!!!

并且通过解析我们能够非常轻易的获得所有分开的的省份,市级,县级 能够轻易得到对应的id

于是我去下载了这样的一个文件,看了一下他的算法.非常令人可惜的是,代码是通过读取一个txt文件,

把所有的城市数据在读出来.非常可惜不是最根本的方法.并且也存在城市信息不全的问题…

<China>
  <province id="01" name="北京">
    <city id="0101" name="北京">
      <county id="010101" name="北京" weatherCode="101010100"/>
      <county id="010102" name="海淀" weatherCode="101010200"/>
      <county id="010103" name="朝阳" weatherCode="101010300"/>
      <county id="010104" name="顺义" weatherCode="101010400"/>
      <county id="010105" name="怀柔" weatherCode="101010500"/>
      <county id="010106" name="通州" weatherCode="101010600"/>
      <county id="010107" name="昌平" weatherCode="101010700"/>
      <county id="010108" name="延庆" weatherCode="101010800"/>
      <county id="010109" name="丰台" weatherCode="101010900"/>
      <county id="010110" name="石景山" weatherCode="101011000"/>
      <county id="010111" name="大兴" weatherCode="101011100"/>
      <county id="010112" name="房山" weatherCode="101011200"/>
      <county id="010113" name="密云" weatherCode="101011300"/>
      <county id="010114" name="门头沟" weatherCode="101011400"/>
      <county id="010115" name="平谷" weatherCode="101011500"/>
    </city>
  </province>

有一天我突然看到中国天气网的城市
在这里插入图片描述

为什么不可以自己把所有的城市按城市编号进行爬取一遍获得城市的省和市!!!

动手敲代码

从北京101010100到台湾的云林101340406 总共需要访问网页近30w次,非常恐怖的数字;

我的笔记本试过了从开始的1k次 平均1秒能达到6次访问,到后面平均1秒访问1.5次,怕是跑个2天差不多.

于是找一下技巧



1

所有城市编号的倒数第4位没有超过2 例如01021600 顶多16个城市


2

所有以市开头的省份 城市代码均相差100,一定以00结尾 ; 否则相差1,但并不是都是以1结尾,仅有一个城市是以1结尾,我忘了


3

和省份同名的城市会显示城区



4

特别注意海南地区
在这里插入图片描述
是没有市的!!

上代码!! 注意当时没有想到另外一种方法 就是当一个省份的读取完了之后

直接将i 赋值为另外一个城市的 城市编码 进行跳转, 这样的速度非常快

当然如果你直接使用这种方式 我建议你把内容写进文件里面,

因为在控制台里面字符显示不够长

我是这样每次读完一个省份我就终止程序 手动更新i的数值,然后得到城市

		String ncity = "";
		String npro = "";
		String ncoun = "";
		HttpURLConnection connection;
		for (long i = 101010100; i <= 101340406;i+=1) {
			//在这里
			int flag=1;
			String k = String.valueOf(i);
			if(k.charAt(5)>=50){
				i=i/10000;
				i=(i+1)*10000;
			} 
			String urlInfo = "http://www.weather.com.cn/weather/" + i + ".shtml";
			URL url;
			try {
				url = new URL(urlInfo);
				connection = (HttpURLConnection) url.openConnection();
//				connection.setRequestMethod("GET");
				connection.connect();
				connection.setReadTimeout(100);
				InputStream is = connection.getInputStream();
				BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
				StringBuilder sb = new StringBuilder();
				String line;
				while ((line = br.readLine()) != null) {
					if(line.equals("<!-- empty -->")) {flag=0;connection.disconnect();break;}
					sb.append(line);
				}
				if(flag==0)continue;
				is.close();
				br.close();
				String data = sb.toString();
				String coun = null;
				String city = null;
				String pro = null;
				try {
					String info = null;
					if (i <= 101044100||(i>=101310101&&i<=101320103)) {
						info = null;
						info = data.split("div class=\"crumbs fl\">")[1];
						city = pro = info.split("</a>")[1].split("target=\"_blank\">")[1];
						coun = info.split("<span>></span>")[1].split("</span>")[0].split("<span>")[1];
					}
					// 离谱居然有一个是&gt
					else {
							info = data.split("div class=\"crumbs fl\">")[1];
							pro = info.split("</a>")[1].split("target=\"_blank\">")[1];	
							city = info.split("</a>")[2].split("target=\"_blank\">")[1];
							coun = info.split("<span>></span>")[2].split("</span>")[0].split("<span>")[1];// 离谱居然有一个是&gt
						}	
						if (coun.equals("城区"))	coun = city;
						if (!npro.equals(pro)) {
							System.out.println("</province>");
						}
						if (!npro.equals(pro)) {
							npro = pro;
							System.out.println("<province id=\"" + k.substring(3, 5) + "\" name=\"" + pro + "\">");
						}
						if (!ncity.equals(city)) {
							System.out.println("  </city>");
						}
						if (!ncity.equals(city)) {
							ncity = city;
							System.out.println("  <city id=\"" + k.substring(3, 7) + "\" name=\""+city+"\">");
						}
						System.out.println("    <county id=\"" + k.substring(3) + "\" " + "name=\"" + coun + "\" "
								+ "weatherCode=\"" + i + "\"/>");
					}
				 catch (Exception e) {
				}

			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	</city>
</province>
<province id="01" name="北京"> 
    <city id="0101" name="北京"> 
      <county id="010100" name="北京" weatherCode="101010100"/>  
      <county id="010200" name="海淀" weatherCode="101010200"/>  
      <county id="010300" name="朝阳" weatherCode="101010300"/>  
      <county id="010400" name="顺义" weatherCode="101010400"/>  
      <county id="010500" name="怀柔" weatherCode="101010500"/>  
      <county id="010600" name="通州" weatherCode="101010600"/>  
      <county id="010700" name="昌平" weatherCode="101010700"/>  
      <county id="010800" name="延庆" weatherCode="101010800"/>  
      <county id="010900" name="丰台" weatherCode="101010900"/>  
      <county id="011000" name="石景山" weatherCode="101011000"/>  
      <county id="011100" name="大兴" weatherCode="101011100"/>  
      <county id="011200" name="房山" weatherCode="101011200"/>  
      <county id="011300" name="密云" weatherCode="101011300"/>  
      <county id="011400" name="门头沟" weatherCode="101011400"/>  
      <county id="011500" name="平谷" weatherCode="101011500"/>  
      <county id="011600" name="东城" weatherCode="101011600"/>  
      <county id="011700" name="西城" weatherCode="101011700"/> 
    </city> 
  </province>  

最后得到这样的数据, 我没有打全否则太长了

手动把开头的那两行删掉 头加一个 尾巴加一个

不要计较那么多啦,有数据就行了. 其中也有一些地区明明是一个市级下面的却不连续的,

只能进行手动修改

类似于!

//		长春地区无
//		<city id="0601" name="长春">
//		<city id="2216" name="巢湖">
		
		
//		  <city id="0812" name="锡林郭勒">
//		    <county id="081206" name="锡林郭勒" weatherCode="101081206"/>
//		  </city>
//		  <city id="0812" name="乌鲁木齐">
//		    <county id="081207" name="水磨沟" weatherCode="101081207"/>
//		  </city>
//		 <city id="2820" name="茂名">
//		 <city id="2821" name="汕尾">
		
//		 <city id="1304" name="乌鲁木齐">
//	     <county id="130403" name="米东" weatherCode="101130403"/>

//		 <city id="1407" name="那曲">
//	    <county id="140703" name="申扎" weatherCode="101140703"/>
//	    </city>

所以即使用了这种方法还需要手动检查一遍

但是因为我是一个一个省份手动复制粘贴,所以这一类的数据还是能及时发现的

所有城市文件我还没有上传, 如果有人需要的话,和我私信吧

既然都看到这里了,给我点个赞吧



版权声明:本文为qq_46056214原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。