Bài viết gần đây
Trang chủ → Bài Viết → Scrape Giá Coin Không Cần API Bằng Python | html.parser CoinGecko (Python 365 Ngày 53)
| Scrape Giá Coin Không Cần API Bằng Python | html.parser CoinGecko (Python 365 Ngày 53)
Được viết bởi Đặng Trí Thanh vào ngày 21/08/2026 lúc 10:26 | 24 lượt xem

Scrape giá coin là gì? Nếu bạn từng nghĩ “muốn lấy giá Bitcoin thì phải xài API” — thì Ngày 53 này sẽ đổi cách nghĩ của bạn. Web scraping cho phép bạn mở trang web bất kỳ, đọc mã HTML, và moi ra con số giá ngay trong đó — hoàn toàn không cần API, không cần key, không cần pip. Chỉ với hai thư viện có sẵn trong Python là urllib và html.parser.
Đây là bài thứ 53 trong chuỗi Python 365 ngày của Hướng Nghiệp Dữ Liệu. Hôm nay bạn sẽ học: scraping là gì, cách tải HTML, cách dùng html.parser để trích xuất giá, cách viết nhiều chiến lược dự phòng vì cấu trúc trang web luôn thay đổi, và nguyên tắc đạo đức scraping mà bất kỳ ai đi thu thập dữ liệu đều phải biết.
1. Scraping là gì? (Giải thích 60 giây)
Scraping (web scraping) là kỹ thuật đọc trang web như một con người đọc, nhưng bằng chương trình: bạn tải mã HTML của một trang, tìm vị trí chứa dữ liệu cần thiết (giá, tên, mô tả…), rồi trích xuất ra thành dữ liệu Python để xử lý tiếp.
Khi nào bạn cần scraping?
| Tình huống | API | Scraping |
|---|---|---|
| Trang web có API công khai | ✅ Dùng API | Không cần |
| Trang không có API (hoặc API trả phí) | ❌ Bó tay | ✅ Vẫn lấy được |
| Cần key, đăng ký, giới hạn request | ⚠️ Phức tạp | ✅ Không cần key |
| Cấu trúc trang thay đổi | Ổn định | ⚠️ Cần sửa chiến lược |
| Độ ổn định lâu dài | Rất ổn | ⚠️ Kém ổn định hơn |
Bài học hôm nay chọn một ví dụ thực tế: trang CoinGecko — trang theo dõi giá coin lớn nhất thế giới. Chúng ta sẽ lấy giá Bitcoin từ trang https://www.coingecko.com/en/coins/bitcoin mà không gọi bất kỳ API nào, chỉ đọc HTML.
Hãy tưởng tượng thế này: mỗi trang web bạn mở ra thực chất là một tài liệu văn bản có cấu trúc — hàng nghìn dòng HTML chứa đựng mọi thứ bạn nhìn thấy trên màn hình, từ con số giá đến nút bấm. Scraping chỉ đơn giản là: tải tài liệu đó về máy, tìm đúng “chỗ” chứa dữ liệu mình cần, và lấy ra. Nghe dễ, nhưng thực tế dạy cho chúng ta bài học đắt giá: trang web là mục tiêu di động — hôm nay giá nằm ở chỗ này, tuần sau họ sửa giao diện là giá nằm chỗ khác. Vì vậy, toàn bộ bài học hôm nay xoay quanh một chữ: dự phòng.
💡 Bạn đã học BeautifulSoup ở Ngày 46. Hôm nay dùng html.parser thuần — để chạy không cần cài thêm gì, và để hiểu sâu cơ chế bên dưới mọi thư viện parsing.
2. Chuẩn bị: không cần pip, không cần key
Điểm mạnh nhất của bài này: mọi thứ đều có sẵn trong Python.
urllib.request— tải trang web (có sẵn).html.parser.HTMLParser— phân tích HTML (có sẵn).re— biểu thức chính quy cho chiến lược dự phòng (có sẵn).json— đọc fallback API nếu cần (có sẵn).
Chỉ cần một file .py và chạy:
python "Day 53_Scrape gia coin.py"
Không pip install, không tài khoản, không API key. Đây chính là tinh thần của Python 365: dùng công cụ có sẵn giải quyết bài toán thật.
Bạn chỉ cần đảm bảo Python được cài đúng (bản 3.8 trở lên là chạy ngon — code dùng type hint list[str] nên bản 3.9+ là thoải mái nhất). Kiểm tra nhanh bằng lệnh:
python --version
Nếu máy bạn chưa có Python, hãy cài từ python.org — nhớ tick chọn “Add Python to PATH” khi cài. Còn nếu bạn dùng Google Colab (miễn phí, chạy trên trình duyệt) thì không cần cài gì cả — chỉ cần tạo notebook mới và dán code vào là chạy được ngay. Toàn bộ bài hôm nay không phụ thuộc hệ điều hành: Windows, macOS hay Linux đều chạy y hệt nhau.
3. Bước 1 — Tải HTML bằng urllib
Bước đầu tiên của mọi script scraping: tải mã HTML về. Có một mẹo quan trọng: nhiều trang web chặn request không có User-Agent (vì trông giống bot). Vì vậy chúng ta luôn gửi kèm một User-Agent hợp lệ:
import urllib.request
URL = "https://www.coingecko.com/en/coins/bitcoin"
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) PythonDay53"}
def fetch_html(url: str) -> str:
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=20) as resp:
return resp.read().decode("utf-8", errors="ignore")
Giải thích từng dòng:
Request(url, headers=HEADERS)— tạo request kèm header, giả làm trình duyệt.urlopen(...)— mở kết nối và tải về..read().decode("utf-8", errors="ignore")— đọc bytes rồi giải mã thành chuỗi;errors="ignore"giúp không chết khi trang có ký tự lạ.
Nếu bạn chạy thử và print(html[:300]), bạn sẽ thấy cả nghìn dòng HTML lộn xộn — công việc tiếp theo là tìm con số giá trong đống hỗn độn đó.
Đọc hiểu HTML: thẻ, attribute và cây DOM
Trước khi viết parser, hãy hiểu 3 khái niệm nền tảng của HTML:
| Khái niệm | Ví dụ | Ý nghĩa |
|---|---|---|
| Thẻ (tag) |
|
Khối nội dung, thường mở/đóng cặp |
| Attribute | data-price-target="btc" |
Thuộc tính gắn trên thẻ, chứa metadata |
| Text | $104,857 |
Nội dung hiển thị nằm giữa thẻ mở và đóng |
Ví dụ một đoạn HTML điển hình:
<span data-price-target="btc" data-price="104857.3">$104,857</span>
Để lấy giá, chúng ta có 3 con đường — và đây chính là lý do bài học này có 3 chiến lược:
- Đọc thẳng attribute
data-price(nhanh, chính xác — nhưng site có thể bỏ attribute). - Đọc text
$104,857rồi làm sạch (site đổi attribute nhưng vẫn hiển thị giá). - Regex tìm
"Bitcoin Price"gần con số$...(site thay đổi cả thẻ lẫn attribute).
Cấu trúc HTML lồng nhau tạo thành cây DOM (Document Object Model) — hiểu cây này giúp bạn hình dung chính xác phần tử nào chứa phần tử nào, từ đó chọn đúng thẻ cần tìm. Trong bài hôm nay, chúng ta chỉ cần một mảnh nhỏ của cây: thẻ có data-price-target="btc".
4. Bước 2 — html.parser: “búp bê ma thuật” tìm tag theo attribute
HTML là các thẻ (tag) lồng nhau:
, … Mỗi thẻ có thể có attribute — ví dụ .
Nhiệm vụ của chúng ta: tìm thẻ có attribute data-price-target="btc", rồi lấy con số giá từ đó. HTMLParser của Python cho phép chúng ta cắm vào 3 “móc” (hook) khi nó đọc qua HTML:
handle_starttag(tag, attrs)— gặp thẻ mở.handle_data(data)— gặp đoạn text.handle_endtag(tag)— gặp thẻ đóng.
Chúng ta viết một class nhỏ tên AttrFinder — một “búp bê ma thuật” chỉ chú ý đúng thẻ mình cần:
from html.parser import HTMLParser
class AttrFinder(HTMLParser):
"""Tìm tag đầu tiên có attribute == value, lấy text bên trong + attrs."""
def __init__(self, attr: str, value: str):
super().__init__()
self.attr, self.value = attr, value
self.found = False
self.parts: list[str] = []
self.tag_attrs = None
def handle_starttag(self, tag, attrs):
d = dict(attrs)
if d.get(self.attr) == self.value:
self.found = True
self.tag_attrs = d
def handle_data(self, data):
if self.found:
self.parts.append(data)
def handle_endtag(self, tag):
self.found = False
@property
def text(self) -> str:
return "".join(self.parts).strip()
Cách hoạt động:
handle_starttag— khi gặp thẻ nào có đúng attribute ta cần, bật cờfound = Truevà lưu toàn bộ attributes (để lấydata-price).handle_data— từ lúc bật cờ, gom hết text bên trong thẻ.handle_endtag— thẻ đóng thì tắt cờ (không lấy text ngoài phạm vi).text— nối các phần text lại, bỏ khoảng trắng thừa.
Đây chính là nguyên lý của mọi thư viện parsing HTML — từ BeautifulSoup đến lxml — chỉ là chúng gói gọn vào cú pháp tiện hơn. Nhớ kỹ: parser chỉ “quét qua” tài liệu một lượt, nên độ phức tạp tỷ lệ thuận với độ dài trang — với một trang giá coin, mọi thứ chạy trong vài mili-giây.
5. Bước 3 — Nhiều chiến lược trích xuất (vì site luôn đổi!)
Kinh nghiệm số một của người làm scraping: cấu trúc trang web thay đổi liên tục. Tuần này giá nằm trong data-price-target, tháng sau họ đổi sang class khác. Vì vậy chúng ta không bao giờ viết “một chiến lược duy nhất” — mà viết một chuỗi dự phòng (fallback chain).
Chiến lược 1: đọc thẳng attribute data-price
def strategy_data_price(html: str):
"""Tìm tag data-price-target='btc' -> lấy attribute data-price (USD)."""
parser = AttrFinder("data-price-target", "btc")
parser.feed(html)
if parser.tag_attrs and parser.tag_attrs.get("data-price"):
return float(parser.tag_attrs["data-price"])
return None
Nhanh và chính xác: CoinGecko đặt sẵn con số giá trong attribute data-price — ta chỉ việc lấy ra và đổi sang float.
Chiến lược 2: đọc text bên trong thẻ
Nếu họ bỏ attribute data-price, con số vẫn còn hiển thị trên màn hình — tức vẫn nằm trong text của thẻ:
def strategy_text_price(html: str):
"""Đọc text trong tag data-price-target rồi bóc dấu $ và dấu phẩy."""
parser = AttrFinder("data-price-target", "btc")
parser.feed(html)
text = parser.text.replace("$", "").replace(",", "")
if text and re.fullmatch(r"d+(.d+)?", text):
return float(text)
return None
Chú ý: text thường có dạng $104,857 — ta bóc bỏ $ và dấu phẩy, rồi kiểm tra bằng re.fullmatch xem có đúng là số không, tránh lấy nhầm “không có dữ liệu”.
Chiến lược 3: regex tìm kiếm “Bitcoin Price” kèm giá
Chiến lược cuối trước khi bỏ cuộc: tìm chuỗi "Bitcoin Price" và lấy con số $... xuất hiện ngay sau đó:
def strategy_regex(html: str):
"""Tìm '$60,000' gần chữ 'Bitcoin Price' (chiến lược cuối)."""
m = re.search(r"Bitcoin Price[sS]{0,200}?$([d,]+(?:.d+)?)", html)
if m:
return float(m.group(1).replace(",", ""))
return None
[sS]{0,200}? nghĩa là “bất kỳ ký tự nào (kể cả xuống dòng), tối đa 200 ký tự, lười biếng (non-greedy)” — đủ linh hoạt để vượt qua khoảng trống giữa chữ và số giá.
Ghép chuỗi dự phòng
price = strategy_data_price(html) or strategy_text_price(html) or strategy_regex(html)
or chạy lần lượt: chiến lược nào trả về số khác 0 thì dừng. Đây là pattern tuyệt vời — thêm chiến lược mới chỉ là thêm một hàm vào chuỗi.
6. Bước 4 — Fallback JSON API (khi mọi thứ thất bại)
Scraping đôi khi thất bại hoàn toàn (site chặn, thay đổi lớn). Lúc đó, chúng ta có “phao cứu sinh”: API miễn phí cùng nguồn. CoinGecko có API công khai không cần key:
def fallback_json_api():
"""Fallback cuối: JSON API cùng nguồn (để vẫn có số hiển thị)."""
url = ("https://api.coingecko.com/api/v3/simple/price?"
"ids=bitcoin&vs_currencies=usd")
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=15) as resp:
return float(json.loads(resp.read().decode("utf-8"))["bitcoin"]["usd"])
Nguyên tắc: người dùng luôn phải nhận được con số — dù bằng đường nào. Scraping là ưu tiên, API là dự phòng.
7. Code hoàn chỉnh Ngày 53
Đây là toàn bộ script Day 53_Scrape gia coin.py — bạn có thể chạy nguyên vẹn:
"""
Day 53 - Web scraping giá coin (không cần API)
Tải HTML trang CoinGecko, dùng html.parser (thư viện chuẩn) để
trích xuất giá Bitcoin. Có nhiều chiến lược dự phòng vì cấu trúc
trang web luôn thay đổi.
"""
import json
import re
import urllib.error
import urllib.request
from html.parser import HTMLParser
from pathlib import Path
URL = "https://www.coingecko.com/en/coins/bitcoin"
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) PythonDay53"}
SNIPPET = Path(__file__).parent / "page_snippet.html"
def fetch_html(url: str) -> str:
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=20) as resp:
return resp.read().decode("utf-8", errors="ignore")
class AttrFinder(HTMLParser):
"""Tìm tag đầu tiên có attribute == value, lấy text bên trong + attrs."""
def __init__(self, attr: str, value: str):
super().__init__()
self.attr, self.value = attr, value
self.found = False
self.parts: list[str] = []
self.tag_attrs = None
def handle_starttag(self, tag, attrs):
d = dict(attrs)
if d.get(self.attr) == self.value:
self.found = True
self.tag_attrs = d
def handle_data(self, data):
if self.found:
self.parts.append(data)
def handle_endtag(self, tag):
self.found = False
@property
def text(self) -> str:
return "".join(self.parts).strip()
def strategy_data_price(html: str):
"""Tìm tag data-price-target='btc' -> lấy attribute data-price (USD)."""
parser = AttrFinder("data-price-target", "btc")
parser.feed(html)
if parser.tag_attrs and parser.tag_attrs.get("data-price"):
return float(parser.tag_attrs["data-price"])
return None
def strategy_text_price(html: str):
"""Đọc text trong tag data-price-target rồi bóc dấu $ và dấu phẩy."""
parser = AttrFinder("data-price-target", "btc")
parser.feed(html)
text = parser.text.replace("$", "").replace(",", "")
if text and re.fullmatch(r"d+(.d+)?", text):
return float(text)
return None
def strategy_regex(html: str):
"""Tìm '$60,000' gần chữ 'Bitcoin Price' (chiến lược cuối)."""
m = re.search(r"Bitcoin Price[sS]{0,200}?$([d,]+(?:.d+)?)", html)
if m:
return float(m.group(1).replace(",", ""))
return None
def fallback_json_api():
"""Fallback cuối: JSON API cùng nguồn (để vẫn có số hiển thị)."""
url = ("https://api.coingecko.com/api/v3/simple/price?"
"ids=bitcoin&vs_currencies=usd")
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=15) as resp:
return float(json.loads(resp.read().decode("utf-8"))["bitcoin"]["usd"])
def main():
print("🕷️ Scrape giá Bitcoin từ CoinGecko (không cần API)n")
try:
html = fetch_html(URL)
except urllib.error.HTTPError as exc:
print(f"⚠️ Trang chặn/đổi: HTTP {exc.code}. Thử API dự phòng...")
print(f" Giá BTC (API): {fallback_json_api():,.2f} USD")
return
except Exception as exc:
print(f"⚠️ Lỗi tải trang: {exc}")
return
price = strategy_data_price(html) or strategy_text_price(html) or strategy_regex(html)
if price is None:
SNIPPET.write_text(html, encoding="utf-8")
print("ℹ️ Không tìm thấy giá (cấu trúc trang đã đổi).")
print(f" Đã lưu HTML ra {SNIPPET.name} để soi — mở file, tìm chỗ chứa giá,")
print(" rồi chỉnh lại attribute trong code.")
try:
print(f" Giá BTC (API dự phòng): {fallback_json_api():,.2f} USD")
except Exception:
pass
return
print(f"💰 Giá Bitcoin: {price:,.2f} USD")
print("n✅ Scraping thành công! Cấu trúc trang thay đổi là chuyện bình thường —")
print(" kỹ năng quan trọng là biết điều chỉnh chiến lược.")
if __name__ == "__main__":
main()
Kết quả khi chạy thành công:
🕷️ Scrape giá Bitcoin từ CoinGecko (không cần API)
💰 Giá Bitcoin: 104,857.32 USD
✅ Scraping thành công! Cấu trúc trang thay đổi là chuyện bình thường —
kỹ năng quan trọng là biết điều chỉnh chiến lược.
Bonus: lưu giá ra CSV để dùng tiếp
Lấy được giá rồi thì để làm gì? Tất nhiên là lưu lại để vẽ biểu đồ, theo dõi lịch sử, hoặc chạy cảnh báo. Chỉ cần thêm vài dòng vào cuối script (bạn đã học CSV ở Ngày 30-31):
import csv
from datetime import datetime
from pathlib import Path
CSV_PATH = Path(__file__).parent / "gia_coin.csv"
def save_price(coin: str, price_usd: float) -> None:
new_row = [datetime.now().isoformat(timespec="seconds"), coin, f"{price_usd:.2f}"]
is_new = not CSV_PATH.exists()
with CSV_PATH.open("a", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
if is_new:
writer.writerow(["thoi_gian", "coin", "gia_usd"])
writer.writerow(new_row)
Chạy script mỗi giờ (Windows Task Scheduler / cron trên Linux), bạn sẽ có một file gia_coin.csv tích lũy — nền tảng cho mọi dashboard hay phân tích sau này (kết hợp Ngày 57, 65 để vẽ biểu đồ đẹp).
8. Xử lý khi site chặn hoặc đổi cấu trúc
Đây là phần quan trọng nhất của bài học — tình huống thất bại là chuyện thường ngày:
- HTTP 403/429 (bị chặn): trang nhận ra bạn là bot. Khắc phục: đổi User-Agent giống trình duyệt thật, giảm tần suất request, thêm
timeout, xoay nhiều User-Agent. - HTTP 404 (trang đổi đường dẫn): URL cũ không còn tồn tại. Kiểm tra lại URL hiện tại của coin trên trang chủ, hoặc dùng trang tìm kiếm của sàn.
- Kết nối timeout: mạng chậm hoặc site chặn IP vùng. Tăng
timeout, thử lại lần 2 sau vài giây, hoặc đổi nguồn dữ liệu. - HTML tải về nhưng không tìm thấy giá: cấu trúc trang đã đổi. Script của chúng ta tự lưu HTML ra
page_snippet.html— mở file đó, bấm Ctrl+F tìm"Bitcoin Price"hoặc$, xem giá nằm trong thẻ/attribute nào, rồi cập nhật chiến lược. - Mọi thứ thất bại: fallback JSON API đảm bảo người dùng vẫn nhận được con số.
Chính vì vậy, script tốt luôn có: chuỗi dự phòng + tự lưu “bằng chứng” (snippet) + fallback. Đây là tư duy kỹ sư, không phải chỉ là viết code.
9. html.parser vs BeautifulSoup — khi nào dùng gì
Bạn đã học BeautifulSoup ở Ngày 46. So sánh nhanh:
| Tiêu chí | html.parser (Ngày 53) | BeautifulSoup (Ngày 46) |
|---|---|---|
| Cài đặt | Không cần (stdlib) | pip install beautifulsoup4 |
| Cú pháp tìm tag | Viết class + hooks | soup.select(), find_all() |
| Gọn code | Dài hơn | Ngắn hơn nhiều |
| Chạy trên máy không có pip | ✅ | ❌ |
Khi dùng trong dự án thật, bạn thường dùng BeautifulSoup vì nhanh hơn khi viết. Nhưng hiểu html.parser giúp bạn biết bên dưới hoạt động ra sao — và là lựa chọn cứu cánh khi không được phép cài thêm thư viện (máy chủ hạn chế, môi trường sandbox…).
10. Đạo đức scraping — 5 nguyên tắc bất biến
Scraping là công cụ mạnh, và mạnh thì phải dùng có trách nhiệm:
- Tôn trọng robots.txt — đọc
https://trangweb.com/robots.txttrước khi scrape; không scrape vùng bị cấm. - Không spam request — thêm
time.sleep(1)giữa các lần tải; chạy chậm, chạy lịch sự. - Chỉ lấy dữ liệu công khai — không vượt tường đăng nhập, không bỏ qua captcha.
- Không tải lại website — tải HTML một lần rồi lưu lại, xử lý offline.
- Kiểm tra điều khoản sử dụng — một số trang cấm scraping; tôn trọng quyết định của họ.
Scraping để học, để làm dashboard cá nhân, để theo dõi giá — hoàn toàn ổn. Scraping để đánh sập server người khác hay ăn cắp nội dung — thì không. Hãy là một “nhện” tử tế. 🕷️
Một nguyên tắc vàng nữa: dữ liệu lấy được hãy dùng cho việc học và ra quyết định cá nhân. Nếu bạn muốn xây dựng sản phẩm thương mại lấy dữ liệu từ một trang web, hãy đọc kỹ điều khoản sử dụng (Terms of Service) của họ — nhiều trang cho phép dùng miễn phí ở quy mô nhỏ, một số yêu cầu xin phép hoặc trả phí. Tôn trọng nguồn dữ liệu cũng là tôn trọng chính sản phẩm của bạn: một dự án dựa trên dữ liệu lấy bất hợp pháp sẽ sụp đổ ngay khi nguồn chặn lại.
11. Ứng dụng thực tế: từ giá coin đến hệ thống cảnh báo
Sau Ngày 53, bạn có thể kết hợp những gì đã học:
- Dashboard giá coin — scrape nhiều coin, lưu CSV, vẽ biểu đồ (kết hợp Ngày 57, 65).
- Cảnh báo giá — khi giá chạm ngưỡng, gửi tin nhắn Telegram (kết hợp Ngày 51).
- Theo dõi giá không cần API — những coin/sàn không có API miễn phí vẫn lấy được giá.
- Backtest dữ liệu lịch sử — lấy dữ liệu từ các trang tổng hợp (kết hợp Ngày 60).
Mảnh ghép Python 365 của bạn đến nay: Binance API (Ngày 39, 42, 55) + BeautifulSoup (Ngày 46) + Telegram Bot (Ngày 51) + Web scraping thuần (Ngày 53) — bạn đã có đủ bộ công cụ để xây dựng hệ thống theo dõi thị trường từ số 0.
Ví dụ một “sản phẩm nhỏ” bạn có thể tự làm sau hôm nay: bot theo dõi giá coin qua Telegram. Bot mỗi giờ scrape giá Bitcoin, lưu vào CSV, so sánh với mức giá trước đó, và nếu biến động vượt ngưỡng (ví dụ ±2%) thì gửi tin nhắn vào Telegram của bạn (dùng bot đã học ở Ngày 51). Toàn bộ hệ thống chỉ cần Python thuần + máy tính chạy thường xuyên — không tốn phí API, không cần server đắt tiền. Đây chính là sức mạnh của việc nắm nhiều mảnh ghép: bạn không phụ thuộc vào một công cụ duy nhất.
12. Bài tập thực hành hôm nay
Học mà không làm thì bằng không — đây là 3 bài tập tăng dần cho Ngày 53:
- Cơ bản: Chạy script
Day 53_Scrape gia coin.pynguyên bản, ghi lại con số giá in ra. Thử tắt User-Agent xem trang phản ứng thế nào (bạn sẽ thấy giá trị của header này). - Trung bình: Sửa script để scrape thêm 2 coin nữa (Ethereum, Solana) — gợi ý: đổi URL sang
https://www.coingecko.com/en/coins/ethereumvà tham số củaAttrFinder; thêmsave_price()từ phần Bonus để ghi cả 3 coin vào CSV. - Nâng cao: Viết hàm
scrape_any_coin(slug: str)dùng chung cho mọi coin, xử lý trường hợp coin không tồn tại (trang 404) — rồi chạy thử cho 10 coin phổ biến và xuất bảng giá ra CSV.
Hoàn thành bài 3, bạn đã có một “mini dashboard giá coin” bằng Python thuần — không API, không pip, chạy mọi nơi. Chia sẻ kết quả của bạn trong nhóm học viên HNDL nhé!
13. FAQ
Hỏi: Scraping có bất hợp pháp không? Không tự nó bất hợp pháp — nhưng tùy trang web và mục đích sử dụng. Luôn tôn trọng robots.txt, chỉ lấy dữ liệu công khai, không đánh sập server. Ở Việt Nam và hầu hết quốc gia, scraping dữ liệu công khai phục vụ học tập/cá nhân là bình thường.
Hỏi: Vì sao không dùng API CoinGecko luôn cho khỏe? Vì không phải lúc nào cũng có API (hoặc API trả phí, giới hạn request). Scraping là kỹ năng “cứu cánh” — và giúp bạn hiểu dữ liệu web hoạt động ra sao. Dùng song song: ưu tiên API khi có, scraping khi cần.
Hỏi: Trang web đổi cấu trúc thì sao? Chuyện bình thường! Script có chuỗi 3 chiến lược + snippet lưu HTML + fallback API — bạn chỉ cần soi snippet rồi cập nhật attribute, không cần viết lại toàn bộ.
Hỏi: Có cần proxy/VPS không? Không — cho việc học và dùng cá nhân, request đơn lẻ với User-Agent hợp lệ là đủ. Proxy chỉ cần khi scrape ở quy mô lớn (và lúc đó hãy cân nhắc lại đạo đức lẫn pháp lý).
Hỏi: Vì sao giá scrape được khác với giá trên app CoinGecko? Vì giá crypto biến động liên tục — giữa lúc trang hiển thị và lúc bạn tải về đã có vài giây chênh lệch. Ngoài ra các nguồn có thể dùng bảng giá khác nhau (spot, futures, trung bình sàn). Với mục đích theo dõi, sai số nhỏ là bình thường; nếu cần độ chính xác tuyệt đối, hãy dùng API chính thức.
Hỏi: Scrape được những dữ liệu gì ngoài giá coin? Mọi thứ hiển thị trên web: bảng xếp hạng coin, khối lượng giao dịch, tin tức, bình luận, giá sản phẩm, thời tiết… Kỹ thuật trong bài này (tải HTML + tìm theo attribute + dự phòng) áp dụng được cho gần như mọi trang web tĩnh.
14. Kết luận
Ngày 53 đã trang bị cho bạn kỹ năng web scraping thuần Python — lấy giá coin (hay bất kỳ dữ liệu web nào) mà không cần API, không cần pip, không cần key. Bạn đã học:
- ✅ Tải HTML bằng
urllib.requestkèm User-Agent hợp lệ. - ✅ Dùng
html.parserviếtAttrFinder— tìm tag theo attribute và lấy text. - ✅ Viết chuỗi 3 chiến lược dự phòng (attribute → text → regex) vì cấu trúc trang luôn đổi.
- ✅ Fallback JSON API để người dùng luôn nhận được con số.
- ✅ 5 nguyên tắc đạo đức scraping.
Kỹ năng quan trọng nhất hôm nay không phải là code — mà là tư duy dự phòng: trang web sẽ đổi, request sẽ bị chặn, và script tốt là script biết cách tự cứu mình. Đó chính là sự khác biệt giữa người viết script và người xây dựng hệ thống.
Ngày tiếp theo trong hành trình: Ngày 54 — yfinance và dữ liệu chứng khoán. Còn bây giờ, hãy mở terminal, chạy script, và nhìn con số Bitcoin hiện ra từ một trang web mà bạn chưa từng gọi API nào. 🕷️💰
▶ Playlist Python 365 · 🌐 Website Hướng Nghiệp Dữ Liệu · 📌 Lập trình Python nâng cao — Tự động hóa
Weekly Digest — Nhận Bản Tin Hàng Tuần
Nhận các bài viết phân tích kỹ thuật chuyên sâu, thuật toán giao dịch tự động (Trading Bot) và các giải pháp công nghệ mới nhất từ Hướng Nghiệp Dữ Liệu.
Đặng Trí Thanh
Giám đốc Công nghệ · DNT Digital · Giảng viên HNDLĐặng Trí Thanh — Founder & CTO · Hướng Nghiệp Dữ Liệu - DNT Digital. Chuyên đào tạo và triển khai thực chiến Python, MT5 và hệ thống bot auto trading / IB cho học viên và doanh nghiệp.