Python 自學第十三天:取得網路公開資料 Open Data
在這一篇文章中,我們以 HTTP 通訊協定為例,利用 Python 直接讀取已經整理好的公開資料 (Open Data),通常 Open Data 會是固定的幾種格式: XML
、JSON
、CSV
、ODT
等。
網路連線
想要取得 Open Data,必須要網路連線至網站伺服器,要求 Server 回傳網頁資訊。因此,python 會模擬瀏覽器,使用模組向網站伺服器提出一些要求 (Request)。也就是如同一般我們在網址欄輸入網址後,瀏覽器背後運行的簡易過程。
- 引用
urllib.request
模組。 - 以
urlopen()
函式模擬瀏覽器,向目標網址建立連線:傳送要求 (Request) 和參數給網站伺服器,並且接收網站伺服器的回應 (Response),然後urlopen()
函式會將回應包裝成物件,回傳給程式中的變數。可以使用with
關鍵字實作,開啟 (得到)、讀取和關閉 Response 物件。 - 在
with
區塊中,依照不同檔案格式以不同語法讀取res
。和讀取檔案的語法相同,如果不熟悉,請參考:Python 自學第九天:讀取、寫入 Text、JSON 或 CSV 檔案。
1 | import urllib.request as req |
HTML 格式
如果目標網址是一般的網頁,也就是 HTML 格式,網站伺服器的回應就會是 HTML 網頁原始碼 (在網頁中,滑鼠按右鍵,點擊「檢視網頁原始碼」出現的東西)。
1 | import urllib.request as req |
網址:字串格式。
read():回傳字串。
如果要讀取中文網頁,記得 read()
讀取完後要解碼,如下:
1 | with req.urlopen(網址) as res: |
JSON 格式
如果目標網址是 Open Data 中的 JSON 格式,如下:
1 | import urllib.request as req |
json.load(res):回傳 List、字典資料格式。
例如,從臺北市內湖科技園區廠商名錄讀取,page_data
會得到如下的資料格式:
1 | { |
想要取得資料結構中的每一筆「案件地址」,語法如下:
1 | # 先用字典格式的語法取得 "results" 的值,也就是資料 List (上面的資料 line 8~9) |
最後,可以試著將讀取到的每一筆資料,依照之前學過的方法,寫入 (儲存) 到檔案中。
參考資料:
彭彭的課程:Python 網路連線程式、公開資料串接
SSL 認證
傳輸層安全性協定 (Transport Layer Security,TLS) 及其前身安全通訊協定 (Secure Sockets Layer,SSL) 是一種安全協定,目的是為網際網路通訊提供安全及資料完整性保障。想了解更多請參考維基百科。
問題
在使用 python 模擬瀏覽器,向網站伺服器提出網頁請求 (Request) ,也就是讀取網路公開資料或網頁的時候,如果網站伺服器的 https 證書不是從證書簽發機構購買,不符合 X509 憑證 (X509 Certificate Signatures),那麼就會報錯:
1 | # <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)> |
可以參考 PEP 476 其中一段:
Currently when a standard library http client (the urllib, urllib2, http, and httplib modules) encounters an https:// URL it will wrap the network HTTP traffic in a TLS stream, as is necessary to communicate with such a server. However, during the TLS handshake it will not actually check that the server has an X509 certificate is signed by a CA in any trust root, nor will it verify that the Common Name (or Subject Alternate Name) on the presented certificate matches the requested host.
The failure to do these checks means that anyone with a privileged network position is able to trivially execute a man in the middle attack against a Python application using either of these HTTP clients, and change traffic at will.
This PEP proposes to enable verification of X509 certificate signatures, as well as hostname verification for Python’s HTTP clients by default, subject to opt-out on a per-call basis. This change would be applied to Python 2.7, Python 3.4, and Python 3.5.
解決方案
Mac 系統中
應用程式 (Applications) >> Python 3.x >> Install Certificates.command
或是在終端機輸入以下命令:
1 | $ /Applications/Python\ 3.x/Install\ Certificates.command |
出現「程序完成」!
更多其他解決方法請參考:
解决Python certificate verify failed的问题
urllib and “SSL: CERTIFICATE_VERIFY_FAILED” Error