Excel: Python 如何干掉 VBA 系列 丙

2023-12-14 05:04:06

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/FgoU8CxofwY90f3IX2Tpww

获取网络动态数据

本文开始之前夸过海口,说要演示一下喂养家畜的饲料动态成本,其实由于行业数据具有一定的商业属性,调用这类接口费钱,所以不打算展开了。

但简简单单地获取一下网络上有点意思的数据,还是可以的哦。不妨读个天气实时数据吧?然后封装成函数,再在 Excel 里调用演示一下。

设想一下,既然需要获取天气数据,那么就离不开具体的地点信息,比如地点名称、地理坐标等。一般我们都习惯按照地区来划分天气状况,或者更新天气报告。

比如,刚起床,不知道今天广州天气怎样呢?要不要穿短袖?(现在已经是冬天啦)

但是目前市面上常见的接口都是直接依据 city id 来访问的,这个 city id 就是一串数字,类似我们的身份证号码,独一无二地代表各个城市。这个 city id 也可以通过 Web API 获取。

那么目前有什么比较好用或者门槛比较低的 Web API 可以方便我们去测试一下呢?

既然是为了测试,那么我们作为学习者就喜欢薅羊毛了,又不是给公司调试产品,不免费怎么过意得去?八戒找到一个非常方便好用的接口给大家,供应商是 和风天气 qweather.com

想要从 qweather.com 读取到天气数据,最简单地可以调用两条接口,一个是获取 city id 的接口,另一个是根据 city id 获取天气数据的接口。如果想要使用这两个接口,建议先登录官网注册一个账号,然后创建项目时选择免费订阅,再添加 Web API 类型的 key(目前限制最多 20 条)。

查询 city id

以广州为例

https://geoapi.qweather.com/v2/city/lookup?location=广州&adm=广东&key=XXXXXX

location= 后边填城市名,adm= 后边填城市的上级省份或者区的上级城市,key= 后边填的 XXXXXX 就是你在官网注册时候手动添加的 key。

adm 参数不是必须的。一般为了避免重名的城市,比如陕西西安、吉林西安等,接口建议带上 adm 参数。

返回的是 json 格式数据,从内容来看,包含了广州各个区对应的 city id,也包含了整个市级别的 city id。一般用市级别的 city id 就够了,除非你想查询的是某个区的 city id。

"name":"广州",
"id":"101280101"

像上面这段,id 字段后边的值就是我们最终想要获取的数据,city id 字符串。

为了方便查询 city id,那么我们来写个函数封装实现调用上面的接口,接收响应数据,提取目标城市的 city id 并且返回

def get_city_id(city_name, province_name):
    url = "https://geoapi.qweather.com/v2/city/lookup?location={}&adm={}&key={}".format(city_name, province_name, api_key)
    response = requests.get(url)
    # print(response.text)
    data = json.loads(response.text)
    array = data["location"]
    for area in array:
        print("area = {}".format(area["name"]))
        if area["name"] == city_name:
            print("city {} id {}".format(city_name, area["id"]))
            return area["id"]
    return None

由于返回的内容里,含有包含有广州字样的所有地区,比如各个区级,所以要遍历一下,然后比较字段 name 的值是否等于 广州,等于就表示找到了目标对象。

如果没找到匹配的内容,应该返回 None 表示获取失败。

看看测试例子

get_city_id("广州", "广东")
get_city_id("香港", "香港")
get_city_id("北京", "北京")

运行结果

area = 广州
city 广州 id 101280101
area = 香港
city 香港 id 101320101
area = 北京
city 北京 id 101010100

一切还算顺利,但是要提醒的是,查询城市对应的 city id 这种非实时动态变化的数据,建议自己做好本地缓存。意思就是不需要每次都从别人的服务器查询这些不会经常变动的数据,应该优先从自己的记录中读取。

查询具体天气数据

继续上面的例子,查询广州的现时天气数据

https://devapi.qweather.com/v7/weather/now?location=101280101&key=XXXXXX

location= 后边填上一个接口查询到的 city id,key= 后边填的 XXXXXX 同样是你在官网注册时候手动添加的 key。

接口中的 now 表示查询的数据是实时值。如果需要查询往后几天的天气预报数据等,需要将 now 改为其它,这里不展开。

返回的也是 json 格式数据,从内容来看,我们的目标数据是 now 对象的 temp 子对象值,也就是温度值。

为了返回天气数据,简单起见只选择温度值。继续写个函数,直接调用前面已经封装好的函数 get_city_id 来查询城市对应的 city id,然后再调用第二个接口获取天气数据,接收响应数据,提取目标城市的温度值并且返回

def temperature(city_name, province_name):
    city_id = get_city_id(city_name, province_name)
    if city_id is None:
        print("fail to get city id of {}".format(city_name))
        return None
    url = "https://devapi.qweather.com/v7/weather/now?location={}&key={}".format(city_id, api_key)
    response = requests.get(url)
    # print(response.text)
    data = json.loads(response.text)
    print("city {} {}℃\n".format(city_name, data["now"]["temp"]))
    return data["now"]["temp"]

前面已经讲过,查询城市对应的 city id 是有可能失败的,所以有必要对函数 get_city_id 的返回值做检查,如果为错误值 None 就打印错误信息(这就是常说的日志,用于调试排查错误用),并且终止流程,也返回 None 作为错误值。

看看测试例子

temperature("广州", "广东")
temperature("香港", "香港")
temperature("北京", "北京")

运行结果

area = 广州
city 广州 id 101280101
city 广州 21℃

area = 香港
city 香港 id 101320101
city 香港 23℃

area = 北京
city 北京 id 101010100
city 北京 0℃

看起来北方现在好冷呀,还是广东的温度舒服~

从上面的测试结果来看,逻辑功能的函数是写好了,但是如果要在 Excel 表格中能够插入查询温度的函数 temperature, 应该参照前面 hello 函数的格式,在函数 temperature 的声明上一行添加 @xw.func 即可

@xw.func
def temperature(city_name, province_name):
...

最终来看看实际效果,打开表格 fishfeed.xlsm 里,选中一个单元格,点击工具栏里的按钮 Import Functions,然后输入

=temperature("广州","广东")

很好,结果满意吗?

这个系列暂时到这里为止,你有什么疑问都可以直接联系我,和我聊聊?

文章来源:https://blog.csdn.net/2301_76403635/article/details/134985405
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。