爬蟲、RESTful API、資料視覺化
TL;DR 寫了一個簡單可用的 prototype ,把抓資料、存資料、呈現資料和資料視覺化這幾件事兜起來,作為自己未來如果要作資料科學專案的腳手架,也 open source 給大家鞭一鞭
台灣 368 鄉鎮市區天氣預報 RESTful api 說明文件
背景
之前有需要用到台灣 368 鄉鎮市區的天氣預報,查了政府資料開放平台,有編號 9307 和 9309 的下列兩筆
不過都沒有提供 json 的 API ,而且內容看起來是縣市級的未來 72 小時的逐三小時的預報,不是鄉鎮市區級的,因此就寫了爬蟲抓資料,試提供 RESTful API,資料來源直接由中央氣象局的在地天氣報馬仔來抓,例如說大安區公所的範例
btw,在公部門開放資料的部目,目前看到健康保險資料服務做得還不錯,可以參考一下,還有以下兩個規範也是未來可努力的方向
- 民104.7 國發會 共通性資料存取應用程式介面(API)規範
- 民104.7 國發會 資料集詮釋資料標準規範
流程與技術棧
實作一個開放資料的 API prototype,資料來源由爬蟲去抓中央氣象局的資料,存在資料庫裡,然後再做一個 RESTful API 當作前後端的接口,開放給前端的 data consumer 作應用,概念上可以參考碁峰的 <資料視覺化使用 Python 與 JavaScript> 一書,以下簡稱視覺化參考書,想做的事很像,都是為現在當紅所謂資料處理顯學,做一些基礎的工作。那本書我沒有看完,後端也用了 Python 不同的工具,但它給了我蠻多啟發,以下詳述
資料的生命週期裡
- 我們會需要先把資料爬下來
- 觀察格式、清理出我們要的資料
- 存進 db ,資料持久化
- 如果需要的話進行一些加值運算再存回 db
- 使用 API 提供網路上存取 db 裡的資料
- 網頁、移動裝置…etc的前端應用使用 API
前、後端是相對的,在不同語境下有其指涉對象,在這裡我指的是網路資料的提供者與使用者,依上述資料週期來看,稍微提一下參考書與我的工具選擇
參考書的工具選擇
- (上述的 1、3項合併) 爬取:Scrapy + MongoDB
- 清理、探索 / 處理:IPython + Pandas + Matplotlib
- 提供:Flask RESTful API + MongoDB
- 轉換:D3.js
我的工具選擇
稍微寫了 Scrapy ,蠻容易上手的,可是感覺比較適合簡單而且 HTML 格式清晰的網站,例如 Scrapy 官方教程的示範網站,如果爬蟲需要比較複雜的互動,例如說處理 .NET 的 VIEWSTATE ,就覺得寫起來卡卡的,所以我就換一個方式,概念上我會用 pandas dataframe 或 csv 檔案當作 metadata ,適合快速迭代想法,確定存在關聯式資料庫時會大概的樣子,然後用 Jupyter + requests 來取代 Scrapy Shell 的資料調適步驟、 SQLAlchemy + MySQLdb 來取代 Scrapy Pipeline + MongoDB ,據說大量迸發的爬取可以用 multiprocessing 這個庫,不過我還沒用過
- 抓取:Jupyter + requests
- 清理:Jupyter + pandas + beautifulsoup
- 持久化:Jupyter + SQLAlchemy + MySQLdb
- 撰寫腳本:將 1-3 寫成 scripts ,如果需要計算模型或額外處理的話,在這裡連結
- 提供:Django REST Framework + MySQLdb
- 呈現:jQuery + D3.js + bootstrap
稍微提一下寫 Scrapy (1.4.0) 的寫法,主要修改下面檔案
- items.py (optional): 可寫可不寫,與 Django 的 models.py 概念不一樣,只是事先規範爬取的變數
- spider/myspider.py: 最主要關於抓取和 parsing HTML 的 code,如果不存在 db ,可以抓完直接 -o 輸出 json 檔
- settings.py: 各種配置,例如要不要經過 pipeline 存入 db
- pipelines.py: 爬下來的資料做後處理,連結 db 持久化
實作參考
之所以說是 prototype ,因為想法是做一個 Proof of Concept ,雖然可以用,但是缺乏安全與效能的探討,算是套套 framework 、踩踩坑,如果使用者數量有起來再來處理
跟其他的爬蟲 + API 解決方案比起來,例如說 AWS API Gateway + Lambda + Dynamodb,自己用框架可能多了一些工作,但至少使用的框架都是開源的,利於學習。還有就是我不想也不會使用 M$ 的解決方案,所以不要問說這些流程在 Windows 、.NET 下的對應關係。而且我只用到雲端資源做開發,就算 Laptop 使用 non-Linux OS,只要瀏覽器能上網也是可以玩玩看,甚至 git clone 完就可以改改 code ,做一個自己的 data processing demo。繼續往下閱讀的 prerequisite 大概就是有一點 Linux 的使用經驗,不會用 vim 的話至少要會其他 Linux 上的純文字編輯器像是 nano
開發環境建置
我在 Cloud9 上的 Ubuntu14.04 環境下進行開發,然後在 CentOS 7 上部署,目前是比較偏好 redhat 系的發行版,不過雲端 IDE 好像都是 Ubuntu 居多,當然也可以自己開 CentOS 的開發虛擬機或 Container ,但就沒有雲端 IDE 方便
還需要設置 MySQL 5.7 (待補)
爬蟲與資料清理使用 requests 、 pandas 、 beautifulsoup4
這邊處理兩種資料
- (舊制)行政區域及村里代碼,對應全台 368 鄉鎮市區唯一編號,是網路上的 csv 檔案
- 另一種是 cwb 上的網頁資料,逐三小時鄉鎮天氣預報,嵌在不是很直觀的 HTML 表格裡
直接用 Jupyter notebook 來講解
- Lab1 整理各縣市鄉鎮區行政中心區碼
- Lab2 抓取大安區公所的逐三小時預報
- Lab3 利用 SQLAlchemy 創建 MySQL table
- Lab4 將 Lab1、Lab2 的結果利用 SQLAlchemy 存入 MySQL
- Lab5 利用 Lab1:4 建立的流程更新 MySQL 裡的氣象資料
確定怎麼寫之後,再把 Lab1:5 寫成 scripts ,我放在 crawler 資料夾裡,方便管理與 cron job 的執行
坑: 免費版的 Cloud9 container 不支援 crontab ,用 nohup + while loop 是可以試試看啦 參考
RESTful API 使用 Django REST Framework
(教學文件待補)
資料視覺化使用 jQuery + D3.js
(教學文件待補)
Django App 部署在 CentOS 7
(教學文件待補)
說明文件使用 MkDocs
寫完一個 Project 總是要寫一些文件讓人 follow ,最簡單的方法就是 Project 的 README.md ,不過如果資料多一點的話光是 README 可能不太夠寫,就需要建立一個說明文件的簡單網站。
- 文件量少:用 README.md
- 文件量中等:文件 source 與專案一同管理
- 文件量多:文件 source 與專案分開管理,單獨部署
身為一個懶惰偏 Python 的阿宅,我只想用最少的 effort 寫前端和 javascript,寫文件這種事當然使用 static site generator ,只要寫 markdown 就可以產生還算精美的外觀,讓我可以專注在內容,如果 Google API Documentation 的話應該會找到一些測試 + 文件的生成工具,像是 Postman 、 Swagger ,可是我只是要單純告訴使用者相關的網址與參數,不需要一個互動式的測試頁面,所以我選擇了 MkDocs 來當作我寫文件的工具,內容的部分,則是參考了這篇
TODO
- db 換成 PostgresSQL
- 測試把 Django 的 ORM 換成 SQLAlchemy 的好處
- 優化爬蟲的寫法
- 用 container 開發、佈署
- 寫 test case