COM6002 Big Data Management · Week 2
Data Collection (Data Ingestion)
COM6002 · Week 2 · Source: 2-Data collection.pptx (42 slides)
Contents · 15 sections
🎯 本講重點 (Learning outcomes)
- 分辨 internal vs external data sources,以及各自的收集技術
- 比較 RESTful API 同 Streaming API(request-response vs push、stateless vs stateful)
- 理解 API 的實際問題:rate limiting、data availability、data quality
- 掌握 HTTP GET vs POST、headers(API key、content type)、response status codes
- 比較 Webhook 同 Pub/Sub (e.g., Apache Kafka)
- 理解 web scraping / crawling 的三種方法、挑戰(dynamic content、CAPTCHA、IP blocking、login)、automated browser (Selenium / Playwright)、anti-scraping evasion 同 robots.txt
⭐ 考試必溫 Top-5
- RESTful vs Streaming 比較表(Simple / Stateless / One round / Client-initiated / header overhead vs Push-based / Persistent connection / Lower latency / Stateful / deltas)
- GET vs POST 比較表,以及「點解 POST 較安全」——唔係因為 encryption,而係 URL 會被 log
- HTTP status codes:2xx / 3xx / 4xx (400, 401, 403, 404) / 5xx (500, 503)
- Pub/Sub vs Webhook 比較表(3 parties vs 2 parties、persistent、replayable、pull/push、scalability)
- Web data 提取的 3 個 methods 及其 pros/cons;scraping challenges 同 robots.txt
1. Data sources:Internal vs External
Slide 2 "Roadmap" 係一張圖,文字擷取不到;請對照原 slide 第 2 頁。
| Internal data | External data |
|---|---|
| Captured by internal systems, e.g., Point-of-Sale System Key techniques: Database CRUD (Create, Read, Update, Delete) operations(之後講 database 時詳談) |
Third-party API Web scraping External databases — access to your business partners' databases Others… e.g., monitoring some telegram groups for crypto trading prediction |
呢一講就係 Week 1 data pipeline 的 Ingestion Layer:由不同 source 抽 raw data,放入 central storage。CRUD 對應 Week 4 SQL 的 INSERT / SELECT / UPDATE / DELETE。
2. Third-party API
例子情景:為 cryptocurrency trading analysis 拎數據。Data providers:Binance、IntoTheBlock、Santiment。
2.1 API characteristics:RESTful vs Streaming
- RESTful — Most common type of API;A request-response model:你 send 一個 request,server 回傳 a single, complete response (done)。
- Streaming — For real-time data delivery:你 connect 到一條 data stream,server pushes data to you as soon as new information becomes available;You need to stop the stream yourself。
- Other types:FIX (Financial Information eXchange) API, SOAP, GraphQL
Binance 兩種都有:RESTful endpoint(REST API)同 Streaming endpoint(WebSocket streams)。
2.2 Paid vs free
有啲 API 要付費(例如 Sanbase,以 USD 計價,slide 7 截圖顯示收費方案,圖片內容擷取不到)。Free plan 通常限制功能或者冇最新數據(in-class exercise 提到:Latest data is NOT available using a free API key)。
3. Concerns in using APIs
- Rate Limiting — 每段時間只准 call 若干次(例如 X / Twitter API 的 rate limits)。超過就會被拒(常見 HTTP 429)。
- Data availability — Not all data are provided via API。例子:Binance 的 News / Announcements 只喺網頁有,API 冇。
- Data quality — 真實經驗:(a) 付費 provider 某隻細價 crypto 的歷史價格錯咗 10 倍;(b) 另一個付費 provider 的 sentiment data,喺 LUNA 崩盤事件之後仍然顯示 positive???!
「付費 = 準確」係錯的。即使係付費 API,都要做 sanity check(例如同另一來源對比價格),呢個就係 Week 1 講的 Veracity。
4. Networking basics
Slide 10、11 用時序圖說明 RESTful 同 Streaming 的網絡交握過程,圖片內容擷取不到;請對照原 slide 第 10–11 頁。以下根據 slide 文字解釋。
- RESTful:Before you send your request and your data, you need to go through a handshaking process(preparation steps,例如 TCP/TLS 連線建立),然後先係 your request 同 your response。每個 request 都要重新經歷呢啲步驟。
- Streaming:都需要一啲 preparation steps 去建立 stream,但之後 connection is maintained,所有之後的 messages 可以由 server 直接傳俾 client(或反方向),唔使再 handshake。
| RESTful | Streaming |
|---|---|
| Simple(睇 example codes 感受一下) | More complex |
| Stateless — each request is independent | Stateful — usually, the messages are deltas(只傳「變咗乜」) |
| One round (only) — one request, one response | Persistent Connection — connection is kept, multiple messages |
| Initiated by the client | Push-based model — server proactively sends data to client |
| Repeats HTTP header overhead per request | Lower latency(冇重複 handshake / header 的 overhead) |
RESTful 似打電話問:「BTC 而家幾錢?」——問完收線,下次再問要再撥號(handshake)。Streaming 似開住條電話線,對方一有價格變動就即刻講俾你聽,而且只講「升咗 0.5」(delta),所以你要自己記住上一個價(stateful)。如果你中途漏聽一句,你手上的「state」就錯咗——呢個就係 stateful 較 complex 的原因。
Worked example:假設每次 REST request 的 handshake + header overhead 約 100 ms,你想每秒拎 10 次價格 → 每秒有 1,000 ms 花喺 overhead,根本做唔到;Streaming 只 handshake 一次,之後每個 update 幾 ms 就到。
5. HTTP requests:GET vs POST
| GET | POST | |
|---|---|---|
| Intended purpose | Retrieve data | Send data to server |
| Parameter location | In URL | In request body |
| Security | (Slightly) Less secure | (Slightly) More secure |
| Size limit | Limited (based on browser) | No limit |
In short, they use different formats to compose the request message to the server.
5.1 GET example(slide 14)
import requests
params = {
"symbols": '["BTCUSDT","ETHUSDT"]',
}
response = requests.get("https://api.binance.com/api/v3/ticker/price", params=params)
print(response.status_code) # 200 代表成功
print(response.json()) # 例如 [{'symbol': 'BTCUSDT', 'price': '...'}, ...]
requests 會自動將 params encode 入 URL:
https://api.binance.com/api/v3/ticker/price?symbols=%5B%22BTCUSDT%22%2C%22ETHUSDT%22%5D
(%5B = [、%22 = "、%2C = ,)。因為參數喺 URL,呢條 link 直接貼入 browser 都 work。
5.2 POST example
The parameters are NOT in the URL,而係放喺 request body(slide 15 截圖,圖片內容擷取不到)。示意:
import requests
# 參數放喺 body(JSON),唔會出現喺 URL
payload = {"symbol": "BTCUSDT", "interval": "1h"}
r = requests.post("https://example.com/api/query", json=payload)
print(r.status_code, r.text)
5.3 Why is POST considered more secure?
NOT because of encryption:加唔加密取決於用 HTTP(no encryption)定 HTTPS(with encryption),GET 同 POST 都可以行 HTTPS。
真正原因:The URL is logged in many places,例如 shown on the browser、bookmark、browser developer console(仲有 server log、proxy log)。將 parameters(maybe your API key)放喺 URL 係 not desired。POST 的參數喺 body,唔會咁容易留低記錄。
5.4 HTTP headers
你的 GET / POST request 可以喺 headers 提供額外資訊。Data collection 常見用途:
- Set your API key in your header — 令 server authenticate 你係邊個(具體 header 名睇 API documentation)
- Content type settings — 話俾 server 知 body 係乜 format,例如
application/json、application/xml - Client / server information — Which browser? Which OS? Device information?(即
User-Agent,之後 anti-scraping 會再講)
import requests
headers = {
"X-CMC_PRO_API_KEY": "你的API key", # CoinMarketCap 的 API key header(in-class exercise)
"Accept": "application/json",
}
r = requests.get(
"https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest",
headers=headers, params={"symbol": "BTC,ETH"})
if r.status_code == 200:
data = r.json()
for sym in ("BTC", "ETH"):
print(sym, data["data"][sym][0]["quote"]["USD"]["price"])
else:
print("Error", r.status_code, r.text)
5.5 HTTP Response status codes
| Class | 意思 | 常見 code |
|---|---|---|
| 2xx | Success | 200 OK(最常見) |
| 3xx | Redirection | — |
| 4xx | Client Error(你個 request 有問題) | 400 Bad Request;401 Unauthorized;403 Forbidden;404 Not Found |
| 5xx | Server Error(對方 server 有問題) | 500 Internal Server Error;503 Service Unavailable |
401 Unauthorized = 未認證(冇 / 錯 API key,「你係邊個?」);403 Forbidden = 知你係邊個,但你冇權限(例如 free key 想拎付費數據)。4xx 要改自己個 request;5xx 通常係 retry 或者等對方修好。
5.6 Python packages for API
有啲 provider 提供 custom package,進一步簡化 API 使用:OpenAI (openai)、Google API(Gmail、Google Drive:google-api-python-client)、Santiment (sanpy)。
6. Webhook
Push model:The data source proactively sends data as soon as an event happens——data provider 主動將資料 send 去你指定的 listener (server)。
- Alchemy — 拎 blockchain 數據;設定 (1) 你想收咩 data (2) 你 server 的 location(URL)去收(slide 21 截圖)
- WhatsApp — 有新 event(例如新 message)時通知你
# 一個最簡單的 webhook listener(Flask):provider 有新 event 就 POST 過嚟
from flask import Flask, request
app = Flask(__name__)
@app.route("/webhook", methods=["POST"])
def receive():
event = request.get_json() # provider 推送的資料
print("New event:", event)
return "", 200 # 回 200 OK,表示收到
app.run(port=8000)
7. Pub/Sub systems (e.g., Apache Kafka)
Slide 22(Pub/Sub broker 架構圖)同 slide 23(Gmail 用 Pub/Sub 讀取內容的例子)係圖片,文字擷取不到;請對照原 slide。
Publish-Subscribe Concept 的 Mechanism:
- Producers push event records to a topic
- Consumers subscribe to topics
- When a topic has a new message, each consumer gets the message
Properties:
- Producers do not know how many consumers have subscribed the topics(解耦)
- The messages are persistent(All messages are stored on disk)and replayable(Consumers can read historical messages)
| Pub/Sub | Webhook | |
|---|---|---|
| Architecture | 3 parties (producer – broker – consumer) | 2 parties (source – destination) |
| Data Persistence | Persistent | Usually lost |
| Data Replayability | Yes | No |
| Model | Pull or push | Push-only |
| Scalability | Higher (Producer sends once to broker; fan-out is handled by distributed cluster) | Lower (Source must manage individual HTTP POST calls to every destination) |
原 slide 25 表格的 Scalability 一行,"Lower" 寫喺 Pub/Sub 欄、"Higher" 寫喺 Webhook 欄,但括號內的解釋明顯係:Webhook 要逐個 destination 發 POST → scalability 較低;Pub/Sub 只 send 一次俾 broker、由 cluster 做 fan-out → 較高。上表按解釋內容排列;溫習時以解釋的邏輯為準,如有疑問請向講師確認。
Webhook = 速遞員直接送貨到你屋企門口,你唔喺度(server down)就冇咗。Pub/Sub = 速遞送去一個智能櫃(broker),貨會存住(persistent),你幾時去拎都得,甚至可以翻睇以前的貨(replayable);一千個人訂同一份報紙,速遞員都只係送一次去智能櫃。
8. Web crawling / scraping
Website are for human to read;好多網站上的 data 冇 (official) API(例如 Wikipedia 的內容)。Objective:Use a program to read and extract the data on the website。
8.1 Web data
- Data on the website are NOT pure text:係 HTML / JavaScript / CSS
- 可以用 Chrome developer console 睇 source code(Press F12)
- HTML = HyperText Markup Language:為 web browser 顯示而設計的文件語言;用 "tags" structure content;HTML is a text file;images data are provided in external files
8.2 Reading a website:三個方法
Challenge:How to extract the data on the web?(課堂 notebook:test_web.ipynb)
- Method 1:Manually read the HTML structure and map the data for automatic data extraction
- Method 2:Convert the entire webpage to a pure text version(using Beautiful Soup)
- Method 3:Use a visual enabled LLM to read, understand and extract data from the screencap of the website
import requests
from bs4 import BeautifulSoup
html = requests.get("https://en.wikipedia.org/wiki/Bitcoin",
headers={"User-Agent": "Mozilla/5.0"}).text
soup = BeautifulSoup(html, "html.parser")
# Method 1:睇清楚 HTML 結構,指定 tag / class 抽取 → structured data
infobox = soup.find("table", class_="infobox")
for row in infobox.find_all("tr"):
th, td = row.find("th"), row.find("td")
if th and td:
print(th.get_text(strip=True), "=>", td.get_text(" ", strip=True))
# Method 2:成頁轉做純文字 → unstructured text(generic,但結構冇咗)
text = soup.get_text("\n", strip=True)
print(text[:500])
8.3 Crawling 整個網站
有時唔止讀一頁,而係讀晒成個網站(例如 HSU 網站所有頁面)。Example handling:
- Extract the links,如果 links are on the same domain,visit them as well
- Avoid visiting the same link too(否則會兜圈)
- Popular tool:Scrapy
# 簡化版 crawler:BFS + visited set
from urllib.parse import urljoin, urlparse
import requests
from bs4 import BeautifulSoup
from collections import deque
start = "https://www.hsu.edu.hk/"
domain = urlparse(start).netloc
visited, queue = set(), deque([start])
while queue and len(visited) < 50: # 限制頁數,示範用
url = queue.popleft()
if url in visited: # 避免重複訪問
continue
visited.add(url)
soup = BeautifulSoup(requests.get(url, timeout=10).text, "html.parser")
for a in soup.find_all("a", href=True):
link = urljoin(url, a["href"]).split("#")[0]
if urlparse(link).netloc == domain: # 只跟同一個 domain
queue.append(link)
print(len(visited), "pages")
8.4 Challenges
- Dynamic Content — Contents are loaded dynamically(JavaScript)after the initial page has loaded;parse initial HTML 會 miss 呢啲內容
- CAPTCHAs — Automated security measures that block programmatic access
- IP Blocking and Rate Limiting — 讀得太密會被 block
- Login required — 內容要 login 後先見到
9. Automated web browser:Selenium / Playwright
Popular Python packages:Selenium / Playwright——A bot to browse the Internet,able to access information even after login,亦可以處理 dynamic content(因為真係行一個 browser,JavaScript 會執行)。
例子:Binance announcements only available on the web → 用途:monitor coming delisting events(slide 34 有截圖示範)。
Mechanism:Browsers provide native automation capabilities(對 web application 的 automated testing 好重要);Selenium/Playwright provides API (in Python) for using the browsers' automation capabilities。Other usages:web automation、form filling。
# Playwright 示意:打開 Binance announcement 頁,等 JavaScript 載入後讀標題
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://www.binance.com/en/support/announcement/list/48")
page.wait_for_timeout(3000) # 等 dynamic content 載入
for t in page.locator("a").all_inner_texts()[:20]:
if "Delist" in t:
print(t)
browser.close()
10. Comparisons between the three methods
| Method 1: Manual mapping of HTML structure | Method 2: Whole page → pure text | Method 3: Visual-enabled LLM | |
|---|---|---|---|
| Pros | Most accurate;provide structured data;easy to process in the future | More generic(任何頁都用得);often used in web browsing function of text-only LLM | A new approach(e.g., OpenAI Operator);capture data beyond text;prevent the HTML format parsing problems |
| Cons | When the website changes its structure, update of the web crawler is needed | Provide unstructured data;clarity of the extracted data may be limited | AI may not be very reliable(depends on how good your LLM is);Expensive — each data extraction is an LLM call |
Slide 36、37 用截圖示範 LLM 讀網頁 screenshot 抽數據,圖片內容擷取不到。
Worked example(成本估算):假設每次 LLM call 約 USD 0.01,每日監察 1,000 個網頁、每頁每小時一次 → 1,000 × 24 × 0.01 = USD 240/日。Method 1 寫好 parser 後幾乎零成本——呢個就係 "Expensive" 的意思。
11. Anti-scraping evasion
有啲網站會偵測 request 係人定 bot,然後 block:
- User-Agent:browser 每個 request 都會 send 一串 string 識別自己;Python / Selenium request 預設冇呢個 header → Solution:Add it on your own
- Reaction time between "clicks":bot 撳得太快太規律 → Solution:Adding some random wait time between clicks
- More advanced settings:Cookies, local storage, …
import random, time, requests
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124.0 Safari/537.36"}
for url in ["https://example.com/p1", "https://example.com/p2"]:
r = requests.get(url, headers=headers)
time.sleep(random.uniform(1, 3)) # 隨機等候,似人類行為,亦減少被 rate limit
CAPTCHAs:有好多種,基本上可以 modelled as a machine learning problem(讀完呢個 Master 你應該識 train 呢類 model);市面亦有 existing products 專門 solve CAPTCHAs。
12. Ethical concerns & robots.txt
Is web crawling ethical? Case study:一間新聞媒體喺網站出新聞,另一間公司 crawl 晒佢所有文章再放喺自己網站——明顯有版權 / 商業道德問題。
Examrobots.txt — the voluntary protocol:A plain text file,tell bots which parts of the site they are or are not allowed to access(例如 https://www.google.com/robots.txt)。重點係 voluntary:佢冇技術上阻止你,靠 crawler 自律遵守。
# robots.txt 例子
User-agent: *
Disallow: /search
Allow: /search/about
# Python 檢查是否允許
from urllib.robotparser import RobotFileParser
rp = RobotFileParser("https://www.google.com/robots.txt"); rp.read()
print(rp.can_fetch("*", "https://www.google.com/search?q=btc")) # False
Slide 41 有一張配圖,文字擷取不到。
13. In-class participation exercise
- Task 1:Apply for a free API key on coinmarketcap.com;download and run
test_api_key.ipynb - Task 2:讀 CoinMarketCap quotes/latest documentation,寫 code print Bitcoin 同 Ethereum 的 latest price(參考 §5.4 的 code)
- Task 3:讀 Santiment documentation,用 API 搵 Bitcoin 的 sentiment data(Santiment 用 GraphQL API)
- Notes:Latest data is NOT available using a free API key;may use vibe coding;2 marks class participation(Submit on Moodle)
自我測驗 Self-test
Q1. 比較 RESTful API 同 Streaming API(至少 4 點)。
RESTful:simple、stateless(每個 request 獨立)、one request one response、由 client 發起、每個 request 重複 HTTP header / handshake overhead。Streaming:push-based(server 主動推)、persistent connection(多個 messages)、lower latency、stateful(messages 通常係 deltas)、more complex、要自己停 stream。
Q2. 「POST 比 GET 安全,因為 POST 會加密。」對唔對?
錯。加密取決於 HTTP vs HTTPS,GET 同 POST 都可以用 HTTPS。POST 較安全係因為參數喺 request body;GET 參數喺 URL,而 URL 會被 browser 顯示、bookmark、developer console(及 server logs)記錄,API key 放 URL 容易洩漏。
Q3. 你 call API 收到 401、403、404、503,各代表乜?應該點處理?
401 Unauthorized:未認證 → 檢查 / 加入 API key header。403 Forbidden:冇權限 → 可能要升級 plan。404 Not Found:endpoint / resource 唔存在 → 檢查 URL。503 Service Unavailable:server 暫時唔得 → 稍後 retry。4xx 係 client error,5xx 係 server error。
Q4. 寫 Python code 用 GET 拎 Binance BTCUSDT 同 ETHUSDT 價格,並說明參數最終喺邊度。
requests.get("https://api.binance.com/api/v3/ticker/price", params={"symbols": '["BTCUSDT","ETHUSDT"]'})。參數被 URL-encode 後放喺 URL query string:?symbols=%5B%22BTCUSDT%22%2C%22ETHUSDT%22%5D,所以喺 browser 都可以直接開。
Q5. 比較 Pub/Sub 同 Webhook(architecture、persistence、replay、model、scalability)。
Pub/Sub:3 parties(producer–broker–consumer)、persistent(存 disk)、replayable、pull or push、scalability 較高(producer 只 send 一次俾 broker,fan-out 由 cluster 處理)。Webhook:2 parties(source–destination)、data usually lost、不可 replay、push-only、scalability 較低(source 要逐個 destination 發 HTTP POST)。
Q6. 一個網站的價格表係由 JavaScript 喺頁面載入後先顯示,用 requests + BeautifulSoup 會出咩問題?點解決?
Dynamic content:requests 只拎到 initial HTML,JavaScript 未執行,價格表唔喺入面。解決:用 automated browser(Selenium / Playwright)真正行 browser,等內容載入後先抽取;亦可處理 login。
Q7. Method 1(manual HTML mapping)同 Method 3(visual LLM)各有咩優缺點?
Method 1:最準、structured data、日後易處理;但網站改結構就要更新 crawler。Method 3:可捕捉文字以外的資料、避開 HTML parsing 問題;但 AI 未必可靠(視乎 LLM 質素),而且每次抽取都係一個 LLM call,好貴。
Q8. 列出兩種 anti-scraping 偵測方法同對應的 evasion,並解釋 robots.txt 的性質。
(1) 檢查 User-Agent header(Python 預設冇)→ 自己加 User-Agent。(2) 檢查 clicks 之間的反應時間 → 加 random wait time。進階:cookies、local storage。robots.txt 係 plain text file,告訴 bots 邊啲部分准 / 唔准訪問;係 voluntary protocol,靠自律遵守。
一頁總結 Cheat sheet
- Internal(POS, CRUD)vs External(third-party API, web scraping, partners' DB, others)
- REST:request-response, simple, stateless, one round, client-initiated, header overhead each time
- Streaming:push, persistent connection, lower latency, stateful (deltas), complex, 自己停
- Other APIs:FIX, SOAP, GraphQL;Paid vs free
- API concerns:Rate limiting / Data availability / Data quality(付費都可以錯)
- GET:retrieve, params in URL, slightly less secure, size limited;POST:send, params in body, slightly more secure, no limit
- POST 安全唔係因為加密(HTTPS 兩者都得),而係 URL 會被 log
- Headers:API key、Content-Type、User-Agent / client info
- 2xx 200 OK;3xx redirect;4xx client (400/401/403/404);5xx server (500/503)
- Webhook:push to your listener;Pub/Sub:producer → topic (broker, e.g., Kafka) → consumers;persistent + replayable
- Web data = HTML/JS/CSS;F12;Methods:(1) map HTML (2) to pure text (Beautiful Soup) (3) visual LLM
- Crawling:same domain links, avoid revisits, Scrapy
- Challenges:dynamic content, CAPTCHAs, IP blocking/rate limiting, login → Selenium / Playwright
- Evasion:User-Agent, random waits, cookies;CAPTCHA = ML problem;robots.txt = voluntary