我們會希望很方便的利用一條命令列就將所有的地震資料下載下來並處理,以下利用 curl 與 Python3 下載中研院 BATS CMT Catalog Search 網頁的資料。
原理:
中研院 BATS (Broadband Array in Taiwan for Seismology)是臺灣地震觀測的重要資料來源。一般而言,當我們想匯出 GMT (psmeca)可接受的格式時,需要到檢索網頁(http://tecws.earth.sinica.edu.tw/BATS/cmtbyform.php)將表單填寫完成後,再送出給後端的伺服器去做查詢並傳回資料。
這份表格是用 HTTP 的 POST request 去完成的(參考 >這邊< 說明語法),因此,接下來我們將用 curl 提供的 -F 選項,將表格中所需的參數一一填入並傳送給伺服器。

流程:
填表單( curl -F)-( POST ) -> ./cmtsearch_result.php 處理 -> 傳回結果(/cmtsearch_result.php) -> Python re 讀取並找出 .dat 檔連結 -> Python requests 模組下載。
變數一覽:
## 搜尋區間 Period ## cbdates="" # hidden fyr1="1995" # 開始年 fmn1="7" # 開始月 $fd1="5" # 開始日 tyr1="2017 # 結束年 tmn1="1" # 結束月 td1="31" # 結束日 ## 地點 Location ## blatitute="" # hidden stla1="20" # 緯度1(小) stla2="27" # 緯度2(大) longitude="" # hidden stlo1="118.0" # 經度1(小) stlo2="124.0" # 經度2(大) ## 規模範圍 Magnitude Constraint ## ML="" # hidden ml1="3.0" # ml下界 ml2="8.0" # ml上界 Mw="" # hidden mw1="3.0" # mw下界 mw2="8.0" # mw上界 ## 深度範圍 Depth Constraint ## depth="" # hidden dep1="0" # 深度下界 dep2="300" # 深度上界 ## CMT 格式設定 Data Type (name="btype") ## # F (Final CMT) # Q (Quick CMT) # B (Both) (Default) btype="B" # 指定 CMT 格式 ## 指定輸出格式 Output Format (format) ## # full (Full format)(Default) # evtlst (Event List) # gmtf (GMT psmeca format ("-Sa" option for GMT version >= 3.3) event code ended with Q = quick CMT) # zmap ( ZMAP Format (ZMAP page) ) # seismicity ( Show Seismicity ) format="gmtf" # 指定輸出格式
瞭解了所有需要的內容後,我們就可以將所有的變數與對應的回應傳回給伺服器(http://tecws.earth.sinica.edu.tw/BATS/cmtsearch_result.php):
curl -X POST -v \ -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30" \ -F "cbdates=" \ -F "fyr1=1995" \ -F "fmn1=7" \ -F "fd1=5" \ -F "tyr1=2017" \ -F "tmn1=1" \ -F "td1=31" \ -F "blatitute=" \ -F "stla1=20" \ -F "stla2=27" \ -F "longitude=" \ -F "stlo1=118.0" \ -F "stlo2=124.0" \ -F "ML=" \ -F "ml1=3.0" \ -F "ml2=8.0" \ -F "Mw=" \ -F "mw1=3.0" \ -F "mw2=8.0" \ -F "depth=" \ -F "dep1=0" \ -F "dep2=300" \ -F "btype=B" \ -F "format=gmtf" \ http://tecws.earth.sinica.edu.tw/BATS/cmtsearch_result.php > cmtsearch_result.html
下載檔案(.dat)
當我們向伺服器要求完成後,伺服器會傳回一個結果呈現的網頁(./cmtsearch_result.php),一般來說,我們要點「Download GMT format file」才可以下載,但是看原始的網頁碼,可以發現一個包含結果的連結:
... <body> <!-- <p class="style2 style1"><strong>BATS CMT Catalog Search Result</strong></p> <hr /> //--> <p> <B>Total: 2444 Records</B><P><a href="#"><span onclick='window.open("./userdata//cmt/1485833677/gmt_meca.dat")'>Download GMT format file</a> </span></a></P><table align="center" > <tr align="right" valign="middle" onmouseover="OMOver(this);" onmouseout="OMOut(this);"> ...
上面的 window.open(“./userdata//cmt/1485833677/gmt_meca.dat“) 就是我們要的資料網址。
在這邊,我用 Python 3 的 re 模組來比出這一段字串,並補完完整網址後用 requests 模組完成下載。(註:這邊假設下載完的網頁檔名為「cmtsearch_result.html」)
# -*- coding: utf-8 -*- """ Find IES CMT (GMT format) download page url Created on Tue Jan 31 11:42:12 2017 Find the pattern like this: "./userdata//cmt/1485833677/gmt_meca.dat" @author: Aspiring_Wayne """ import io import re import requests def download_file(url): #ref : http://stackoverflow.com/questions/16694907/how-to-download-large-file-in-python-with-requests-py local_filename = url.split('/')[-1] # 設定 URL 最後一部份作為存檔檔名 r = requests.get(url, stream=True) with io.open(local_filename, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) return local_filename def main(): pat = re.compile("\./userdata//cmt/(\d+)/gmt_meca\.dat") with io.open("cmtsearch_result.html","rt") as fin: content = fin.read() #print(content) try: res=re.search(pat,content).group(0) print(res) except AttributeError as e: print("No matched result.\n".format(e)) return 1 download_file(r"http://tecws.earth.sinica.edu.tw/BATS/"+res[2:]) print("Download Finished!") return 0 if __name__ == "__main__": main()
之後再研究是否可以完全由 Python 完成工作~
示範輸出
$ curl -X POST -v \ > -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30" \ > -F "cbdates=" \ > -F "fyr1=1995" \ > -F "fmn1=7" \ > -F "fd1=5" \ > -F "tyr1=2017" \ > -F "tmn1=1" \ > -F "td1=31" \ > -F "blatitute=" \ > -F "stla1=20" \ > -F "stla2=27" \ > -F "longitude=" \ > -F "stlo1=118.0" \ > -F "stlo2=124.0" \ > -F "ML=" \ > -F "ml1=3.0" \ > -F "ml2=8.0" \ > -F "Mw=" \ > -F "mw1=3.0" \ > -F "mw2=8.0" \ > -F "depth=" \ > -F "dep1=0" \ > -F "dep2=300" \ > -F "btype=B" \ > -F "format=gmtf" \ > http://tecws.earth.sinica.edu.tw/BATS/cmtsearch_result.php > cmtsearch_result.html Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 140.109.82.7... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to tecws.earth.sinica.edu.tw (140.109.82.7) port 80 (#0) > POST /BATS/cmtsearch_result.php HTTP/1.1 > Host: tecws.earth.sinica.edu.tw > User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30 > Accept: */* > Content-Length: 2337 > Expect: 100-continue > Content-Type: multipart/form-data; boundary=------------------------e4b8da9e6a22a70e > < HTTP/1.1 100 Continue 0 2337 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0} [2337 bytes data] < HTTP/1.1 200 OK < Date: Tue, 31 Jan 2017 05:20:41 GMT < Server: Apache/2.2.3 (Scientific Linux) < X-Powered-By: PHP/5.1.6 < Set-Cookie: PHPSESSID=dnnladbiaqv34kb2p536trhl51; path=/ < Expires: Thu, 19 Nov 1981 08:52:00 GMT < Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 < Pragma: no-cache < Content-Length: 7735 < Connection: close < Content-Type: text/html; charset=UTF-8 < Content-Language: en < { [7592 bytes data] 100 10072 100 7735 100 2337 7504 2267 0:00:01 0:00:01 --:--:-- 7711 * Closing connection 0