[GMT] 自動從中研院 BATS CMT Catalog Search 下載地震資料

我們會希望很方便的利用一條命令列就將所有的地震資料下載下來並處理,以下利用 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 選項,將表格中所需的參數一一填入並傳送給伺服器。

BATS stations (2016)
BATS stations (2016)

流程:

填表單( 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

 

請多多指教!

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料