BeautifulSoup Web Scraping: Từ HTML Tĩnh đến Các Trang Động
Expert in Web Scraping Technologies
TL;DR:
- BeautifulSoup phân tích HTML; nó không thực thi JavaScript. Nội dung phản hồi phải chứa các ghi chép mà bạn muốn chọn trước.
- Requests cộng với BeautifulSoup là con đường ngắn nhất cho các trang tĩnh. Lấy, xác minh, phân tích, chuẩn hóa và xuất ra trong một quy trình Python.
- Bộ chọn CSS là thực tế cho các thẻ lồng nhau. Giới hạn các bộ chọn trường bên trong mỗi ghi chép để giá trị không bị lạc qua các hàng.
- Các trang động cần một con đường thu thập khác. Kiểm tra một điểm đầu vào JSON nội bộ trước, sau đó sử dụng HTML đã render khi việc thực thi trình duyệt là cần thiết.
- BeautifulSoup vẫn hữu ích sau khi render. Universal Scraping API có thể trả về HTML trong khi BeautifulSoup giữ quyền quản lý việc phân tích và đầu ra JSON.
Việc thu thập dữ liệu web bằng BeautifulSoup hoạt động tốt nhất khi việc thu thập trang và phân tích HTML được xử lý như những công việc riêng biệt. Requests lấy một đại diện. BeautifulSoup biến đại diện đó thành một cây điều hướng được. Cả hai thao tác không chứng minh rằng nội dung phụ thuộc vào JavaScript đã xuất hiện.
Hướng dẫn này xây dựng một trình thu thập tĩnh, thêm phân trang giới hạn, chứng minh vấn đề vỏ rỗng trên một trang JavaScript, và giữ cùng một bộ phân tích BeautifulSoup sau khi thực hiện bước render được quản lý.
HTTP tĩnh, JSON nội bộ, hay HTML đã render?
Chọn con đường thu thập trước khi viết bộ chọn.
| Hành vi trang | Con đường tốt nhất đầu tiên | Vai trò của BeautifulSoup |
|---|---|---|
| Các ghi chép có mặt trong HTML ban đầu | Requests | Phân tích phản hồi trực tiếp |
| Trang tải các ghi chép từ một yêu cầu JSON công cộng | Requests đến điểm cuối ổn định đó | Chỉ phân tích các trường HTML nhúng nếu cần thiết |
| Nội dung cần thiết xuất hiện sau JavaScript | Trình render được quản lý hoặc trình duyệt | Phân tích HTML đã render trả về |
| Quy trình làm việc cần nhấp chuột, biểu mẫu hoặc thao tác phiên | Tự động hóa trình duyệt | Phân tích snapshot hoặc HTML cuối cùng |
Xem mã nguồn hoặc kiểm tra phản hồi của Requests, không chỉ bảng phần tử của trình duyệt. Trình duyệt hiển thị DOM sau JavaScript; Requests thấy phản hồi của máy chủ.
Điều kiện tiên quyết
Bạn cần Python, một môi trường ảo, và quyền truy cập vào các trang mục tiêu công cộng. Các ví dụ có thể chạy sử dụng requests và beautifulsoup4 với bộ phân tích HTML tích hợp sẵn của Python.
Tài liệu Beautiful Soup đề cập đến việc lựa chọn bộ phân tích và bộ chọn CSS. Tài liệu Requests quickstart mô tả cách xử lý phản hồi và kiểm tra trạng thái.
Cài đặt BeautifulSoup và Requests
Tạo một môi trường tách biệt và cài đặt các gói chính xác mà kịch bản nhập vào:
bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install beautifulsoup4 requests
Xác nhận rằng các nhập khẩu được giải quyết trước khi thêm mã mạng:
bash
python -c "import bs4, requests; print(bs4.__version__, requests.__version__)"
Thu thập một Trang HTML Tĩnh
Trang Quotes to Scrape công khai đặt mỗi thẻ trích dẫn trong HTML phản hồi. Bộ phân tích giới hạn văn bản, tác giả và thẻ bên trong mỗi ghi .quote.
python
import json
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
url = "https://quotes.toscrape.com/page/1/"
response = requests.get(url, timeout=30)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
records = []
for card in soup.select(".quote"):
records.append({
"text": card.select_one(".text").get_text(strip=True),
"author": card.select_one(".author").get_text(strip=True),
"tags": [tag.get_text(strip=True) for tag in card.select(".tag")],
"source_url": response.url,
})
next_link = soup.select_one("li.next a")
next_url = urljoin(response.url, next_link["href"]) if next_link else None
print(json.dumps({
"count": len(records),
"first": records[0],
"next_url": next_url,
}, indent=2))
Bộ phân tích thực hiện ba việc hữu ích: nó chọn các thẻ hoàn chỉnh trước, giữ mọi trường bên trong phạm vi thẻ, và bảo vệ URL nguồn. URL nguồn đó làm cho các vấn đề bộ chọn hoặc phân trang sau này có thể tái tạo được.
find_all vs Bộ chọn CSS
BeautifulSoup cung cấp cả tìm kiếm dựa trên phương pháp và lựa chọn CSS.
find()trả về thẻ đầu tiên phù hợp theo tên hoặc thuộc tính.find_all()trả về tất cả các thẻ phù hợp.select_one()trả về kết quả phù hợp bộ chọn CSS đầu tiên.select()trả về tất cả các kết quả phù hợp bộ chọn CSS.
Các bộ chọn CSS ngắn gọn cho các bố cục thẻ lồng nhau. Tìm kiếm dựa trên phương pháp có thể rõ ràng hơn khi khớp một thẻ và một thuộc tính. Chọn một phong cách cho một dự án và giới hạn các trường con dưới thùng chứa ghi chép.
Tránh các chuỗi bộ chọn dài gắn với các lớp trình bày. Thích thuộc tính bền vững, phần tử ngữ nghĩa, mẫu URL ổn định, hoặc khóa JSON nội bộ khi trang công khai chúng.
Thêm Phân Trang Giới Hạn
Phân trang cần một điều kiện dừng ngay cả khi mục tiêu hiện tại có một liên kết tiếp theo rõ ràng. Kịch bản này thu thập hai trang tĩnh và dừng sớm khi liên kết biến mất.
python
import json
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
url = "https://quotes.toscrape.com/page/1/"
rows = []
for _ in range(2):
response = requests.get(url, timeout=30)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
for card in soup.select(".quote"):
rows.append({
"text": card.select_one(".text").get_text(strip=True),
"author": card.select_one(".author").get_text(strip=True),
"source_url": response.url,
})
next_link = soup.select_one("li.next a")
if not next_link:
break
url = urljoin(response.url, next_link["href"])
print(json.dumps({"count": len(rows), "last": rows[-1]}, indent=2))
Sử dụng số lượng trang tối đa, bộ URL đã truy cập, và khóa ghi chép ổn định trước khi áp dụng mẫu vào một trang web lớn hơn. Giữ công việc song song nhỏ và tôn trọng chính sách của trang web.
Bắt đầu thu thập dữ liệu với Scrapeless
Tăng cường quy trình thu thập dữ liệu và tự động hóa của bạn với Scrapeless!
Đăng ký ngay hôm nay và nhận $5 tín dụng miễn phí — không yêu cầu thẻ tín dụng.Nhận tín dụng miễn phí của bạn ngay bây giờ trong Bảng điều khiển Scrapeless.
Tại sao BeautifulSoup trả về một trang động rỗng
Phiên bản JavaScript của cùng một bản demo trả về một shell HTML cho một yêu cầu trực tiếp. Các thẻ trích dẫn được đính kèm sau khi trình duyệt chạy các script của trang, vì vậy soup.select('.quote') không tìm thấy bản ghi nào trong phản hồi ban đầu.
Sự phân biệt này có thể nhìn thấy với một chẩn đoán ngắn:
python
import requests
from bs4 import BeautifulSoup
url = "https://quotes.toscrape.com/js/"
response = requests.get(url, timeout=30)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
print({
"status": response.status_code,
"title": soup.title.get_text(strip=True),
"quote_cards": len(soup.select(".quote")),
})
Trạng thái 200 có nghĩa là máy chủ đã trả về một phản hồi HTTP thành công; nó không có nghĩa là biểu diễn chứa các bản ghi kinh doanh. tiêu chuẩn ngữ nghĩa HTTP định nghĩa hành vi trạng thái, trong khi trình thu thập dữ liệu phải xác thực danh tính trang và các bộ chọn cần thiết.
Trước khi lựa chọn một trình hiển thị, hãy kiểm tra các yêu cầu Fetch/XHR trong công cụ phát triển của trình duyệt. Một phản hồi JSON công khai ổn định có thể nhỏ hơn và dễ xác thực hơn so với một DOM đã được hiển thị. Đừng tái hiện các yêu cầu phụ thuộc vào thông tin xác thực riêng tư, điểm cuối bị hạn chế, hoặc quyền hạn mà bạn không có.
Nơi BeautifulSoup Dừng Lại
BeautifulSoup dừng lại ở việc phân tích. Nó không chạy các script của trang, nhấp vào các điều khiển, duy trì môi trường thực thi của trình duyệt, hoặc giải quyết các vấn đề thu thập xảy ra trước khi HTML đến với trình phân tích.
API thu thập dữ liệu toàn cầu không rác có thể trả về HTML đã hiển thị cho các trang JavaScript công khai. BeautifulSoup sau đó có thể phân tích chuỗi trả về đó với các bộ chọn tương tự được sử dụng cho HTML địa phương.
Lưu ý: Yêu cầu đám mây bên dưới yêu cầu một
SCRAPELESS_API_KEYthuộc về người đọc. Hình dạng yêu cầu đã được xác thực; cuộc gọi bị hạn chế thông tin xác thực không được thực hiện trong môi trường này.
python
import os
import requests
from bs4 import BeautifulSoup
response = requests.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"]},
json={
"actor": "unlocker.webunlocker",
"proxy": {"country": "ANY"},
"input": {
"url": "https://quotes.toscrape.com/js/",
"jsRender": {
"enabled": True,
"waitUntil": "domcontentloaded",
"response": {"type": "html"}
}
}
},
timeout=60
)
response.raise_for_status()
payload = response.json()
if payload.get("code") != 200:
raise RuntimeError("Rendered HTML was not returned")
soup = BeautifulSoup(payload["data"], "html.parser")
records = [
{
"text": card.select_one(".text").get_text(strip=True),
"author": card.select_one(".author").get_text(strip=True),
}
for card in soup.select(".quote")
]
print({"count": len(records), "first": records[0] if records else None})
Tài liệu API thu thập dữ liệu toàn cầu định nghĩa việc hiển thị JavaScript và các tùy chọn phản hồi. Giữ cấu hình trình hiển thị trong lớp thu thập để trình phân tích vẫn có thể kiểm tra với các tài liệu HTML đã lưu.
Xác thực trước khi lưu JSON
Một trình phân tích nên từ chối trang sai thay vì xuất một tệp trống như là thành công. Xác thực:
- URL cuối cùng khớp với máy chủ và tuyến đường mong đợi;
- tiêu đề hoặc H1 xác định trang dự định;
- bộ chọn thẻ cần thiết tồn tại;
- mỗi bản ghi được chấp nhận chứa khóa kinh doanh của nó;
- các trường có thể null vẫn
nullthay vì dịch chuyển các giá trị lân cận; - URL nguồn được lưu trữ với từng hàng.
Giao thức loại trừ Robot chỉ định các chỉ thị cho crawler mà các khách hàng tự động được yêu cầu tôn trọng. Nó không thay thế quyền hạn hoặc luật pháp áp dụng.
Khắc phục sự cố trình thu thập BeautifulSoup
| Triệu chứng | Nguyên nhân có thể | Kiểm tra |
|---|---|---|
| Không có bản ghi nào với trạng thái 200 | Nội dung được hiển thị bằng JavaScript hoặc bộ chọn sai | Kiểm tra HTML phản hồi và phần tử cần thiết |
| Văn bản rối rắm | Mã hóa phản hồi sai | So sánh tiêu đề, siêu dữ liệu tài liệu và thân đã giải mã |
| Các trường kết hợp với thẻ sai | Các bộ chọn trường toàn cầu | Phạm vi các truy vấn trường dưới mỗi контейнер bản ghi |
| Các hàng trùng lặp | Vòng lặp phân trang truy cập lại một URL | Theo dõi các URL đã truy cập và khóa bản ghi ổn định |
| Hành vi của trình phân tích khác biệt | Backend trình phân tích khác nhau | Ghi rõ trình phân tích được chọn |
Kết luận
Thu thập dữ liệu web bằng BeautifulSoup là đáng tin cậy khi phản hồi đã chứa dữ liệu. Các yêu cầu xử lý thu thập tĩnh; BeautifulSoup xử lý việc phân tích; phân trang có giới hạn và xác thực biến kết quả thành đầu ra có cấu trúc.
Đối với các trang động, hãy kiểm tra một nguồn JSON công khai nội bộ trước. Khi trạng thái trang cần JavaScript, trả về HTML đã hiển thị thông qua API thu thập dữ liệu toàn cầu và giữ BeautifulSoup như là trình phân tích.
Giữ Phân Tích Python, Di Chuyển Việc Hiển Thị Lên Đám Mây
So sánh giá cả của Scrapeless, nghiên cứu ranh giới của trình duyệt trong hướng dẫn tải xuống Puppeteer, và tạo một tài khoản Scrapeless. Tham gia Discord hoặc Telegram để thảo luận về việc triển khai.
Câu Hỏi Thường Gặp
Q: BeautifulSoup có tốt cho việc thu thập dữ liệu web không?
BeautifulSoup là một trình phân tích HTML và XML thực tế khi một thành phần khác đã thu thập tài liệu chính xác.
Q: BeautifulSoup có thể thu thập một trang web động không?
BeautifulSoup không thể thực thi JavaScript, nhưng nó có thể phân tích HTML được trả về bởi một API nội bộ, một trình hiển thị được quản lý, hoặc một bước tự động hóa trình duyệt.
Q: BeautifulSoup web scraping có hợp pháp không?
Chỉ thu thập dữ liệu công khai mà bạn được phép truy cập, xem xét các điều khoản của trang và hướng dẫn của robots, tối thiểu hóa việc thu thập, và tìm kiếm tư vấn pháp lý cho khu vực pháp lý liên quan.
Q: Các trình thu thập BeautifulSoup có cần proxy không?
Một yêu cầu tĩnh nhỏ được phép có thể không cần proxy; khối lượng công việc địa lý hoặc sản xuất có thể yêu cầu một proxy thích hợp và kiểm soát lưu lượng rõ ràng.
Q: Điều gì nên xảy ra khi DOM thay đổi?
Kiểm tra lại phản hồi hiện tại, xác định nguồn bền vững như một thuộc tính hoặc khóa JSON, thắt chặt các bộ chọn, và xác thực các trường cần thiết trước khi lưu trữ dữ liệu.
Q: Một trình thu thập BeautifulSoup nên sử dụng bao nhiêu đồng thời?
Bắt đầu với không quá ba công nhân mỗi máy chủ, quan sát chính sách trang và hành vi phản hồi, và giảm mức độ song song khi mục tiêu hoặc trường hợp sử dụng yêu cầu ít lưu lượng hơn.
Q: Các ví dụ có chạy mà không cần một đại lý AI không?
Có. Các ví dụ Python chạy trực tiếp; một đại lý là sự phối hợp tùy chọn xung quanh cùng các bước thu thập và phân tích.
Tại Scrapless, chúng tôi chỉ truy cập dữ liệu có sẵn công khai trong khi tuân thủ nghiêm ngặt các luật, quy định và chính sách bảo mật trang web hiện hành. Nội dung trong blog này chỉ nhằm mục đích trình diễn và không liên quan đến bất kỳ hoạt động bất hợp pháp hoặc vi phạm nào. Chúng tôi không đảm bảo và từ chối mọi trách nhiệm đối với việc sử dụng thông tin từ blog này hoặc các liên kết của bên thứ ba. Trước khi tham gia vào bất kỳ hoạt động cạo nào, hãy tham khảo ý kiến cố vấn pháp lý của bạn và xem xét các điều khoản dịch vụ của trang web mục tiêu hoặc có được các quyền cần thiết.




