Python bài 21: Gọi HTTP API, xử lý JSON và tải dữ liệu
- 18-10-2026
- Toanngo92
- 0 Comments
Giáo trình Python miễn phí · Chương 11/12: HTTP và cơ sở dữ liệu · Bài 21/24.
Mục lục
Mục tiêu bài học
Thực hiện yêu cầu HTTP có timeout, kiểm tra trạng thái và xử lý dữ liệu trả về thay vì giả định mọi yêu cầu đều thành công.
HTTP và requests
HTTP trao đổi yêu cầu và phản hồi. GET thường lấy dữ liệu, POST thường gửi dữ liệu để xử lý. Phản hồi gồm status code, header và body. Phản hồi 200 chưa chắc có cấu trúc JSON mong đợi; lỗi mạng khác với phản hồi HTTP lỗi.
Cài requests trong môi trường dự án bằng python -m pip install requests. Ví dụ gọi dịch vụ minh họa công khai; cần Internet và dịch vụ có thể thay đổi hoặc tạm ngừng. Không đưa dữ liệu nhạy cảm vào dịch vụ thử nghiệm. Không bỏ xác minh TLS để tránh lỗi chứng chỉ.
import requests
try:
response = requests.get("https://httpbin.org/get", params={"chu_de": "Python"}, timeout=(3, 10))
response.raise_for_status()
data = response.json()
print(data["args"]["chu_de"])
except requests.exceptions.JSONDecodeError:
print("Phản hồi không phải JSON hợp lệ")
except requests.RequestException as loi:
print("Không thể hoàn thành yêu cầu:", loi)
except (KeyError, TypeError):
print("JSON không đúng cấu trúc dự kiến")
Khi dịch vụ trả đúng dữ liệu, kết quả là Python. params mã hóa query string; json=… trong POST gửi JSON, còn data=… thường gửi form hoặc dữ liệu đã định dạng. timeout=(3, 10) giới hạn kết nối và chờ đọc, không bảo đảm tổng thời gian của toàn bộ luồng tải luôn dưới 13 giây.
Tải tệp theo từng khối
Với tệp lớn, dùng stream=True và iter_content() để tránh nạp toàn bộ body vào bộ nhớ. Giới hạn dung lượng và đặt tên tệp trong thư mục do ứng dụng kiểm soát. Ví dụ tải một ảnh công khai, không nhận URL tùy ý của người dùng.
from pathlib import Path
import requests
tep = Path("anh_python_demo.png")
max_bytes = 5 * 1024 * 1024
so_byte = 0
try:
with requests.get("https://httpbin.org/image/png", stream=True, timeout=(3, 10)) as r:
r.raise_for_status()
with tep.open("wb") as f:
for chunk in r.iter_content(chunk_size=8192):
so_byte += len(chunk)
if so_byte > max_bytes:
raise ValueError("Tệp vượt giới hạn 5 MiB")
f.write(chunk)
print("Đã lưu", so_byte, "byte")
except (requests.RequestException, OSError, ValueError):
if tep.exists():
tep.unlink()
raise
HTML, API và xử lý lỗi
response.text là văn bản, response.content là bytes. Nếu cần lấy thông tin từ HTML, dùng parser như BeautifulSoup thay vì regex cho mọi cấu trúc. Cài beautifulsoup4 khi cần; ưu tiên API chính thức nếu có. Tôn trọng quyền truy cập và giới hạn tần suất.
Ghi nhận status code và loại lỗi bằng logging, không ghi token hoặc nội dung riêng tư. Retry phải có giới hạn và xét tính an toàn của thao tác; gửi lại POST có thể tạo dữ liệu trùng. Nếu tải tệp thất bại, dọn dữ liệu tải dở và giữ nguyên lỗi để bên gọi quyết định cách xử lý.
Lỗi thường gặp và lưu ý
- Luôn đặt timeout và xử lý lỗi; không dùng requests.get(url).json() như thể không thể thất bại.
- Không để máy chủ gọi URL người dùng nhập mà chưa kiểm soát đích truy cập.
Ghi nhớ
Luồng HTTP cần kiểm soát kết nối, trạng thái, định dạng và cấu trúc dữ liệu. Tải tệp cần giới hạn kích thước và dọn phần tải dở.
