使用Python爬取全国各地城市的天气数据

思路

1、使用json框架解析出城市的编码
2、使用pymysql框架操作mysql数据库
3、每个循环里面代码逻辑如下:
1)得到城市的编码
2)如果编码为空,说明是省份,使用continue进入下个循环
3)发送查看该城市天气的请求
4)使用json框架解析天气接口返回的数据
5)将该城市的天气数据导入数据库
image.png
image.png

遇到的问题

很多城市的天气爬取失败。使用浏览器请求接口,结果如下:
image.png

原因分析

频繁请求天气接口,导致ip被封。
image.png

解决方案

循环里面设置等待1秒,这样爬虫就会每隔1秒钟发送一次请求(每分钟的请求次数大约60次,低于阈值300次)

sleep(1)

数据分析

实时温度最高的城市

select * from weatherinfo 
where convert(wendu,decimal) = (select max(convert(wendu,decimal)) from weatherinfo);

image.png
实时温度最低的城市

select * from weatherinfo 
where convert(wendu,decimal) = (select min(convert(wendu,decimal)) from weatherinfo);

image.png
二十大高温城市

select * from weatherinfo order by convert(wendu,decimal) desc limit 0,20;

image.png
十大低温城市

select * from weatherinfo order by convert(wendu,decimal) limit 0,10;

image.png

城市编码错误,接口返回403结果码

image.png

完整代码

如下:

# -*- coding: utf-8 -*-

from requests import *
from json import *
from pymysql import *
import traceback
from time import *


def f():
    # 请求城市的接口
    res = get('http://cdn.sojson.com/_city.json')
    # 打印响应头
    # print res.headers
    # 打印响应正文
    # print res.text
    cities = loads(res.text)
    # 连接数据库
    conn = connect('192.168.0.124', 'root', '123456', 'weather', charset='utf8')
    # 获取游标
    cursor = conn.cursor()
    for city in cities:
        cid = city['city_code']
        if cid == '':
            continue
        url = 'http://t.weather.itboy.net/api/weather/city/{0}'.format(cid)
        # print(url)
        quality = ''
        pm25 = -1
        pm10 = -1
        shidu = ''
        try:
            # 请求天气的接口
            res = get(url)
            # 等待1秒
            sleep(1)
            # 将响应正文转成字典对象
            obj = loads(res.text)
            data = obj['data']
            cityinfo = obj['cityInfo']
        except KeyError:
            print(url)
            print(res.text)
            if 'too many requests' in res.text:
                print(u'ip可能被封')
                break
            else:
                continue
        except:
            print(url)
            print(u'网络异常')
            traceback.print_exc()
            continue
        try:
            quality = data['quality']
            pm25 = data['pm25']
            pm10 = data['pm10']
            shidu = data['shidu']
        except KeyError:
            print(url)
            print(u'数据异常')
        # 构造sql语句
        sql = "insert into weatherinfo values('%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s')" % \
              (cityinfo['cityId'], cityinfo['city'], cityinfo['parent'], shidu, pm25, pm10,
               quality, data['wendu'], data['ganmao'])
        # print(sql)
        try:
            # 执行sql语句
            cursor.execute(sql)
            conn.commit()
        except:
            print(sql)
            print(u'导入数据库失败')
            traceback.print_exc()
            # 发生错误时回滚
            conn.rollback()
    # 关闭数据库连接
    conn.close()


if __name__ == '__main__':
    f()

参考资料

[1] 免费天气API,天气JSON API,不限次数获取十五天的天气预报
https://www.sojson.com/blog/305.html
[2] Python错误解决:UnicodeEncodeError: ‘latin-1’ codec can’t encode characters in position
https://blog.csdn.net/lynn_coder/article/details/79504564
[3] 命令行修改MySQL数据库密码
https://www.cnblogs.com/supiaopiao/p/8527391.html
[4] python3连接mysql数据库及异常信息处理
https://blog.csdn.net/lovelong8808/article/details/77193752
[5] python字符串拼接
https://www.cnblogs.com/yexuesong/p/9232349.html
[6] python中__name__的使用
https://www.cnblogs.com/1204guo/p/7966461.html
[7] 浅析python中__name__ = ‘__main__’ 的作用
https://www.cnblogs.com/alan-babyblog/p/5147770.html

微信扫一扫关注公众号
image.png
点击链接加入群聊

https://jq.qq.com/?_wv=1027&k=5eVEhfN
软件测试学习交流QQ群号:511619105

软件测试学习资料
《自动化测试教程》

  • 1
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值