前言
說一下這個想法的由來。其實最初目的不是為了獲取天氣的,這只是一個練習而已。最初是想自動獲取公司的出勤情況,提醒我前一天有沒有忘記打卡的。公司打卡是由網站可以查詢的,有時忘記了或者系統(tǒng)出錯,可能當天打卡沒有打上,不去查看的話就記為缺勤了(這可是關乎工資啊啊啊啊),于是想到了每天定時執(zhí)行一次查詢任務,要是差到有缺勤記錄就在登錄系統(tǒng)時發(fā)出提示。所以作為一個初學者我就自然想到怎么獲取網站固定信息了。由于在公司是內網,無法在家測試,所以就寫個查詢天氣的腳本來確定基本的腳本結構。
原理
原理呢,其實就是字符串的處理。我知道可以用網站的api發(fā)出請求,然后返回數(shù)據(jù),這樣更加方便快捷。但是,我不是學軟件的不會這個,233333。當然 這不是理由,可以去學,只是有更簡便的方式。我選擇將網頁源碼下載下來然后分析字符獲取字段,畢竟如果登錄網頁能看到信息,那么在網頁的html里應該也有這個字段。那么現(xiàn)在大概的步驟就明確了:
- 下載網頁源碼。
- 查看源碼,分析關鍵字段的特征,從而能夠查找匹配。
這種方式只適合不需要網頁交互的查詢,假如查詢時還要輸入密碼這些就不能查到了。只要在瀏覽器直接輸入網址就能訪問的網頁可以用這種方法查詢需要的信息。
詳細分析
在這里我選取中國天氣網上海天氣來作為查詢的網址。首先用瀏覽器將網頁另存為html格式,然后查看文本內容(在這里推薦使用代碼編輯器查看,瀏覽器有瀏覽網頁源碼功能的也可以查看。我將網頁文件傳到樹莓派用vim查看了,后面perl也是在樹莓派上寫)。用vim查看代碼,然后搜索日期,天氣應該是按日期來排的。太幸運了,直接就搜到了:
實在是easy啊。那么我們來分析這一行。
<input type="hidden" id="hidden_title" value="10月27日20時 周五 晴轉多云 16/22°C" />
這一行的分析思路有以下幾點:
- 這一句是通過搜索日期的到的,那么我們可以在代碼中使用查找日期來定位這一行。
- 我們需要的天氣信息在
value=
關鍵詞后面用雙引號包起來的字段,我們可以在定位行后在行里定位字符串value=
,相信這不難做到。最簡單粗暴的方式就是用數(shù)組把每個字符保存起來,然后一個一個遍歷。這一行的字符也不多,占用內存也不大。 - 我還發(fā)現(xiàn),我需要的字段被雙引號
"
包起來,那么我聯(lián)想到perl中的split
函數(shù)。可以將這一行用split
函數(shù)將字符分解為以"
隔開的列表,這樣我們只要訪問列表元素就可以了。
代碼實現(xiàn)
首先使用shell的curl
命令下載網頁。這里解釋一下為什么不用perl
的命令(當然是因為技術不好啊_)。perl對網絡的操作好像需要一些模塊,不知道這些模塊是安裝perl
時自帶的還是需要額外添加,也不確定公司的perl
是不是帶有這些模塊。但是shell的curl
命令是自帶的,我就使用shell命令來下載網頁了。在perl
中調用shell命令表達如下:
`curl -o wether.html http://www.weather.com.cn/weather/101020100.shtml`
注意兩邊的單引號!網址中的101020100.shtml
指的是上海的天氣頁面,不清楚具體城市編碼方式,可以一個一個去網站查詢看。命令中的-o wether.html
參數(shù)指的是將下載的網頁另存為wether.html
文件。
下載好網頁后就可以以文本方式讀取網頁內容了。在處理文件字符之前,我們需要獲得查詢的關鍵字,也就是日期。獲得關鍵字后去讀取文件每一行,并判斷當前行是否包含關鍵字,包含關鍵字則將當前行分解為列表,得到列表就可以輸出天氣信息了。
最后得到代碼如下:
#!/usr/bin/perl -w
`curl -o wether.html http://www.weather.com.cn/weather/101020100.shtml`;
if ( ! open HTML,'<','wether.html' ) {
die "cannot open:$!"; #文件打開失敗提示
}
$date =`date`; #獲取當前時間
chomp($date);
@date_list = split /\s+/,$date; #將獲取到的時間以空格分解,提取出日期。也可以通過控制
#獲取時間命令的參數(shù)來直接獲得日期。比如 date "+%m月%d日"
#這樣就可以直接獲取"x月x日"格式的時間
while (defined ($line = <HTML>)) { #讀取文件每一行到$line變量里
$gre=(grep /$date_list[2]/,$line) + (grep /value=/,$line);#如果有日期,又有value關鍵詞,則認為找到了
if ($gre == 2){
@val_list=split /"/,$line; #將文本行以"為分隔符分解字段
print $val_list[5]."\n"; #天氣信息在列表元素5里
last;
}
}
close HTML;
以上就是代碼實現(xiàn)過程,很簡單的幾行就搞定了。方法很偏門啊,慎用。
運行結果
想要獲取更準確更實時的數(shù)據(jù)也可以在網頁中繼續(xù)查找,主要是字符串的定位問題。更簡單粗暴的方式是查看數(shù)據(jù)在哪一行,直接跳到那一行去分解字符串獲取數(shù)據(jù),這就免得去分析查找的關鍵字怎么獲取了。但這種方法的前提是網頁的內容變動不太大,需要的信息總是出現(xiàn)在那一行。就天氣來說,網頁內容還是比較固定的,可以采用這種方式。