设为首页收藏本站

Crossin的编程教室

 找回密码
 立即加入
查看: 61850|回复: 47
打印 上一主题 下一主题

【Python 第43课】 查天气(1)

[复制链接]

3

主题

0

好友

515

积分

管理员

Rank: 9Rank: 9Rank: 9

跳转到指定楼层
楼主
发表于 2013-7-23 21:20:18 |只看该作者 |正序浏览
用 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

回复

使用道具 举报

0

主题

0

好友

22

积分

新手上路

Rank: 1

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

谢谢,果然可以了
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

47#
发表于 2019-3-5 19:37:51 |只看该作者
jaxon 发表于 2019-3-5 12:01
老师,我试着读取百度首页,然后在写入文件时出现报错。

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

写入时,open加上参数 encoding='utf8' 试下
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

22

积分

新手上路

Rank: 1

46#
发表于 2019-3-5 12:01:51 |只看该作者
老师,我试着读取百度首页,然后在写入文件时出现报错。

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

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

微信图片_20190305120252.png

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

微信图片_20190305120219.png

回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

45#
发表于 2018-9-23 16:47:50 |只看该作者
Konmey 发表于 2018-9-22 22:53
老师您好,我将文件下载之后看到的是

请问这是正常显示吗?

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

gbk或者utf8都试一下,两个文件都要加。而且看你用什么编辑器,有的编辑器会自作主张帮你加编码。乱码的话,你要么设置下编码,要么重新创建文件复制进去。
公众号前几天“查天气”文章里应该有提到
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

6

积分

新手上路

Rank: 1

44#
发表于 2018-9-22 22:53:46 |只看该作者
老师您好,我将文件下载之后看到的是
微信图片_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
请问这是怎么回事呢?
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

43#
发表于 2018-8-22 22:10:29 |只看该作者
phb625031983 发表于 2018-8-21 19:25
crossin老师好,因为之前的接口都不能用了,所以我换成了这接口:
https://www.sojson.com/open/api/weathe ...

要用 urllib.quote 处理下
看我公众号今天发的文章,以及里面附的代码
稍后我也会发上来
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

4

积分

新手上路

Rank: 1

42#
发表于 2018-8-21 19:25:57 |只看该作者
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等方式,都不管用。。
请问老师这个问题怎么结局啊!谢谢了!
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

41#
发表于 2018-8-10 13:03:26 |只看该作者
_test001 发表于 2018-8-10 10:21
查询结果出错了 好像是输入的“北京”编码有错?url识别不了?
但我不懂怎么改。。。

这个接口是直接用城市名
而且记得用utf8编码
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

6

积分

新手上路

Rank: 1

40#
发表于 2018-8-10 10:21:52 |只看该作者
查询结果出错了 好像是输入的“北京”编码有错?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"}
>>>
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即加入

QQ|手机版|Archiver|Crossin的编程教室 ( 苏ICP备15063769号  

GMT+8, 2024-5-2 21:27 , Processed in 0.032859 second(s), 27 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部