Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Cào dữ liệu (web scraping) là kỹ thuật tự động đọc nội dung trang web và trích xuất thông tin cần thiết, ví dụ danh sách sản phẩm hay tiêu đề bài viết. Bài này hướng dẫn bạn làm từng bước với Python, requests và BeautifulSoup, đồng thời nhắc về những nguyên tắc đạo đức cần tuân thủ.
Không phải trang nào cũng cho phép cào dữ liệu. Trước khi bắt đầu, hãy làm ba việc:
/robots.txt ở gốc tên miền để biết đường dẫn nào được phép truy cập.Khi cào, hãy gửi yêu cầu thưa thớt, đặt khoảng nghỉ giữa các lần gọi để không gây tải cho máy chủ, và không thu thập dữ liệu cá nhân hoặc nội dung có bản quyền để phát tán. Trong bài, ta thực hành trên trang luyện tập dành cho người học scraping là books.toscrape.com, được tạo ra để thử nghiệm.
python -m venv venv
# kích hoạt môi trường ảo rồi:
pip install requests beautifulsoup4import requests
from bs4 import BeautifulSoup
URL = "https://books.toscrape.com/"
headers = {"User-Agent": "hoc-scraping-demo/1.0"}
response = requests.get(URL, headers=headers, timeout=10)
response.raise_for_status()
response.encoding = response.apparent_encoding
soup = BeautifulSoup(response.text, "html.parser")
print(soup.title.get_text(strip=True))Ba chi tiết đáng nhớ: timeout tránh treo vô hạn khi mạng chậm; raise_for_status() báo lỗi nếu mã trạng thái là 4xx hoặc 5xx; và thiết lập User-Agent rõ ràng giúp chủ trang biết ai đang truy cập.
Mở trang trong trình duyệt, bấm chuột phải vào một sản phẩm và chọn Inspect để xem cấu trúc HTML. Trên trang mẫu, mỗi cuốn sách nằm trong thẻ article có lớp product_pod. Ta dùng select với CSS selector để lấy:
books = []
for item in soup.select("article.product_pod"):
title = item.h3.a["title"]
price = item.select_one("p.price_color").get_text(strip=True)
link = item.h3.a["href"]
books.append({"title": title, "price": price, "link": link})
for b in books[:5]:
print(b["title"], "-", b["price"])Ghi nhớ các hàm chính: select trả về danh sách, select_one trả về phần tử đầu tiên hoặc None, get_text(strip=True) lấy chữ đã cắt khoảng trắng, và cú pháp tag["thuộc_tính"] lấy giá trị thuộc tính như href. Hãy kiểm tra None khi cấu trúc trang không đồng đều, nếu không bạn sẽ gặp lỗi AttributeError.
Trang mẫu có nút "next" dẫn sang trang kế tiếp. Ta theo liên kết đó cho đến khi hết, kèm khoảng nghỉ lịch sự:
import time
from urllib.parse import urljoin
def scrape_all(start_url, max_pages=3):
url = start_url
results = []
for _ in range(max_pages):
res = requests.get(url, headers=headers, timeout=10)
res.raise_for_status()
res.encoding = res.apparent_encoding
page = BeautifulSoup(res.text, "html.parser")
for item in page.select("article.product_pod"):
results.append({
"title": item.h3.a["title"],
"price": item.select_one("p.price_color").get_text(strip=True),
})
next_link = page.select_one("li.next a")
if not next_link:
break
url = urljoin(url, next_link["href"])
time.sleep(1) # nghỉ 1 giây giữa các lần gọi
return resultsHàm urljoin ghép liên kết tương đối thành địa chỉ đầy đủ. Giới hạn max_pages giúp bạn thử nghiệm an toàn trước khi chạy rộng.
import csv
data = scrape_all(URL)
with open("books.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=["title", "price"])
writer.writeheader()
writer.writerows(data)
print("Đã lưu", len(data), "dòng")Dùng bảng mã utf-8-sig giúp Excel đọc đúng tiếng Việt có dấu khi mở file CSV.
Bạn đã đi từ tải trang, chọn phần tử, duyệt nhiều trang đến xuất CSV. Điều quan trọng không kém kỹ thuật là thái độ: cào dữ liệu có trách nhiệm, tôn trọng robots.txt, giới hạn tần suất và ưu tiên API chính thức.
Nếu muốn dùng Python cho phân tích dữ liệu và tự động hóa, bạn có thể tham khảo các khóa học tại codebem.com.
Nguyễn Đình Cường
0 comment