返回目錄
A
洞見數據:用分析思維駕馭數據科學 - 第 2 章
第二章:數據採集與存儲
發布於 2026-02-27 01:31
# 第二章:數據採集與存儲
> 本章聚焦於**從外部或內部系統取得資料**的技術與流程,並說明如何將資料安全、有效且可追蹤地存放起來。資料採集與存儲是數據科學生命週期中最基礎、最容易被忽略的環節,但它決定了後續清洗、分析與模型開發的品質與可重複性。
---
## 2.1 API 資料採集
### 2.1.1 API 類型
| 類型 | 說明 | 適用場景 |
|------|------|----------|
| RESTful | 基於 HTTP,使用 GET/POST/PUT/DELETE 取得/更新資源 | 公開資料、第三方服務 (OpenWeather, Twitter) |
| GraphQL | 一次請求可取得多層結構資料 | 複雜關聯資料、減少多次請求 |
| SOAP | XML 交換,具備安全與事務性 | 金融、政府系統 |
### 2.1.2 典型流程
1. **授權**:取得 API 金鑰或 OAuth 令牌。
2. **請求**:使用 `requests` 或 SDK 發送 HTTP 請求。
3. **資料驗證**:檢查 HTTP 狀態碼、JSON 結構、缺失欄位。
4. **儲存**:寫入 CSV、Parquet、資料庫或雲端儲存。
### 2.1.3 Python 範例(RESTful)
python
import requests, json, pandas as pd
from pathlib import Path
API_URL = "https://api.example.com/v1/items"
API_KEY = "YOUR_API_KEY"
headers = {"Authorization": f"Bearer {API_KEY}", "Accept": "application/json"}
params = {"page": 1, "per_page": 100}
all_data = []
while True:
resp = requests.get(API_URL, headers=headers, params=params)
resp.raise_for_status()
data = resp.json()
all_data.extend(data["items"])
if not data.get("next_page"):
break
params["page"] = data["next_page"]
# 儲存為 Parquet
df = pd.DataFrame(all_data)
output_path = Path("data/api_items.parquet")
df.to_parquet(output_path, engine="pyarrow")
print(f"資料已寫入 {output_path}")
> **備註**:若 API 速率受限,請加入 `time.sleep()` 或使用 `tenacity` 進行重試機制。
## 2.2 網頁爬蟲(Web Scraping)
### 2.2.1 基本概念
| 步驟 | 說明 |
|------|------|
| 1. 目標確定 | 確認要抓取的網頁 URL 與資料結構 |
| 2. 請求頁面 | 使用 `requests` 或 `httpx` 取得原始 HTML |
| 3. 解析內容 | 透過 `BeautifulSoup`, `lxml` 或 `Scrapy` 解析 DOM |
| 4. 儲存資料 | 匯出為 JSON、CSV 或寫入資料庫 |
### 2.2.2 常見陷阱
* **反爬機制**:IP 封鎖、JavaScript 渲染、CAPTCHA。解法:使用 Selenium、Puppeteer 或代理池。
* **版權問題**:遵循網站的 `robots.txt` 與使用條款。
* **資料結構變化**:建立爬蟲可監控頁面結構並自動提醒。
### 2.2.3 Python 範例(Selenium + BeautifulSoup)
python
from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd
# 1. 開啟瀏覽器
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
# 2. 目標頁面
url = "https://example.com/products"
driver.get(url)
# 3. 等待 JavaScript 生成
driver.implicitly_wait(5)
# 4. 取得頁面源碼
html = driver.page_source
soup = BeautifulSoup(html, 'lxml')
# 5. 解析資料
items = []
for card in soup.select('.product-card'):
title = card.select_one('.title').text.strip()
price = card.select_one('.price').text.strip()
items.append({"title": title, "price": price})
# 6. 儲存
df = pd.DataFrame(items)
df.to_csv('data/products.csv', index=False)
driver.quit()
## 2.3 結構化資料源與資料庫
| 技術 | 優缺點 | 推薦使用場景 |
|------|--------|--------------|
| SQL(MySQL, PostgreSQL, SQLite) | ACID 交易、複雜查詢 | 商業報表、交易資料 |
| NoSQL(MongoDB, CouchDB, DynamoDB) | 高彈性、水平擴展 | 日誌、非結構化資料 |
| OLAP(Snowflake, BigQuery) | 大規模分析、列式存儲 | BI、機器學習預測 |
### 2.3.1 連接示例(Python)
python
import sqlalchemy
from sqlalchemy import create_engine
# PostgreSQL
engine = create_engine("postgresql+psycopg2://user:pass@host:5432/dbname")
# 讀取資料表
df = pd.read_sql('SELECT * FROM sales', engine)
> **備註**:對於大批量資料寫入,使用 `COPY` 或批次插入可顯著提升效能。
## 2.4 雲端儲存與資料湖(Data Lake)
### 2.4.1 主要雲端存儲
| 雲端平台 | 儲存服務 | 特色 |
|-----------|----------|------|
| AWS | S3, Glacier | 物件存儲、低成本長期備份 |
| GCP | Cloud Storage, BigQuery | 與 GCP 服務整合、資料分析即時 |
| Azure | Blob Storage, Data Lake Storage Gen2 | 與 Azure 服務、Spark 兼容 |
### 2.4.2 資料湖設計原則
1. **Schema-on-read**:資料可任意儲存,讀取時再決定結構。
2. **分類與權限**:使用文件夾、標籤與 IAM 角色管理存取。
3. **生命周期管理**:自動將冷數據遷移至 Glacier / Archive。
### 2.4.3 與資料庫連結(Apache Spark)
python
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("DataLakeExample") \
.config("spark.hadoop.fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem") \
.getOrCreate()
# 讀取 Parquet
df = spark.read.parquet("s3a://my-bucket/raw/logs/2023-08/part-0000.parquet")
## 2.5 資料治理 (Data Governance) 與元資料管理 (Metadata Management)
### 2.5.1 為何重要
* **可追蹤性**:確保資料來源、採集時間、變更歷史。
* **品質保證**:定義資料品質指標(完整度、正確性、時間一致性)。
* **合規性**:滿足 GDPR、HIPAA 等法規。
### 2.5.2 主要概念
| 概念 | 定義 |
|------|------|
| **資料目錄 (Data Catalog)** | 追蹤資料集、來源、擁有者、版本 |
| **資料品質度量** | 完整度、重複度、時效性指標 |
| **資料所有權** | 定義資料擁有者、保護等級、審核流程 |
### 2.5.3 工具與平台
| 工具 | 角色 |
|------|------|
| **OpenMetadata** | 開源資料目錄,支援多雲、資料品質、監控 |
| **AWS Glue Data Catalog** | 與 S3/Redshift、Athena 整合 |
| **Azure Purview** | 全面治理、合規性管理 |
| **Google Data Catalog** | 元資料索引、搜尋 |
> **實作範例**:使用 OpenMetadata API 建立資料集元資料。
python
import requests, json
API_URL = "https://metadata.example.com/api/v1/datasets"
TOKEN = "OPENMETADATA_TOKEN"
headers = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
payload = {
"name": "sales_raw",
"location": "s3://my-bucket/raw/sales/",
"description": "Raw sales data from API",
"tags": ["raw", "sales"],
}
resp = requests.post(API_URL, headers=headers, data=json.dumps(payload))
resp.raise_for_status()
print("資料集已註冊於 OpenMetadata")
## 2.5 進階議題:ETL、流式資料與資料治理合流
1. **ETL(Extract‑Transform‑Load)**:傳統批次處理,適合日結、週結報表。
2. **ELT(Extract‑Load‑Transform)**:在資料湖中先寫入原始資料,後續由 SQL/Spark 進行轉換。
3. **流式資料(Kafka, Flink, Cloud Pub/Sub)**:低延遲資料流,適合 IoT、即時監控。
4. **資料管道監控**:使用 Airflow, Prefect, Dagster 進行排程與失敗告警。
---
## 2.6 小結
* **採集方式選擇**:根據資料型態、更新頻率與合規性決定使用 API、爬蟲、資料庫或雲端物件儲存。
* **儲存格式**:列式格式(Parquet、ORC)適合分析,文本格式(CSV、JSON)適合快速原型。
* **資料治理**:從一開始就建立資料目錄與元資料管理,可避免「資料失蹤」與「品質不一致」問題。
> **建議閱讀**:
> * *Designing Data-Intensive Applications* by Martin Kleppmann – 章節 4、6。
> * *Data Engineering on AWS* by Andy McCrory – 針對 S3、Glue、Athena 的實務設計。
---
> **實務提醒**:每次採集完資料後,請務必產生 **資料品質報告**(缺失率、重複率、時間戳對齊)並寫入 `log` 或 `dashboard`,以確保數據來源不會在未發現的情況下改變。