Python爬取天气实况(2)

三、对爬取天气实况程序的进一步优化
对上一篇的程序进行优化,加上了处理异常机制,比如爬取失败怎么处理,比如站号不存在怎么处理,使程序更加健壮。
代码如下:

import requests
import re


def getHTMLtext(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status() #如果状态不是200,引发HTTPError异常
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "ERROR"


def parseHTML(s):
    try:
        pat_title = re.compile(r'[A-Z]?\d{4,5}.*站的当前实况')
        title = pat_title.search(s).group(0)
        print(title)

        lst = re.findall(r'[\d\D]*?', s)
        for l in lst:
            m = re.sub(r'[\n\t]+|||', '', l)
            result = re.split('',m)
            print(result[0]+':'+result[1]+' (更新时间:'+result[2]+')')
    except:
        print("该站号可能不存在!")


num = input("请输入站号:")
url = "http://q-weather.info/weather/" + str(num) + "/realtime/"
s = getHTMLtext(url)

if(s == "ERROR"):
    print("查询失败!请重试")
else:
    parseHTML(s)
        

几个运行结果如下:
1.站号存在的情况:
Python爬取天气实况(2)_第1张图片
2.站号不存在的情况:
在这里插入图片描述
3.网络问题
这种情况会输出“查询失败!请重试”,由于我碰到的几率较小,因此也没有截图放出来了。

四、爬取站号的详细信息
我们以59659茂名站为例(http://q-weather.info/weather/59659/),下图就是查天气网站截图:
Python爬取天气实况(2)_第2张图片
爬取的HTML源代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN">\n<head>\n\t<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />\n\t<title>气象站59659的详细信息</title>\n\t<style type="text/css">\n\t\ttable {\n\t\t\tborder-width: 0px;\n\t\t\tborder-style: solid;\n\t\t\tborder-collapse: collapse;\n\t\t}\n\t\ttable th {\n\t\t\tborder-width: 1px;\n\t\t\tpadding: 3px;\n\t\t\tborder-style: solid;\n\t\t}\n\t\ttable td {\n\t\t\tborder-width: 1px;\n\t\t\tpadding: 3px;\n\t\t\tborder-style: solid;\n\t\t}\n\t</style>\n</head>\n<body>\n\t<center>\n\t\t<h1>站点59659的信息</h1>\n\t\t<table>\n\t\t\t<tr>\n\t\t\t\t<td width="100px">WMO编号</td>\n\t\t\t\t<td width="200px">59659</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>站名</td>\n\t\t\t\t<td>茂名</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>所在市</td>\n\t\t\t\t<td>茂名</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>地理位置</td>\n\t\t\t\t<td>21.75N<br />\n\t\t\t\t\t110.92E<br />\n\t\t\t\t\t33.3m</td>\n\t\t\t</tr>\n\t\t</table>\n\t\t<h2>服务列表</h2>\n\t\t<p><a href="realtime/">查询当前实况</a></p>\n\t\t<p><a href="today/">查询今日实况</a></p>\n\t\t<p><a href="cma7day/">中国气象局7天预报</a></p>\n\t\t<p><a href="t77day/">T7Online 7天预报</a></p>\n\t\t<p><a href="t7en8day/">WeatherOnline 8天预报</a></p>\n\t</center>\n</body>\n</html>\n

如果将转义字符转义(就是将\n和\t变成换行和制表),也就是:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
	<title>气象站59659的详细信息</title>
	<style type="text/css">
		table {
			border-width: 0px;
			border-style: solid;
			border-collapse: collapse;
		}
		table th {
			border-width: 1px;
			padding: 3px;
			border-style: solid;
		}
		table td {
			border-width: 1px;
			padding: 3px;
			border-style: solid;
		}
	</style>
</head>
<body>
	<center>
		<h1>站点59659的信息</h1>
		<table>
			<tr>
				<td width="100px">WMO编号</td>
				<td width="200px">59659</td>
			</tr>
			<tr>
				<td>站名</td>
				<td>茂名</td>
			</tr>
			<tr>
				<td>所在市</td>
				<td>茂名</td>
			</tr>
			<tr>
				<td>地理位置</td>
				<td>21.75N<br />
					110.92E<br />
					33.3m</td>
			</tr>
		</table>
		<h2>服务列表</h2>
		<p><a href="realtime/">查询当前实况</a></p>
		<p><a href="today/">查询今日实况</a></p>
		<p><a href="cma7day/">中国气象局7天预报</a></p>
		<p><a href="t77day/">T7Online 7天预报</a></p>
		<p><a href="t7en8day/">WeatherOnline 8天预报</a></p>
	</center>
</body>
</html>

这个就比之前的好弄很多了,所在市信息、地理位置都包围在tr标签里面,一个很简单的想法就是将所有符合以下正则表达式:

r'[\d\D]*?'

全部都找出来,所用的函数是findall函数,然后将结果存进列表中。由于WMO不是我们想要的信息,它位于list[0]里面,我们不管它就是了。接着再用:

r'[\n\t]+|||'

删掉我们不需要的符号\n\t和tr标签、td标签,留下/td标签以作分隔符。
所以我们提取出来的其实是以下结果:

站名</td>#这是list[1]的内容!!!
茂名</td>
			
所在市</td>#这是list[2]的内容!!!
茂名</td>
			
地理位置</td>#这是list[3]的内容!!!
21.75N<br />
110.92E<br />
33.3m</td>

list[1]和[2]很好处理,用re.split函数以/td作为分隔,将有用信息拿出来就是了。
我们发现地理位置信息(list[3])与其他两个有一点不同,那就是list[3]多了两个br/标签,因此我们需要特别处理。
完整代码如下:

import requests
import re


def getHTMLtext(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status() #如果状态不是200,引发HTTPError异常
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "ERROR"
    

def parseInform(s):
    lst = re.findall(r'[\d\D]*?', s)
    #处理站名信息和所在市信息
    for l in lst[1:3] :
        l = re.sub(r'[\n\t]+|||', '', l)
        result = re.split(r'', l)
        print(result[0] + ':' + result[1])
     #对地理信息做特殊处理
    l = re.sub(r'[\n\t]+|||', '', lst[3])
    result = re.split(r'|
'
, l) print(result[0] + ':' + result[1] + '/' + result[2] + '\n海拔:' + result[3]) num = input("请输入站号:") url = "http://q-weather.info/weather/" + str(num) s = getHTMLtext(url) if(s == "ERROR"): print("查询失败!请重试") else: parseInform(s)

运行结果如下:
Python爬取天气实况(2)_第3张图片
我们最后可以将查询站点的详细信息程序和实时天气程序连接在一起,稍作修改,就能够得到一个不错的查询天气脚本了。
当然,这个网站还有查询最近24小时天气的功能,有时间的话我们会继续做做爬虫。

你可能感兴趣的:(Python爬虫)