将天气抓取到数据库并通过ip以及城市行政编码获取当前城市天气

思路

首先需要获得访问者的ip所在城市,之后通过该城市获得当前天气信息,而天气数据通过定时任务的形式定时爬取到本地数据库。

实现过程

获取访问者ip对应城市信息

通过太平洋网络提供的API接口以在页面script访问的形式获得json

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="referrer" content="no-referrer"/>
		<title></title>
	</head>
	<body>
	</body>
	<script>
		function ipJson(obj) {
			console.log(obj) 
			//获得的json,注意在head里面添加<meta name="referrer" content="no-referrer"/>
		}
	</script>
	<script src="http://whois.pconline.com.cn/ipJson.jsp?callback=ipJson"></script>
</html>

获得的json数据大致是这样的,接下来我用到的只是citycode这个参数,通过这个参数去请求后台接口获取当地天气

{
    "ip":"210.51.167.169",
    "pro":"北京市",
    "proCode":"110000",
    "city":"北京市",
    "cityCode":"110000",
    "region":"大兴区",
    "regionCode":"110115",
    "addr":"北京市大兴区 亦庄联通通泰IDC机房(亦庄经济技术开发区北环东路一号联通国际大厦)",
    "regionNames":"",
    "err":""
}

数据库

通过各种百度寻找,找到了这个行政编码数据库,然后根据这个天气预报插件定制中各个城市对应的值,增加了几个所需要的字段,这里我只填写了市级对应的weatherid
新增字段

  • WeatherId:天气插件的城市id
  • HighTemperature:最高气温
  • LowTemperature:最低气温
  • CityShow:显示的城市名称
  • WeatherText:天气状况
  • Icon:天气状况图标

这是数据库地址

天气抓取

通过对这个天气插件的爬取获得到对应地区的天气信息,然后存储到数据库,传递参数py=城市id就可以获得对应城市天气了,该部分运用了jsoup这个html解析器,通过分析天气插件的html,可以将我们所需要的部分从中取出。
在这里插入图片描述
这里由于需要通过代理连接网络,所以写了连接代理的部分,这样就获得到了对应城市的天气信息。

public class GetWeather {

    public Document getDocument (String url){
        System.setProperty("http.proxySet", "true");
        System.getProperties().put("http.proxyHost", "代理地址");
        System.getProperties().put("http.proxyPort", "代理端口");
        setDefaultAuthentication();
        String  agent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)"
                    + "  Chrome/56.0.2924.87 Safari/537.36" ;
        try {
            return Jsoup.connect(url).ignoreContentType(true)
                    .userAgent(agent)
                    .ignoreHttpErrors(true)
                    .timeout(10000).get();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void setDefaultAuthentication() {
        BasicAuthenticator auth = new BasicAuthenticator("代理账号", "密码");
        Authenticator.setDefault(auth);
    }

    public static class BasicAuthenticator extends Authenticator {
        String userName;
        String password;
        public BasicAuthenticator(String userName, String password) {
            this.userName = userName;
            this.password = password;
        }
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(userName, password.toCharArray());
        }
    }

    public static MyWeather getWeather (String py,int time){
        GetWeather t = new GetWeather();
        String url = "http://i.tianqi.com/index.php?c=code&a=getcode&id=35&py=" + py;
        Document doc = t.getDocument(url);
        Boolean flag = false;
        // 判断是否访问成功
        try {
            flag = new String(doc.select("title").text().getBytes(),"utf-8").indexOf(new String("天气预报".getBytes(),"utf-8")) != -1 && doc != null;
        } catch (IOException e) {
            e.printStackTrace();
        }
        MyWeather myWeather = new MyWeather();
        // 获取目标HTML代码
        if(flag) {
            Elements elements1 = doc.select("li");
            // 高的温度
            Elements elements2 = elements1.select("p");
            String highTemperature = elements2.get(0).text() + "°C";
            // 低的温度
            String lowTemperature1 = elements2.get(1).text().substring(1);
            String lowTemperature = lowTemperature1.substring(0, lowTemperature1.length() - 1) + "°C";
            // 城市
            String cityShow = elements2.get(2).text();
            // 天气及风向
            String setWeatherText = elements1.get(1).text();
            Elements elements3 = doc.select(".pngtqico");
            String icon = elements3.attr("src").substring(elements3.attr("src").lastIndexOf("/")+1);
            myWeather.setCityShow(cityShow);
            myWeather.setHighTemperature(highTemperature);
            myWeather.setLowTemperature(lowTemperature);
            myWeather.setWeatherText(setWeatherText);
            myWeather.setIcon(icon);
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return myWeather;

        } else {
            return null;
        }
    }
}

定时任务及天气获取

定时任务这里运用了Spring Task,做了一个简单的每隔一个小时进行一次的抓取

AlarmTask
@Component
@EnableScheduling
public class AlarmTask {

    @Resource
    private WeatherService weatherService;

    /**
     * 默认是fixedDelay 上一次执行完毕时间后执行下一轮
     */
    @Scheduled(cron = "0 0 * * * ?")
    public void run() throws InterruptedException {

        weatherService.start();
    }

}
WeatherService
@Service
public class WeatherService {

    @Resource
    MyWeatherMapper mapper;

    public MyWeather getWeather(int Id){
        MyWeather myWeather = mapper.getWeather(Id);
        //所在城市对应城市id是否为空,如果为空就找他的父级城市
        if(myWeather != null && ("null".equals(String.valueOf(myWeather.getCityShow())) || "".equals(myWeather.getCityShow()+""))){
            myWeather = getWeather(myWeather.getParentId());
        }

        return myWeather;
    }

    public void start(){
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        long start = System.currentTimeMillis();
        System.out.println("=====================开始执行天气抓取:"+ df.format(start) +"========================");
        List<MyWeather> weatherList = mapper.getAllWeatherId();//获得数据库中所有的城市id
        ExecutorService exec = Executors.newFixedThreadPool(5);//5个线程执行
        for (MyWeather weather:weatherList){
            try {
                exec.execute(() -> {
                    MyWeather getWeatherList = GetWeather.getWeather(weather.getWeatherId(),1000);//遍历爬取,延时1000毫秒
                    getWeatherList.setWeatherId(weather.getWeatherId());
                    if (getWeatherList != null){
                        mapper.updateWeather(getWeatherList);//将获取到的天气信息存储到数据库
                        System.out.println(getWeatherList.getCityShow());
                    }
                });
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        exec.shutdown();

        while (true){
            if (exec.isTerminated()){
                break;
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("=====================本次执行结束:"+ df.format(end) +"========================");
        System.out.println("用时:"+((float)(end-start)/1000)+"秒");

    }
}
MyWeatherMapper
@Mapper
public interface MyWeatherMapper {

    List<MyWeather> getAllWeatherId();

    void updateWeather(MyWeather getWeatherList);

    MyWeather getWeather(int Id);

}
mapper.xml
    <select id="getAllWeatherId" resultMap="MyWeather">
        select distinct WeatherId from weather
        <where>
            WeatherId IS NOT NULL and WeatherId != ''
        </where>
    </select>

    <select id="getWeather" resultMap="MyWeather">
        select * from weather
        <where>
            Id=#{Id}
        </where>
    </select>

    <update id="updateWeather" parameterType="com.tanzhi.weather.entity.MyWeather">
        update weather
        <set>
            <if test="CityShow != null">CityShow=#{CityShow},</if>
            <if test="HighTemperature != null">HighTemperature=#{HighTemperature},</if>
            <if test="LowTemperature != null">LowTemperature=#{LowTemperature},</if>
            <if test="WeatherText != null">WeatherText=#{WeatherText},</if>
            <if test="Icon != null">Icon=#{Icon}</if>
        </set>
        where WeatherId=#{WeatherId}
    </update>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值