Crossin的编程教室

标题: 【Python 第43课】 查天气(1) [打印本页]

作者: crossin    时间: 2013-7-23 21:20
标题: 【Python 第43课】 查天气(1)
用 python 查天气系列:
【Python 第43课】 查天气(1) https://python666.cn/cls/lesson/44/
【Python 第44课】 查天气(2) https://python666.cn/cls/lesson/45/
【Python 第45课】 查天气(3) https://python666.cn/cls/lesson/46/
查天气补充说明:https://mp.weixin.qq.com/s/dNu1tZm1jStW5OdEaxPcww
查天气视频讲解:https://zhuanlan.zhihu.com/p/89037314

=========================================
再次更新:
公众号里回复关键字: 查天气
有最新查天气案例文章

更新:
查天气系列中的部分链接已经失效,新的访问接口可参考这两篇文章:
http://blog.csdn.net/hello_haozi/article/details/7564223
http://blog.csdn.net/fancylovejava/article/details/26102635

如以后再次失效,可在网上搜一下“查天气接口”之类的,应该也会有其他可用接口

=========================================
PS:
1.
本帖子附带下载好的 city.py 文件。但因为接口有可能会变动,所以不保证其中数据一直有效。
由于需要以中文作为键名来匹配,city.py和代码文件的第一行都需要指定编码。windows平台上,请将编码改为cp936,而不是utf-8。否则可能导致编码报错或者无法匹配出结果。
2.
城市代码接口地址中的 data5 现已更新为 data3
http://m.weather.com.cn/data3/city.xml
3.
具体天气信息网站已不更新,所以可用来做网络请求的练习,但已无法实用。

=========================================
使用 wthrcdn.etouch.cn 作为数据源的时候请注意:
如果发现结果是乱码,排除字符编码设置外,还有个原因是因为此接口使用了 gzip 压缩,解决方法参见此楼:
http://bbs.crossincode.com/forum.php?mod=redirect&goto=findpost&ptid=9&pid=9075&fromuid=3
=========================================
给大家看一个程序:

43weather.png

你输入一个城市的名称,就会告诉你这个城市现在的天气情况。接下来的几节课,我就说一下怎么实现这样一个小程序。

之所以能知道一个城市的天气,是因为用了中国天气网(www.weather.com.cn)提供的天气查询接口。在浏览器里试着访问一下:
http://www.weather.com.cn/data/cityinfo/101010100.html
你就能看到北京现在的天气。这段看上去有点像python中字典类的文字是一种称作json格式的数据。(因为编码的缘故,有些浏览器看到的中文会是乱码)

而我们的程序要做的事情,就是按照用户输入的城市名称,去天气网的接口请求对应的天气信息,再把结果展示给用户。

于是,在这个程序中,我们要用到两个新模块:
1. urllib2
用来发送网络请求,获取数据

2. json
用来解析获得的数据


特别说明:下面一段的城市获取链接现在已过期,无法通过其抓取城市代码。替代方案:
1. 接口间歇性可用,有时这个接口 http://m.weather.com.cn/data3/city.xml 是可行的。
2. 可以直接下载 city.py 城市列表
https://pan.baidu.com/s/1c0Nw4m(下载之后如果在程序里出错,试试在前面加上# -*- coding: UTF-8 -*- ,windows下加# -*- coding: cp936 -*- )
3. 文章 http://blog.csdn.net/hello_haozi/article/details/7564223 中给出了城市代码,可用代码将其抓取出来(这是一个附加题)
4. 选择新接口:http://wthrcdn.etouch.cn/weather_mini?city=北京
无需城市代码,直接给城市名称即可。城市名需用utf8编码。返回结果的结构和教程示例会有所不同。

此段内容已过期
听上去似乎还挺不算太复杂?但是注意刚才那个例子,我们请求北京天气时,用了“101010100”这样的数字。这是天气网设定的城市代码。然而令人蛋疼的是,天气网并没有直接给出所有城市代码的对应关系,而是给了3个接口:

1. http://m.weather.com.cn/data3/city.xml
获取所有省/直辖市的编号,如“01|北京,02|上海,03|天津”

2. http://m.weather.com.cn/data3/city省编号.xml
获取二级地区编号,如江苏是:city19.xml

3. http://m.weather.com.cn/data3/city二级编号.xml
获取三级编号,如南京是:city1901.xml

得到最终的三级编号之后,再加上中国101的前缀,就得到了城市代码,如南京市区就是“101190101”

所以,你可以选择,再写一个python程序,事先把这些复杂的编码全部抓取下来,整理成你要的格式;或者,偷懒一下,跳过这个过程,直接拿我抓好的编码。我放在了网盘里:
(也可从本贴附件中下载)
https://pan.baidu.com/s/1c0Nw4m
(下载之后如果在程序里出错,试试在前面加上# -*- coding: UTF-8 -*- ,windows下加# -*- coding: cp936 -*- )

今天先卖个关子,不说具体的写法。想挑战的同学可以试试在我说之前就把这个程序搞定。


#==== Crossin的编程教室 ====#
微信ID:crossincode

面向零基础初学者的编程课
每天5分钟,轻松学编程
微信二维码

city.py

60.45 KB, 阅读权限: 10, 下载次数: 515


作者: byron    时间: 2013-7-23 21:24
https://gist.github.com/imbyron/6055795
哈哈
作者: fdksjfskfddffd    时间: 2013-7-24 23:40

作者: simple    时间: 2013-7-25 10:25

作者: 曙光    时间: 2013-7-25 10:29
这个好,终于明白天气软件的原理了。手机上的天气软件做的越来越大,越来越慢,真不爽。
作者: xfxfxff    时间: 2013-7-25 20:43
微信粉丝,头一天来论坛,希望越来越好
作者: lwolf    时间: 2013-7-25 22:05
报道一下(
作者: michael    时间: 2013-7-27 17:12
city的数据原来在这里

作者: acalaca    时间: 2013-7-29 16:12
微信粉儿过来报道~~~
作者: 林夕_信仰    时间: 2013-9-1 18:27
http://m.weather.com.cn/data5/city.xml 这个链接失效啊啊
作者: crossin先生    时间: 2013-9-1 22:51
林夕_信仰 发表于 2013-9-1 18:27
http://m.weather.com.cn/data5/city.xml 这个链接失效啊啊

不是失效,只是因为它格式的问题,无法在浏览器里显示,你在网页上右键,选择查看源代码就能看到了
作者: 林夕_信仰    时间: 2013-9-3 17:24
crossin先生 发表于 2013-9-1 22:51
不是失效,只是因为它格式的问题,无法在浏览器里显示,你在网页上右键,选择查看源代码就能看到了 ...

啊,原来是这样,谢~
作者: toddlerya    时间: 2013-9-16 22:23
# -*- coding: UTF-8 -*- ,windows下加# -*- coding: cp936 -*-
开始没看见 百度了一圈解决了才发现 老师已经告诉了
作者: jane    时间: 2013-10-30 13:11
crossin先生 发表于 2013-9-1 22:51
不是失效,只是因为它格式的问题,无法在浏览器里显示,你在网页上右键,选择查看源代码就能看到了 ...

1   如何知道/获取 天气网的这三个接口呢???
2   http://www.weather.com.cn/data/cityinfo/%s.html'  % citycode  这个链接又是怎么知道呢?


1. http://m.weather.com.cn/data5/city.xml
获取所有省/直辖市的编号,如“01|北京,02|上海,03|天津”

2. http://m.weather.com.cn/data5/city省编号.xml
获取二级地区编号,如江苏是:city19.xml

3. http://m.weather.com.cn/data5/city二级编号.xml
获取三级编号,如南京是:city1901.xml

作者: crossin先生    时间: 2013-10-30 14:37
jane 发表于 2013-10-30 13:11
1   如何知道/获取 天气网的这三个接口呢???
2   http://www.weather.com.cn/data/cityinfo/%s.html'  ...

我从网上搜出来的
作者: vose    时间: 2013-11-7 19:46
先生,这是可以用的地址
http://www.weather.com.cn/data/city3jdata/china.html 各省地址
http://www.weather.com.cn/data/city3jdata/provshi/[省份代码].html 省辖市区地址
http://www.weather.com.cn/data/city3jdata/station/[省份代码][市区代码].html 市内各区县地址
http://www.weather.com.cn/data/cityinfo/[省份代码][市区代码].html 最终天气
作者: 508490571    时间: 2014-3-16 23:20
本帖最后由 508490571 于 2014-3-16 23:21 编辑
  1. <blockquote># -*- coding: cp936 -*-
复制代码

作者: liu-pengfei    时间: 2014-9-26 18:41
先生,这句话“得到最终的三级编号之后,再加上中国101的前缀,就得到了城市代码,如南京市区就是“101190101””不完全对,直辖市的城市代码不是这样的吧?
作者: robinlkm    时间: 2014-12-10 20:56
先生,我想问一下如何确定这些网址的。
当我在中国天气网里点击北京的时候 出现的是 http://www.weather.com.cn/weather1d/101010100.shtml#[url]www.weather.com.cn[/url]
我想知道您是如何一步一步确定这些网址的。
谢谢!
作者: crossin先生    时间: 2014-12-11 11:00
robinlkm 发表于 2014-12-10 20:56
先生,我想问一下如何确定这些网址的。
当我在中国天气网里点击北京的时候 出现的是 http://www.weather.co ...

网上搜索了一下,有别人写过的关于格式的帖子

一般来说,要抓一个网站,都得先做点分析。每个网站都不一样,具体方法可能都不同,做个几次大约就有数了
作者: robinlkm    时间: 2014-12-11 11:11
crossin先生 发表于 2014-12-11 11:00
网上搜索了一下,有别人写过的关于格式的帖子

一般来说,要抓一个网站,都得先做点分析。每个网站都不一 ...

谢谢 先生
作者: lovia    时间: 2015-5-28 20:01
文件没法下载
作者: 巴黎巴黎    时间: 2015-6-18 15:51
想再次感谢一下CROSSIN先生~ 虽然只学了43课,但是真的觉得这篇教程太棒了!
作者: yaso    时间: 2016-8-18 15:49
url='http://m.weather.com.cn/data/%s.html'%citycode
这句代码的天气永远16度,为什么会不准?怎么才能查询实时的?
作者: crossin先生    时间: 2016-8-19 11:10
yaso 发表于 2016-8-18 15:49
url='http://m.weather.com.cn/data/%s.html'%citycode
这句代码的天气永远16度,为什么会不准?怎么才能 ...

此接口停止更新了,是数据本身问题。
看本帖开头的说明,里面有新的接口地址
作者: yxskey    时间: 2017-1-22 08:03
北京的气温查出来,总是-2℃ ~ 16℃,是怎么回事
作者: crossin先生    时间: 2017-1-22 19:56
yxskey 发表于 2017-1-22 08:03
北京的气温查出来,总是-2℃ ~ 16℃,是怎么回事

接口已停止更新数据,看一楼帖子里的说明
作者: 布不奇奇YM    时间: 2017-2-22 17:41
好多资料是英文……英语不好真是要多绕几圈路……

QQ截图20170222173918.png (53.71 KB, 下载次数: 537)

QQ截图20170222173918.png


作者: Ramemory    时间: 2017-7-18 22:27

作者: blueheart    时间: 2017-8-24 10:36
本帖最后由 blueheart 于 2017-8-24 10:56 编辑

城市列表city.py不全啊,有很多地方(特别是某些区县)都没有的,请问作者如何获取最全的城市列表呢?
作者: crossin先生    时间: 2017-8-24 11:40
blueheart 发表于 2017-8-24 10:36
城市列表city.py不全啊,有很多地方(特别是某些区县)都没有的,请问作者如何获取最全的城市列表呢? ...

原始数据就是有问题。
数据源查看本贴最前面的链接和说明
作者: blueheart    时间: 2017-8-24 17:46
crossin先生 发表于 2017-8-24 11:40
原始数据就是有问题。
数据源查看本贴最前面的链接和说明

哦哦,谢谢您
作者: Aquamarine    时间: 2017-10-30 21:10
请问下,urllib2和json两个模块是不是Python3自带的没有,要去https://pypi.python.org/下载?
作者: crossin先生    时间: 2017-10-31 10:52
Aquamarine 发表于 2017-10-30 21:10
请问下,urllib2和json两个模块是不是Python3自带的没有,要去https://pypi.python.org/下载? ...

json有的
urllib2 变成 urllib3 和 urllib.request,你网上搜下使用方法即可
作者: Aquamarine    时间: 2017-10-31 23:04
本帖最后由 Aquamarine 于 2017-10-31 23:29 编辑
crossin先生 发表于 2017-10-31 10:52
json有的
urllib2 变成 urllib3 和 urllib.request,你网上搜下使用方法即可

感谢指教,用urllib.request通过。
作者: coolqing    时间: 2018-4-25 12:22
请问怎么去网站上抓数据啊,附加题。。
作者: crossin先生    时间: 2018-4-25 15:13
coolqing 发表于 2018-4-25 12:22
请问怎么去网站上抓数据啊,附加题。。

跟查天气的思路一样,找地址、发请求、处理返回的文本
作者: chenkeke    时间: 2018-8-6 10:01
想知道现在的天气接口是哪一个?
作者: crossin先生    时间: 2018-8-6 15:50
chenkeke 发表于 2018-8-6 10:01
想知道现在的天气接口是哪一个?

可以用的:http://www.weather.com.cn/data/cityinfo/101010100.html

看本贴开头的说明
作者: _test001    时间: 2018-8-10 10:21
查询结果出错了 好像是输入的“北京”编码有错?url识别不了?
但我不懂怎么改。。。

#coding:cp936
import urllib2
import gzip
from StringIO import StringIO

cityname=raw_input('你想查哪个城市的天气?\n')
url='http://wthrcdn.etouch.cn/weather_mini?city=%s'%cityname
content=urllib2.urlopen(url).read() #读取天气信息

#gzip解压
buf = StringIO(content)
f = gzip.GzipFile(fileobj=buf)
content = f.read()

print content


======== RESTART: C:\Users\Administrator\Desktop\003_WeatherReport.py ========
你想查哪个城市的天气?
北京
{"status":1002,"desc":"invilad-citykey"}
>>>
作者: crossin先生    时间: 2018-8-10 13:03
_test001 发表于 2018-8-10 10:21
查询结果出错了 好像是输入的“北京”编码有错?url识别不了?
但我不懂怎么改。。。

这个接口是直接用城市名
而且记得用utf8编码
作者: phb625031983    时间: 2018-8-21 19:25
crossin老师好,因为之前的接口都不能用了,所以我换成了这接口:
https://www.sojson.com/open/api/weather/json.shtml?city=北京
是以城市名为关键词的,但是这样又出现了一个新问题:
  1. #-*- encoding: utf-8 -*-

  2. import urllib.request
  3. import json

  4. cityname = input('你想查哪个城市的天气?\n')
  5. url = ('https://www.sojson.com/open/api/weather/json.shtml?city=%s' % cityname)
  6. content = urllib.request.urlopen(url).read()
  7. data = json.loads(content)
  8. print(data)
复制代码
这是我的代码,运行后我按提示输入北京后结果报错为:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 38-39: ordinal not in range(128)

在网上查过一些解决办法,包括用import sys等方式,都不管用。。
请问老师这个问题怎么结局啊!谢谢了!
作者: crossin先生    时间: 2018-8-22 22:10
phb625031983 发表于 2018-8-21 19:25
crossin老师好,因为之前的接口都不能用了,所以我换成了这接口:
https://www.sojson.com/open/api/weathe ...

要用 urllib.quote 处理下
看我公众号今天发的文章,以及里面附的代码
稍后我也会发上来
作者: Konmey    时间: 2018-9-22 22:53
老师您好,我将文件下载之后看到的是
微信图片_20180922164938.png
请问这是正常显示吗?
然后我按照您的代码输入之后:
import urllib.request
import json
from city import city

cityname = input("which city do you want to search?\n")
citycode = city.get(cityname)
print(citycode)
if citycode:
        url = ("http://www.weather.com.cn/data/cityinfo/%s.html"%citycode)
        content = urllib.request.urlopen(url).read()
        print(content)
得到的结果是:
南京
None
请问这是怎么回事呢?
作者: crossin先生    时间: 2018-9-23 16:47
Konmey 发表于 2018-9-22 22:53
老师您好,我将文件下载之后看到的是

请问这是正常显示吗?

编码不一致
跟你系统有关,要看你控制台输入是什么编码
然后全都设成一致的
# coding: gbk

gbk或者utf8都试一下,两个文件都要加。而且看你用什么编辑器,有的编辑器会自作主张帮你加编码。乱码的话,你要么设置下编码,要么重新创建文件复制进去。
公众号前几天“查天气”文章里应该有提到
作者: jaxon    时间: 2019-3-5 12:01
老师,我试着读取百度首页,然后在写入文件时出现报错。

如果我不写入文件,把print出来的结果复制到baidu.html中,打开会是乱码,请问老师是怎么回事呢

微信图片_20190305120252.png (32.27 KB, 下载次数: 691)

微信图片_20190305120252.png

微信图片_20190305120219.png (30.41 KB, 下载次数: 686)

微信图片_20190305120219.png


作者: crossin先生    时间: 2019-3-5 19:37
jaxon 发表于 2019-3-5 12:01
老师,我试着读取百度首页,然后在写入文件时出现报错。

如果我不写入文件,把print出来的结果复制到baidu ...

写入时,open加上参数 encoding='utf8' 试下
作者: jaxon    时间: 2019-3-6 10:44
crossin先生 发表于 2019-3-5 19:37
写入时,open加上参数 encoding='utf8' 试下

谢谢,果然可以了




欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5