logo

Thursday 24th of May 2012

廣告

廣告贊助商

首頁 Python教學 Python程式範例 Yahoo!奇摩今日天氣截取
Yahoo!奇摩今日天氣截取 PDF 列印 E-mail
作者是 Victor   
週三, 11 二月 2009 21:09

Yahoo!奇摩今日天氣截取

這個程式示範如何用Python從Yahoo!奇摩的天氣網頁裡抓出今日台中的天氣,你會發現居然是這麼的簡單,對於Python而言這算是家常便飯,Python光是內建的標準函式庫就能讓你做一堆常見的工作,抓網頁也包括在裡面,甚至網頁Parser光是標準的就有好幾種讓你選,當然受到廣範使用的正規表示法理所當然也有提供,但是因為即然Parser都幫你寫好了,所以就沒有使用正規表示法的必要。

# -*- coding: utf-8 -*-

import urllib

# 抓取Yahoo!奇摩天氣的網頁內容放到WebContent
weatherWeb = urllib.urlopen("http://tw.weather.yahoo.com/today.html")
webContent = weatherWeb.read().decode('utf_8')
weatherWeb.close()

import HTMLParser

# 用來解析台中地區天氣資訊的解析器,繼承自HTMLParser
class WeaterHTMLParser(HTMLParser.HTMLParser):
    
    def handle_data(self, data):
        """處理標籤以外的資料,也就是網頁中的文字"""

        data = data.strip()

        # 如果台中地區已出現過,就記錄天氣資訊
        if hasattr(self, 'found') and data:
            # 到了彰化地區,中止解析
            if data == u'彰化地區':
                self.stop = True
                return
            self.weather.append(data)

        # 出現台中地區
        # 設定旗標以通知後面幾次呼叫記下資訊
        if data == u'台中地區':
            self.found = True
            self.weather = []
            self.weather.append(data)

    def unknown_decl(self, data):
        """Override unknown handle method to avoid exception"""
        pass

Parser = WeaterHTMLParser()

try:
    # 將網頁內容拆成一行一行餵給Parser
    for line in webContent.splitlines():
        # 如果出現停止旗標,停止餵食資料,並且跳出迴圈
        if hasattr(Parser, 'stop') and Parser.stop:
            break
        Parser.feed(line)
except HTMLParser.HTMLParseError, data:
    print "# Parser error : " + data.msg

Parser.close()

print u"%s 的今天氣是 %s,氣溫是 %s度%s,降雨機率是 %s" % tuple(Parser.weather)
print "Press enter to continue."
raw_input()

首先介紹urllib這個module,是的,一般抓取網頁的工作,對於urllib來說真的是再簡單也不過了,一個urlopen函數開啟某個網址,然後將傳回的物件呼叫它的read函數,取出所有網頁的內容,最後關閉,原本可能會很複雜的工作全部都已經被包好了,當然,你可能會覺得,這樣抓網頁的功能太過陽春,如果你想送表單、改變header怎麼辦? Python都幫你想好了,有urllib2,比urllib更強大的網頁抓取函式庫可以使用。


接下來介紹HTMLParser,就如字面上的意思一樣,是HTML的解析器,不是嚴謹地去解析網頁,它可以處理像不對稱的HTML語法等等,對於網路上各種千奇百怪出錯的網頁來說,當然是選擇可以容錯的 Parser比較好,如果是解析嚴謹的XML或XHTML就可以考慮用其它嚴謹的Parser,否則用這個就相當好用了。


它的運作方式是這樣,使用者覆載(override)一系列的handle_xxx函數,例如handle_data就是負責處理非HTML標籤,也就是不在<>的那些字用的方法,當它分析到這樣的資料就會呼叫handle_data,所以覆載了這個函數就可以處理這些資料,如果你希望可以處理HTML標籤,你也可以覆載handle_startag等等方法,相當容易使用,在這個例子裡面我們只對天氣的資訊有興趣,因為天氣資訊不在標籤裡,而是在外面的字,所以我們只使用handle_data來抓資料。


它的流程很簡單,就是發現台中地區的字樣之後,就物件自己本身一個found的屬性,然後設為True,讓接下來幾次遇到data被呼叫要處理時,就能知道台中地區已經出現過了,就可以開始記下天氣資訊,而彰化地區的判斷,是當遇到彰化地區就表示超過了我們想要的資訊範圍,為了省一點時間,就讓接下來的網頁不要再分析了,於是設定了stop的屬性,告訴外面的迴圈可以停止了。
就是這麼簡單,一個抓取天氣網頁的程式就完成了。

為了讓大家了解HTMLParser的運作方式,我特意改了原本程式,用來示範HTMLParser的運作方式:

# -*- coding: utf-8 -*-

import urllib

# 抓取Yahoo!奇摩天氣的網頁內容放到WebContent
weatherWeb = urllib.urlopen("http://tw.weather.yahoo.com/today.html")
webContent = weatherWeb.read().decode('utf_8')
weatherWeb.close()

import HTMLParser

# 用來解析台中地區天氣資訊的解析器,繼承自HTMLParser
class WeaterHTMLParser(HTMLParser.HTMLParser):
    def handle_starttag(self, tag, attrs):
        print u'標籤 %s %s 開始' % (tag, attrs)

    def handle_startendtag(self, tag, attrs):
        print u'空標籤 %s %s' % (tag, attrs)

    def handle_endtag(self, tag):
        print u'標籤 %s 結束' % tag

    def handle_data(self, data):
        print u'資料 "%s"' % data

    def handle_comment(self, data):
        print u'註解 "%s"' % data

    def unknown_decl(self, data):
        """Override unknown handle method to avoid exception"""
        pass

Parser = WeaterHTMLParser()

try:
    # 將網頁內容拆成一行一行餵給Parser
    for line in webContent.splitlines():
        # 如果出現停止旗標,停止餵食資料,並且跳出迴圈
        if hasattr(Parser, 'stop') and Parser.stop:
            break
        Parser.feed(line)
except HTMLParser.HTMLParseError, data:
    print "# Parser error : " + data.msg

Parser.close()

print "Press enter to continue."
raw_input()

注意事項 : 此程式檔必須用utf-8儲存,如果是用Python內建的IDLE會自動判斷第一行,但是如果使用計事本等軟體儲存,就必須選擇utf-8

 

核心是 Joomla!. Designed by: Free Joomla Theme, whois protect. Valid XHTML and CSS.