设为首页收藏本站

Crossin的编程教室

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

【Python 第46课】 查天气(4)

  [复制链接]

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

跳转到指定楼层
楼主
发表于 2013-7-27 00:01:01 |显示全部楼层 |倒序浏览
python 查天气系列:
【Python 第43课】 查天气(1) http://bbs.crossincode.com/forum.php?mod=viewthread&tid=8
【Python 第44课】 查天气(2) http://bbs.crossincode.com/forum.php?mod=viewthread&tid=9
【Python 第45课】 查天气(3) http://bbs.crossincode.com/forum.php?mod=viewthread&tid=12
【Python 第46课】 查天气(4) http://bbs.crossincode.com/forum.php?mod=viewthread&tid=42


这一课算是“查天气”程序的附加内容。没有这一课,你也查到天气了。但了解一下城市代码的抓取过程,会对网页抓取有更深的理解。

天气网的城市代码信息结构比较复杂,所有代码按层级放在了很多xml为后缀的文件中。而这些所谓的“xml”文件又不符合xml的格式规范,导致在浏览器中无法显示,给我们的抓取又多加了一点难度。

首先,抓取省份的列表:
  1. url1 = 'http://m.weather.com.cn/data3/city.xml'
  2. content1 = urllib2.urlopen(url1).read()
  3. provinces = content1.split(',')
复制代码
输出content1可以查看全部省份代码:
  1. 01|北京,02|上海,03|天津,...
复制代码
对于每个省,抓取城市列表:
  1. url = 'http://m.weather.com.cn/data3/city%s.xml'
  2. for p in provinces:
  3.     p_code = p.split('|')[0]
  4.     url2 = url % p_code
  5.     content2 = urllib2.urlopen(url2).read()
  6.     cities = content2.split(',')
复制代码
输出content2可以查看此省份下所有城市代码:
  1. 1901|南京,1902|无锡,1903|镇江,...
复制代码
再对于每个城市,抓取地区列表:
  1. for c in cities[:3]:
  2.     c_code = c.split('|')[0]
  3.     url3 = url % c_code
  4.     content3 = urllib2.urlopen(url3).read()
  5.     districts = content3.split(',')
复制代码
content3是此城市下所有地区代码:
  1. 190101|南京,190102|溧水,190103|高淳,...
复制代码
最后,对于每个地区,我们把它的名字记录下来,然后再发送一次请求,得到它的最终代码:
  1. for d in districts:
  2.     d_pair = d.split('|')
  3.     d_code = d_pair[0]
  4.     name = d_pair[1]
  5.     url4 = url % d_code
  6.     content4 = urllib2.urlopen(url4).read()
  7.     code = content4.split('|')[1]
复制代码
name和code就是我们最终要得到的城市代码信息。它们格式化到字符串中,最终保存在文件里:
  1. line = "    '%s': '%s',\n" % (name, code)
  2. result += line
复制代码
同时你也可以输出它们,以便在抓取的过程中查看进度:
  1. print  name + ':' + code
复制代码
完整代码:
  1. import urllib2

  2. url1 = 'http://m.weather.com.cn/data3/city.xml'
  3. content1 = urllib2.urlopen(url1).read()
  4. provinces = content1.split(',')
  5. result = 'city = {\n'
  6. url = 'http://m.weather.com.cn/data3/city%s.xml'
  7. for p in provinces:
  8.     p_code = p.split('|')[0]
  9.     url2 = url % p_code
  10.     content2 = urllib2.urlopen(url2).read()
  11.     cities = content2.split(',')
  12.     for c in cities:
  13.         c_code = c.split('|')[0]
  14.         url3 = url % c_code
  15.         content3 = urllib2.urlopen(url3).read()
  16.         districts = content3.split(',')
  17.         for d in districts:
  18.             d_pair = d.split('|')
  19.             d_code = d_pair[0]
  20.             name = d_pair[1]
  21.             url4 = url % d_code
  22.             content4 = urllib2.urlopen(url4).read()
  23.             code = content4.split('|')[1]
  24.             line = "    '%s': '%s',\n" % (name, code)
  25.             result += line
  26.             print  name + ':' + code
  27. result += '}'
  28. f = file('/home/crossin/Desktop/city.py', 'w')
  29. f.write(result)
  30. f.close()
复制代码
如果你只是想抓几个测试一下,并不用全部抓下来,在provices后面加上[:3],抓3个省的试试看就好了。

补充:如果发现输出的是乱码(这种事往往发生在windows下),试着把输出那行改为
  1. print  name.decode('utf-8') + ':' + code
复制代码


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

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


#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

沙发
发表于 2013-7-27 14:55:02 来自手机 |显示全部楼层
lpd0933 发表于 2013-7-27 11:49
看了这个帖子,我明白:为什么按照查天气(1)的方法最后部分城市的编码不一致。

查天气(1)中提到‘’‘ ...

是的,我也是后来发现直辖市是有问题的
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

板凳
发表于 2013-8-5 16:20:38 |显示全部楼层
grdzyz 发表于 2013-7-31 23:29
请问p_code = p.split('|')[0]中的[0]表示什么?

split得出的结果诸如['01', '北京']形式的list,[0]就是取到它的省级别编码
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

地板
发表于 2013-8-5 16:23:06 |显示全部楼层
book 发表于 2013-8-5 13:12
code = content4.split('|')[1]  ??

split得出的结果诸如['190101', '101190101']形式的list,[1]就是取到它的城市编码
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

5#
发表于 2013-8-6 15:20:34 |显示全部楼层
book 发表于 2013-8-6 13:22
您好,这里是[0] 还是[1],我运行了好多次,抓的过程中,总是出错,每次都出在urllib2.urlopen().read(), ...

最后一步的城市代码是后面一个值,所以是[1]
你把那个语句分开两步,比如
  1. content=urllib2.urlopen(。。。)
  2. data=content.read()
复制代码
看下到底哪句出错,错误提示是什么。
如果不是提供的url有问题,那就是网络问题
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

6#
发表于 2013-8-15 23:33:04 |显示全部楼层
sd.times 发表于 2013-8-15 21:42
我的代码,抓取出来的城市名称是乱码。不知道是什么原因。
代码前已经加了:# -*- coding: cp936 -*-
请指 ...

那种乱码?把代码和程序错误都发上来看看
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

7#
发表于 2013-8-17 15:09:21 |显示全部楼层
sd.times 发表于 2013-8-17 05:05
代码就是贴的你写的:
# -*- coding: cp936 -*-
import urllib2

是windows对python的中文支持不好。
你可以改成
  1. print  name.decode('utf-8') + ':' + code
复制代码
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

8#
发表于 2013-9-2 18:51:56 |显示全部楼层
aresli 发表于 2013-9-2 17:23
在不用[:3]减少查询城市的时候,始终会报一个错误:
  code = content4.split('|')[1]
IndexError: list in ...

很可能是,查询多了,对方服务器有时候没有回复成功。
你把contect4打出来看看,错的时候是什么数据
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

9#
发表于 2013-9-2 20:37:04 |显示全部楼层
aresli 发表于 2013-9-2 20:24
试了5次,有3次是放回一张html文件的源代码,应该是长404页面,

最近经常这样,请求多了它那里就拿不到数据。在循环里面sleep一下,可能会好些。
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

10#
发表于 2013-9-3 20:26:38 |显示全部楼层
林夕_信仰 发表于 2013-9-3 17:29
先生,我抓取省份的列表之后,输出content1,结果是乱码的(我在文件头已经加了#encoding:utf-8 ),怎么 ...

你这问题好像和楼上某个问题是一样的,你看一下上面的评论。
  1. print content.decode('utf-8')
复制代码
用这个方法试试看。
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

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

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

GMT+8, 2024-5-3 05:55 , Processed in 0.029676 second(s), 28 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部