Từ Sitemaps đến Liên kết Được Hiển thị: Bộ 6 Phương Pháp cho Khám Phá URL Toàn Bộ Trang web
Expert in Web Scraping Technologies
Những Điều Chính Cần Nhớ:
- Không có lệnh đơn nào liệt kê mọi trang. Một danh mục URL hoàn chỉnh đến từ việc sử dụng các phương pháp chồng lên nhau: toán tử tìm kiếm
site:để ước lượng nhanh,sitemap.xmlvà chỉ mục sitemap cho những gì trang web công bố, các chỉ thị Sitemap trongrobots.txtcho các điểm vào, một trình thu thập SEO hoặc một trình thu thập Python cho những gì thực sự được liên kết, và một trình duyệt đám mây cho các liên kết trên client-side chỉ xuất hiện sau khi JavaScript chạy. - Sitemaps là nguồn thông tin có thẩm quyền nhanh nhất — khi chúng tồn tại và được cập nhật thường xuyên. Một lệnh
requests.get("/sitemap.xml")duy nhất cộng với một vòng lặp đệ quy qua bất kỳ chỉ mục sitemap nào có thể trả về hàng trăm URL trong một lần. - Một trình thu thập theo chiều rộng tìm thấy những gì mà sitemaps bỏ qua. Sitemaps được biên soạn bởi tác giả và thường xuyên bị lỗi thời; một vòng lặp BFS qua các liên kết nội bộ
<a href>phát hiện các trang cô lập, nội dung được liên kết sâu và bất cứ điều gì mà sitemap đã quên. Trình thu thập trong hướng dẫn này tôn trọng các quy tắcDisallowtrongrobots.txttrên mỗi URL trước khi lấy nó. - Liên kết được render bằng JavaScript cần một trình duyệt thực. Ứng dụng một trang và các catalog cuộn vô hạn vẽ các liên kết nội bộ của chúng ở phía client, vì vậy một lệnh HTTP thuần sẽ trả về một shell gần như trống. Scrapeless Scraping Browser render trang trong một trình duyệt đám mây, sau đó bạn thu thập các anchor từ DOM đã được hydrate — với egress dân cư của Mỹ được gắn trên phiên.
- Miễn phí để bắt đầu. Các tài khoản Scrapeless mới bao gồm thời gian chạy Scraping Browser miễn phí — đăng ký tại app.scrapeless.com.
Giới thiệu: tại sao việc có một danh mục URL đầy đủ lại khó hơn nó xuất hiện
Biết mỗi trang trên một trang web là nền tảng cho nhiều công việc: một audit SEO kỹ thuật, một di chuyển nội dung, một cuộc quét liên kết hỏng, một pipeline giám sát giá cần mọi URL sản phẩm, hoặc một công việc hấp thụ LLM muốn toàn bộ tài liệu văn bản. Vấn đề là không có trang web nào cung cấp cho bạn danh sách đảm bảo hoàn chỉnh. Trang chủ liên kết đến hầu hết các phần, sitemap công bố một số trang, và các trang mồ côi — có thể tiếp cận qua liên kết trực tiếp nhưng không được liên kết từ điều hướng — trượt qua cả hai.
Các tùy chọn hiện có mỗi cái chỉ bao phủ một phần. Toán tử Google site: cung cấp một ước lượng công khai nhanh nhưng giới hạn kết quả và chỉ phản ánh những gì đã được lập chỉ mục. Một sitemap.xml là có thẩm quyền cho những gì mà nhà xuất bản chọn để tuyên bố, nhưng nó trở nên lỗi thời và bỏ sót các trang mà CMS chưa bao giờ đăng ký. Một trình thu thập theo dõi liên kết tìm thấy đồ thị liên kết, nhưng một trình thu thập HTTP đơn giản trả về một shell trống trên các trang nặng JavaScript nơi mà điều hướng được render ở phía client.
Hướng dẫn này sẽ đi qua sáu phương pháp theo thứ tự chi phí và độ đầy đủ — đầu tiên là rẻ và nhanh, cuối cùng là kỹ lưỡng và được render. Các ví dụ Python sử dụng requests và thư viện chuẩn cho các lớp tĩnh, và một trình duyệt đám mây thông qua Scrapeless Scraping Browser cho lớp JavaScript, vì vậy các liên kết ở phía client trở nên có thể phát hiện. Ghi egress Mỹ, render trang, thu thập các anchorage. Các liên kết chéo đến các hướng dẫn anh em sẽ có ở cuối.
Bạn Có Thể Làm Gì Với Nó
- Kiểm tra SEO kỹ thuật. Liệt kê mọi URL có thể lập chỉ mục, sau đó so sánh việc thu thập với sitemap để tìm ra các trang cô lập và các trang mà sitemap đã quên.
- Di chuyển nội dung. Xây dựng danh sách URL nguồn hoàn chỉnh trước khi thực hiện chuyển đổi để không có gì bị lỗi 404 sau khi chuyển đổi, và ánh xạ các đường dẫn cũ sang mới.
- Quét liên kết hỏng. Đi qua đồ thị liên kết nội bộ, ghi lại mọi đích đến, và đánh dấu những cái trả về trạng thái không phải 200.
- Giám sát giá và catalog. Phát hiện mọi URL sản phẩm trên một nhà bán lẻ — bao gồm cả những cái được render bằng JavaScript — và đưa chúng vào một pipeline trích xuất phía dưới.
- Hấp thụ văn bản LLM. Sản xuất bộ đầy đủ các URL nội dung để một công việc trích xuất văn bản có thể kéo toàn bộ tài liệu công cộng mà không bỏ lỡ các bài viết được liên kết sâu.
- Lập bản đồ nội dung cạnh tranh. Tính toán cấu trúc phần công khai của một đối thủ từ sitemaps và đồ thị liên kết để định kích thước dấu chân nội dung của họ.
Tại Sao Chọn Scrapeless Scraping Browser
Hầu hết hướng dẫn này chạy trên thư viện chuẩn Python và requests — sitemaps và robots.txt là văn bản thuần và XML, và một trình thu thập liên kết tĩnh không cần gì thêm. Scrapeless Scraping Browser là một trình duyệt đám mây tùy chỉnh, chống phát hiện được thiết kế cho các trình thu thập web và các tác nhân AI; đó là cấp độ mà bạn cần khi các liên kết bạn cần chỉ tồn tại sau khi JavaScript chạy. Để phát hiện URL toàn trang cụ thể, nó mang lại:
- Render JavaScript phía đám mây, vì vậy các liên kết nội bộ trên một ứng dụng một trang, một catalog cuộn vô hạn, hoặc một điều hướng React/Vue/Next.js xuất hiện trong DOM mà bạn đọc — không phải dưới dạng một
<div id="root">trống. - Proxy egress dân cư của Mỹ, được gắn cho mỗi phiên, vì vậy các trang web ggate địa lý sẽ phục vụ cùng một cấu trúc trang mà họ phục vụ cho một khách truy cập Mỹ.
- Chống phát hiện in dấu vân tay trên mỗi phiên, vì vậy trang được render khớp với những gì lưu lượng truy cập tự nhiên thấy thay vì một hồ sơ tự động bị đánh dấu.
- Liên tục phiên giữa việc điều hướng khởi động và trang mục tiêu, vì vậy một lần truy cập trang chủ thiết lập cookie sẽ được chuyển sang trang mà bạn thực sự muốn liệt kê.
- Một điểm cuối, CDP tiêu chuẩn, vì vậy Playwright (hoặc bất kỳ khách hàng Chrome DevTools Protocol nào) kết nối qua WebSocket mà không cần trình duyệt cục bộ thực hiện việc render.
Lấy khóa API của bạn trên gói miễn phí tại app.scrapeless.com.
Các yêu cầu cần thiết
- Python 3.10 trở lên.
- Tài khoản Scrapeless và khóa API — đăng ký tại app.scrapeless.com.
pip install requests playwrightvàplaywright install chromium(Chromium cục bộ chỉ là khách hàng giao thức CDP; việc render diễn ra trên đám mây của Scrapeless).- Sự quen thuộc cơ bản với terminal và HTTP.
Phương pháp 1 — Toán tử tìm kiếm Google site:
Ước lượng nhanh nhất đầu tiên không cần mã. Gõ vào Google:
site:example.com
Google trả về các trang mà nó đã lập chỉ mục cho máy chủ đó, và tiêu đề kết quả hiển thị số lượng gần đúng. Hãy thu hẹp lại để định hình cấu trúc phần:
site:example.com/blog— chỉ URLs dưới/blog.site:example.com inurl:product— các URL đã lập chỉ mục có đường dẫn chứaproduct.site:example.com -inurl:tag— loại trừ một đoạn đường dẫn mà bạn không quan tâm.
Phương pháp này tốt để làm gì: có cảm nhận trong ba mươi giây về quy mô của trang web và các phần hiện có. Nó không tốt để: tính toàn vẹn. Toán tử site: chỉ phản ánh các trang mà Google đã chọn để lập chỉ mục, số lượng kết quả là ước tính chứ không phải con số chính xác, và toán tử giới hạn số lượng kết quả mà bạn có thể duyệt qua. Hãy coi nó như một bài kiểm tra hợp lý so với các phương pháp chi tiết hơn bên dưới — nếu sơ đồ trang của bạn công bố 5.000 URLs và site: cho thấy khoảng 200, thì khoảng cách đó tự nó cũng là một phát hiện.
Phương pháp 2 — Phân tích sitemap.xml và chỉ mục sơ đồ
Sơ đồ trang là tuyên bố của nhà xuất bản về các URL của mình, được phục vụ dưới dạng XML tại một đường dẫn thông thường như /sitemap.xml. Đây là nguồn đáng tin cậy nhanh nhất khi nó tồn tại và được cập nhật. Hai hình dạng cần chú ý:
- Sơ đồ
<urlset>liệt kê các URL trang trực tiếp, một<url><loc>…</loc></url>cho mỗi trang. - Sơ đồ
<sitemapindex>liệt kê các sơ đồ khác — các trang web lớn chia sẻ các URL của mình qua các tệp con (pages_sitemap.xml,blog_sitemap.xml, v.v.) và trỏ đến chúng từ một chỉ mục. Bạn đi qua chỉ mục, rồi đi qua từng tệp con.
Kịch bản requests này xử lý cả hai hình dạng bằng một hàm đệ quy duy nhất. Nó phát hiện thẻ gốc, đệ quy vào một chỉ mục sơ đồ, và thu thập các URL trang từ mỗi <urlset>:
python
import requests
import xml.etree.ElementTree as ET
from urllib.parse import urljoin
SM_NS = "{http://www.sitemaps.org/schemas/sitemap/0.9}"
HEADERS = {"User-Agent": "Mozilla/5.0 (sitemap-discovery)"}
def walk_sitemap(url, seen=None):
"""Trả về mọi URL trang có thể truy cập từ một sơ đồ hoặc chỉ mục sơ đồ."""
seen = seen if seen is not None else set()
if url in seen: # bảo vệ chống lại một sơ đồ tham chiếu đến chính nó
return []
seen.add(url)
resp = requests.get(url, headers=HEADERS, timeout=30)
resp.raise_for_status()
root = ET.fromstring(resp.content)
tag = root.tag.split("}")[-1] # loại bỏ không gian tên, giữ lại "sitemapindex" hoặc "urlset"
urls = []
if tag == "sitemapindex":
# Một chỉ mục trỏ đến các sơ đồ con — đệ quy vào mỗi tệp.
for sm in root.findall(f"{SM_NS}sitemap"):
loc = sm.findtext(f"{SM_NS}loc")
if loc:
urls.extend(walk_sitemap(loc.strip(), seen))
else:
# Một urlset liệt kê trực tiếp các URL trang.
for u in root.findall(f"{SM_NS}url"):
loc = u.findtext(f"{SM_NS}loc")
if loc:
urls.append(loc.strip())
return urls
if __name__ == "__main__":
pages = walk_sitemap("https://example.com/sitemap.xml")
print(f"Đã phát hiện {len(pages):,} URL từ cây sơ đồ")
for u in pages[:10]:
print(" ", u)
Chạy trên một trang có /sitemap.xml là một chỉ mục sơ đồ trỏ đến các sơ đồ con, việc đi bộ đệ quy sẽ trả về tập hợp các sơ đồ con trong một lần.
Một vài lưu ý về các sơ đồ trong thực tế:
- Đường dẫn là quy tắc, không phải là sự đảm bảo.
/sitemap.xmllà vị trí phổ biến, nhưng một trang có thể đặt tên nó theo bất kỳ cách nào và tuyên bố đường dẫn thực tế trongrobots.txt(Phương pháp 3). Luôn kiểm trarobots.txttrước khi giả định tệp không tồn tại. - Có các sơ đồ nén. Một số trang phục vụ
sitemap.xml.gz;requestskhông tự động giải nén một tệp.gz, vì vậy hãy giải nén nó bằng mô-đungziptrước khi phân tích nếu bạn gặp phải một tệp như vậy. - Sơ đồ trang (Sitemaps) sẽ trở nên lỗi thời. Chúng phản ánh những gì CMS đã đăng ký tại thời điểm tạo ra. Các trang được thêm vào kể từ lần xây dựng cuối cùng, và các trang mồ côi mà CMS chưa bao giờ đăng ký sẽ bị thiếu — đó chính là lý do mà Phương pháp 5 và 6 tồn tại.
Phương pháp 3 — Đọc các chỉ thị Sitemap trong robots.txt
Trước khi bắt đầu thu thập bất kỳ thông tin nào, hãy lấy /robots.txt. Nó phục vụ hai mục đích cho việc khám phá URL: nó thường công bố vị trí sơ đồ trang với một hoặc nhiều dòng Sitemap:, và nó cho bạn biết những đường dẫn mà trang web yêu cầu robot tìm kiếm không được truy cập (Disallow:). Cả hai đều quan trọng — cái đầu tiên cung cấp thông tin cho Phương pháp 2, cái thứ hai là nghĩa vụ tuân thủ mà bạn mang vào Phương pháp 5.
python
import requests
from urllib.parse import urljoin
HEADERS = {"User-Agent": "Mozilla/5.0 (sitemap-discovery)"}
def sitemaps_from_robots(base_url):
"""Trích xuất mọi chỉ thị Sitemap: được công bố trong robots.txt."""
resp = requests.get(urljoin(base_url, "/robots.txt"), headers=HEADERS, timeout=30)
resp.raise_for_status()
sitemaps = []
for line in resp.text.splitlines():
if line.lower().startswith("sitemap:"):
sitemaps.append(line.split(":", 1)[1].strip())
return sitemaps
if __name__ == "__main__":
for sm in sitemaps_from_robots("https://example.com"):
print("Sitemap đã được công bố:", sm)
robots.txt của một trang web thường công bố một hoặc nhiều dòng Sitemap: — ví dụ Sitemap: https://example.com/sitemap.xml. Hãy đưa chúng trực tiếp vào walk_sitemap từ Phương pháp 2 và bạn sẽ có bộ URL hoàn toàn đã được công bố bởi nhà xuất bản mà không cần phải đoán đường dẫn.
Mô hình tổng hợp này là nền tảng của việc phát hiện tĩnh: đọc robots.txt để tìm sơ đồ trang và các đường dẫn không được phép, sau đó xem từng sơ đồ trang đã được công bố. Bất cứ điều gì mà hai điều đó trả về sẽ là danh sách chính thức khởi đầu của bạn. Mọi thứ sau đó đều nhằm tìm những trang mà chúng bỏ lỡ.
Nhận khóa API của bạn trên gói miễn phí: app.scrapeless.com
Phương pháp 4 — Các công cụ SEO thu thập dữ liệu (tùy chọn không mã)
Nếu bạn không muốn viết Python, một công cụ thu thập dữ liệu SEO desktop hoặc đám mây sẽ thực hiện việc khám phá, lập bản đồ liên kết, và báo cáo trong một công cụ. Những công cụ phổ biến — Screaming Frog SEO Spider, Sitebulb, và các công cụ kiểm tra trang web được tích hợp trong Ahrefs và Semrush — đều thực hiện công việc cốt lõi giống nhau: cung cấp một URL khởi đầu, theo dõi các liên kết nội bộ theo chiều rộng, và tạo ra bảng tất cả các URL được tìm thấy cùng với mã trạng thái, tiêu đề, độ sâu, và số lượng liên kết đến.
Các công cụ này là lựa chọn đúng khi:
- Bạn muốn một báo cáo trực quan và một xuất dữ liệu CSV mà không cần duy trì mã nguồn.
- Bạn cần các cột SEO tiêu chuẩn (trạng thái, chính thống, khả năng lập chỉ mục, chuỗi chuyển hướng) được tính toán cho bạn.
- Trang web chủ yếu là HTML được render từ máy chủ, điều mà các công cụ thu thập dữ liệu desktop xử lý một cách tự nhiên.
Những giới hạn của chúng thì đáng lưu ý: các gói miễn phí giới hạn số lượng URL (phiên bản miễn phí của Screaming Frog dừng lại ở 500 URL), việc render JavaScript là chế độ tùy chọn, chậm hơn mà không phải gói nào cũng cung cấp, và các công cụ kiểm tra đám mây tính phí theo kích thước dự án. Đối với một cuộc kiểm tra một lần của một trang web nhỏ, chúng rất khó để vượt qua; đối với một quy trình lặp lại đưa dữ liệu cho một hệ thống khác, các phương pháp lập trình dưới đây sẽ cung cấp cho bạn các URL dưới dạng dữ liệu thay vì báo cáo. Hai phương pháp tiếp theo là con đường lập trình đó.
Phương pháp 5 — Một công cụ thu thập dữ liệu liên kết nội bộ BFS bằng Python
Khi sơ đồ trang lỗi thời hoặc không có, bạn phát hiện các trang theo cách mà một công cụ tìm kiếm làm: bắt đầu từ trang chính, phân tích mỗi thẻ <a href>, xếp hàng những gì bạn chưa thấy, và lặp lại theo chiều rộng cho đến khi không còn liên kết nào hoặc bạn đạt đến giới hạn trang. Điều này tìm thấy các trang mồ côi và các trang liên kết sâu mà không có sơ đồ trang nào công bố.
Hai trách nhiệm là không thể thương lượng trong một công cụ thu thập dữ liệu liên kết, và cả hai đã được tích hợp trong mã dưới đây:
- Tôn trọng
robots.txt. Kiểm tracan_fetchcho mỗi URL trước khi yêu cầu nó, và bỏ qua bất kỳ thứ gì mà trang web không cho phép. Thư viện chuẩnurllib.robotparsersẽ đọc và đánh giá các quy tắc cho bạn. - Cách ly trên host và loại bỏ trùng lặp. Chỉ xếp hàng các liên kết mà host phù hợp với host khởi đầu, loại bỏ các phần URL để
/pagevà/page#sectionchỉ được tính một lần, và giữ một tập hợpseenđể đảm bảo rằng một vòng lặp trong đồ thị liên kết không bị lặp vô tận.
python
rp.read() # phân tích các quy tắc Disallow và bất kỳ crawl-delay nào
return rp
def crawl(start_url, max_pages=200, user_agent="*"):
"""Đi bộ theo chiều rộng các liên kết nội bộ, tôn trọng robots.txt."""
host = urlparse(start_url).netloc
robots = load_robots(start_url)
seen = {start_url}
queue = deque([start_url])
found, skipped = set(), []
while queue and len(found) < max_pages:
url = queue.popleft()
# Cổng tuân thủ: không bao giờ lấy một đường dẫn mà trang web cấm.
if not robots.can_fetch(user_agent, url):
skipped.append(url)
continue
try:
resp = requests.get(url, headers=HEADERS, timeout=30)
resp.raise_for_status()
except requests.RequestException:
# Một URL xấu được ghi lại ra ngoài băng, không bị theo đuổi nội tuyến.
continue
if "text/html" not in resp.headers.get("Content-Type", ""):
continue
found.add(url)
parser = LinkParser()
parser.feed(resp.text)
for href in parser.links:
absolute = urldefrag(urljoin(url, href))[0] # giải quyết + loại bỏ #fragment
if urlparse(absolute).netloc == host and absolute not in seen:
seen.add(absolute)
queue.append(absolute)
return found, skipped
if __name__ == "__main__":
pages, disallowed = crawl("https://example.com/", max_pages=200)
print(f"Đã phát hiện {len(pages):,} trang; đã bỏ qua {len(disallowed)} trang bị cấm bởi robots.txt")
---
Một lần chạy trực tiếp của trình thu thập thông tin này đối với một danh mục demo tĩnh đã phát hiện 40 trang với giới hạn đặt ở 40 và không có URL nào bị bỏ qua, vì `robots.txt` của trang đó không cấm gì. Khi chỉ định vào một trang có `robots.txt` cấm một đường dẫn, trình thu thập thông tin tương tự đã từ chối đúng URL bị cấm và ghi lại nó vào danh sách `skipped` thay vì lấy nó - việc tuân thủ đã được thực hiện cho mỗi URL, không phải là một suy nghĩ thứ cấp.
Cách mà điều này kết hợp với các phương pháp trước đó:
- **Trình thu thập tìm thấy những gì bản đồ trang web bỏ qua;** bản đồ trang web tìm thấy những gì trình thu thập không thể tiếp cận bằng liên kết. Chạy cả hai và lấy hợp nhất để có bảng kê đầy đủ nhất.
- **Sự cố giữ bên ngoài.** Một URL bị lỗi bị loại bỏ khỏi lần này và việc thu thập tiếp tục - một trang xấu không bao giờ làm dừng toàn bộ hành trình. Thu thập các URL bị loại bỏ riêng biệt để xem xét.
- **Giới hạn độ đồng thời để lịch sự.** Một trình thu thập đơn luồng như cái ở trên đã rất nhẹ nhàng. Nếu bạn song song hóa, hãy giữ nó ở **không nhiều hơn 3 công nhân mỗi chủ đề**, và tôn trọng bất kỳ `Crawl-delay` nào mà `robots.txt` tuyên bố.
- **Trình thu thập chỉ HTML.** Các liên kết được vẽ bằng JavaScript sau khi tải không nhìn thấy bởi `requests`. Khoảng trống đó chính là những gì Phương pháp 6 khép lại.
---
## Phương pháp 6 - Render các trang nặng JavaScript với Scrapeless Scraping Browser
Một trình thu thập dựa trên `requests` đọc bất kỳ byte nào mà máy chủ gửi. Đối với một ứng dụng trang đơn, một danh mục cuộn vô hạn, hoặc điều hướng React/Vue/Next.js, những byte đó là một vỏ ứng dụng - `<div id="root"></div>` cộng với một thẻ script - và các liên kết nội bộ được vẽ ở phía khách hàng khi gói chạy. HTTP thông thường không thể nhìn thấy chúng; một trình duyệt thực sự có thể.
Scrapeless Scraping Browser kết xuất trang trong một trình duyệt đám mây và mở nó qua Giao thức DevTools của Chrome. Bạn kết nối với Playwright qua một điểm cuối WebSocket, làm nóng trang chính để phiên mang theo cookie, điều hướng đến mục tiêu, sau đó thu thập các liên kết từ DOM đã được làm mát - tương tự như bước phân tích liên kết ở Phương pháp 5. Lưu lượng egress của Mỹ được gắn với phiên để các trang web geo-gated phục vụ cấu trúc tiêu chuẩn của họ.
Kết nối là một URL WebSocket duy nhất được xây dựng từ khóa API của bạn. Đây là hình dạng kết nối chính xác:
```python
import os
from urllib.parse import urlencode
from playwright.sync_api import sync_playwright
def scraping_browser_url(proxy_country="US", session_ttl=240):
params = urlencode({
"token": os.environ["SCRAPELESS_API_KEY"],
"sessionTTL": session_ttl,
"proxyCountry": proxy_country,
})
return f"wss://browser.scrapeless.com/api/v2/browser?{params}"
Với điểm cuối trong tay, hãy kết xuất mục tiêu và thu hoạch các liên kết nội bộ của nó:
python
from urllib.parse import urljoin, urldefrag, urlparse
def discover_rendered_links(start_url, proxy_country="US"):
"""Kết xuất một trang nặng JS trong trình duyệt đám mây và thu thập các liên kết cùng miền."""
host = urlparse(start_url).netloc
homepage = f"{urlparse(start_url).scheme}://{host}/"
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(scraping_browser_url(proxy_country))
context = browser.contexts[0] if browser.contexts else browser.new_context()
page = context.pages[0] if context.pages else context.new_page()
# Làm nóng trang chính trước để phiên mang theo cookie, sau đó đi đến mục tiêu.
page.goto(homepage, wait_until="domcontentloaded", timeout=60_000)
page.goto(start_url, wait_until="networkidle", timeout=60_000)
vi
# Đọc href từ DOM đã được hydrate, sau khi quá trình render phía máy khách đã chạy.
hrefs = page.eval_on_selector_all(
"a[href]", "els => els.map(e => e.getAttribute('href'))"
)
browser.close()
links = set()
for href in hrefs:
if not href:
continue
absolute = urldefrag(urljoin(start_url, href))[0]
if urlparse(absolute).netloc == host:
links.add(absolute)
return links
if __name__ == "__main__":
found = discover_rendered_links("https://example.com/app/catalog")
print(f"Đã phát hiện {len(found):,} liên kết phía máy khách sau khi render")
for u in sorted(found)[:10]:
print(" ", u)
---
Mô hình khiến điều này đáng tin cậy:
- **Khởi động trang chủ, sau đó điều hướng.** Lần đầu `goto` đến `/` cho phép phiên làm việc nhận cookie và vượt qua các kiểm tra tải lần đầu của trang; lần `goto` thứ hai hạ cánh trên trang bạn thực sự muốn liệt kê. Đi thẳng đến một URL sâu trong một phiên lạnh có khả năng cao hơn sẽ gặp phải thử thách.
- **`wait_until="networkidle"` trên mục tiêu** cho phép router phía máy khách có thời gian gắn kết các liên kết trước khi bạn đọc DOM. Đối với các trang cuộn vô hạn, hãy cuộn đến đáy trong một vòng lặp (`page.mouse.wheel`) cho đến khi số lượng liên kết dừng tăng, sau đó thu thập.
- **Quá trình render diễn ra trên đám mây của Scrapeless,** không trên máy của bạn. Lệnh `playwright install chromium` cục bộ chỉ là khách hàng CDP nói với điểm cuối `wss://browser.scrapeless.com/...`.
- **Phản hồi kết quả vào trong hợp nhất.** Các liên kết đã được render tham gia vào tập tin sitemap và tập tin thu thập tĩnh; loại bỏ trùng lặp bộ sưu tập kết hợp theo URL chuẩn hóa cho danh sách cuối cùng.
Để kết nối điều này vào một trình thu thập đầy đủ, hãy thay thế thân `requests.get` trong Phương pháp 5 bằng `discover_rendered_links` trên các máy chủ mà bạn biết là nặng JavaScript, và giữ con đường `requests` rẻ cho phần lớn được render phía máy chủ. Sự phân chia HTTP đầu tiên, trình duyệt thứ hai này giữ việc sử dụng trình duyệt đám mây cho các trang thực sự cần nó.
---
## Những gì bạn nhận lại
Mỗi phương pháp phát ra một tập hợp các URL tuyệt đối; danh sách cuối cùng là hợp nhất không trùng lặp giữa tất cả chúng. Một bản ghi hợp nhất cho một máy chủ trông như thế này:
```json
// Lược đồ phản ánh sự hợp nhất của bốn phương pháp lập trình.
// Số lượng là mẫu minh họa, không phải một bức tranh tĩnh của bất kỳ trang nào hôm nay.
{
"host": "example.com",
"discovered_at_methods": ["sitemap", "robots", "bfs_crawl", "rendered"],
"counts": {
"from_sitemap": 226,
"from_bfs_crawl": 40,
"from_rendered": 18,
"union_unique": 248
},
"sample_urls": [
"https://example.com/",
"https://example.com/blog",
"https://example.com/blog/how-to-scrape-bbb-business-listings",
"https://example.com/app/catalog?page=2"
],
"skipped_by_robots": [
"https://example.com/private/"
]
}
Một vài quan sát trung thực về việc phát hiện URL toàn bộ trang, đáng để biết trước khi chạy quy mô lớn:
- Hợp nhất tốt hơn bất kỳ nguồn đơn lẻ nào. Sitemaps công bố những gì nhà xuất bản đã đăng ký; việc thu thập BFS tìm thấy các liên kết mồ côi; lượt pass render tìm ra các liên kết phía máy khách. Sự bao phủ là hợp nhất của cả ba trừ những con đường bị cấm.
- Loại bỏ trùng lặp trên các URL chuẩn hóa. Gỡ bỏ các đoạn, quyết định xem các dấu gạch chéo phía sau và các tham số truy vấn
?utm_*có quan trọng cho trường hợp sử dụng của bạn hay không, và chuẩn hóa trước khi đếm — nếu không,/pagevà/page/sẽ làm phình to tổng số. - Sitemaps chậm hơn nội dung. Một trang được xuất bản sau lần tạo sitemap cuối cùng chỉ xuất hiện trong các cấp độ thu thập. Nếu một danh sách toàn bộ quan trọng, hãy luôn thực hiện một lần thu thập song song với việc đọc sitemap.
- Các liên kết phía máy khách là vô hình với HTTP. Nếu một lần thu thập
requestscủa một trang lớn đã biết chỉ trả về một vài URL, điều hướng hầu như chắc chắn là được render phía máy khách — nâng cấp máy chủ đó lên Phương pháp 6. - Tôn trọng danh sách không cho phép từ đầu đến cuối. Mảng
skipped_by_robotskhông phải là một danh sách TODO. Những con đường đó sẽ không được đưa vào danh sách.
Kết luận: xây dựng một danh sách URL hoàn chỉnh
Tìm mọi trang giảm xuống bốn bước lập trình được xếp chồng lên một kiểm tra thủ công: ước lượng kích thước với site:, đọc robots.txt để biết vị trí sitemap và các con đường không cho phép, đi bộ cây sitemap để biết các URL đã được công bố, thu thập BFS đồ thị liên kết nội bộ để tìm ra các liên kết mồ côi, và render các máy chủ nặng JavaScript trong trình duyệt đám mây để tìm các liên kết phía máy khách. Lấy hợp nhất, loại bỏ trùng lặp trên các URL chuẩn hóa, và đó là danh sách.
Đối với lớp proxy định tuyến tầng đã được hiển thị, xem [Proxy SSL là gì?](https://www.scrapeless.com/vi/blog/what-is-an-ssl-proxy-2026?utm_source=website&utm_medium=blog&utm_campaign=scrapingbrowser&utm_term=find-all-urls-website-scrapeless-scraping-browser). Trang sản phẩm [Scraping Browser](https://www.scrapeless.com/vi/product/scraping-browser?utm_source=website&utm_medium=blog&utm_campaign=scrapingbrowser&utm_term=find-all-urls-website-scrapeless-scraping-browser) và trang [giá cả](https://www.scrapeless.com/vi/pricing?utm_source=website&utm_medium=blog&utm_campaign=scrapingbrowser&utm_term=find-all-urls-website-scrapeless-scraping-browser) đề cập đến tầng trình duyệt đám mây; tài liệu SDK đầy đủ có tại [docs.scrapeless.com](https://docs.scrapeless.com?utm_source=website&utm_medium=blog&utm_campaign=scrapingbrowser&utm_term=find-all-urls-website-scrapeless-scraping-browser). Ghi US egress trên tầng đã được hiển thị, làm nóng trang chính trước trang mục tiêu, tôn trọng `robots.txt` trên mọi URL và coi danh sách cuối cùng là tập hợp của mọi phương pháp.
---
## Sẵn sàng để xây dựng quy trình dữ liệu AI của bạn?
Tham gia cộng đồng của chúng tôi để nhận kế hoạch miễn phí và kết nối với các nhà phát triển xây dựng quy trình phát hiện URL và thu thập dữ liệu: [Discord](https://discord.gg/VU2vtbq7Q2) · [Telegram](https://t.me/scrapeless).
Đăng ký tại [app.scrapeless.com](https://app.scrapeless.com/passport/login/?utm_source=website&utm_medium=blog&utm_campaign=scrapingbrowser&utm_term=find-all-urls-website-scrapeless-scraping-browser) để nhận runtime Scraping Browser miễn phí và điều chỉnh các mẫu trên cho các trang web, sơ đồ trang và khu vực mà quy trình cần.
---
## Câu hỏi thường gặp
**H: Việc thu thập dữ liệu một trang web để tìm tất cả các trang của nó có hợp pháp không?**
Việc phát hiện tự thân đọc các URL hiển thị công khai, nhưng tính hợp pháp phụ thuộc vào những gì bạn truy cập, từ đâu và theo điều kiện nào. Tôn trọng `robots.txt` của trang web, xem xét các điều khoản dịch vụ của nó, tránh các khu vực riêng tư hoặc yêu cầu xác thực, và tham khảo ý kiến cố vấn cho các trường hợp sử dụng nhạy cảm. Scrapeless chỉ truy cập dữ liệu công khai.
**H: Sơ đồ trang hay crawl — cái nào cung cấp danh sách đầy đủ?**
Không phương pháp nào có thể đứng một mình. Sơ đồ trang là tuyên bố của nhà xuất bản và thường không được cập nhật hoặc không đầy đủ; một lần thu thập dữ liệu tìm thấy đồ thị liên kết nhưng bỏ lỡ các trang không có liên kết nào tới trang đó. Danh sách đầy đủ là *hợp nhất* của việc đi bộ sơ đồ trang (Phương pháp 2) và crawl BFS (Phương pháp 5), với tầng đã hiển thị (Phương pháp 6) được thêm vào cho các liên kết phía client.
**H: Tại sao crawler của tôi chỉ tìm thấy một vài trang trên một trang web lớn?**
Trang web gần như chắc chắn sản xuất điều hướng phía client. Một yêu cầu `requests` đơn giản trả về mã nguồn ứng dụng trước khi JavaScript chạy, vì vậy không có liên kết nào để theo dõi. Render các máy chủ đó với Scrapeless Scraping Browser (Phương pháp 6) và thu thập các liên kết từ DOM đã được hydrate thay thế.
**H: Tôi có cần một proxy để phát hiện URL không?**
Đối với việc đọc sơ đồ trang từ một máy chủ duy nhất và một lần thu thập tĩnh lịch sự, thường là không. Một proxy xứng đáng khi trang web geo-gates nội dung (bạn cần US egress để xem cấu trúc của Mỹ), khi IP của bạn bị giới hạn tốc độ, hoặc khi tầng đã hiển thị cần egress từ nhà ở để phù hợp với lưu lượng truy cập tự nhiên. Kết nối Scrapeless trong Phương pháp 6 ghi egress với `proxy_country="US"`.
**H: Làm thế nào tôi có được một render sạch khi một trang phục thử thách truy cập?**
Ghi egress từ nhà ở tại Mỹ trên phiên và **làm nóng phiên** — điều hướng đến trang chính của trang web trước trong cùng một phiên trình duyệt trước trang mục tiêu, như mã của Phương pháp 6 thực hiện, để cookie được thiết lập và trang sâu tải trong ngữ cảnh đã được tin cậy. Một cú nhảy lạnh thẳng đến một URL sâu có nhiều khả năng thu hút thử thách hơn.
**H: Điều gì xảy ra khi trang web thay đổi HTML hoặc cấu trúc liên kết của nó?**
Crawler tĩnh dựa trên phần tử `<a href>` chung, vì vậy các thay đổi trong đánh dấu hiếm khi làm hỏng nó. Nếu bạn đã thắt chặt bộ chọn tầng render đến một container cụ thể, hãy kiểm tra lại khi đánh dấu thay đổi và mở rộng lại tới `a[href]` nếu trang web tái tổ chức điều hướng của nó.
**H: Làm thế nào tôi tránh đánh mạnh vào trang web khi thu thập dữ liệu?**
Crawler đơn luồng trong Phương pháp 5 đã khá nhẹ nhàng. Nếu bạn chạy song song, hãy giữ đồng thời **không quá 3 worker trên mỗi máy chủ**, tôn trọng bất kỳ chỉ dẫn `Crawl-delay` nào trong `robots.txt`, và không bao giờ xếp hàng một đường dẫn mà các quy tắc cấm che phủ.
**H: Làm thế nào tôi có thể loại bỏ các URL trùng lặp trong danh sách cuối cùng?**
Chuẩn hóa trước khi đếm: loại bỏ `#fragments`, quyết định xem một slash ở cuối và các tham số truy vấn theo dõi (`?utm_*`) có ý nghĩa cho trường hợp sử dụng của bạn hay không, và lưu trữ các URL trong một `set` được khóa trên hình thức chuẩn hóa. Mỗi phương pháp đã trả về một `set`; hãy lấy hợp nhất của tất cả chúng và các bản sao sẽ bị sụp đổ.
**H: Tôi có thể phát hiện các URL mà không cần một đại lý AI hoặc bất kỳ SDK nào không?**
Có. Các Phương pháp 1-5 chỉ sử dụng thư viện chuẩn Python và `requests`. Phương pháp 6 thêm Playwright kết nối với điểm cuối Scrapeless Scraping Browser qua CDP — không yêu cầu khung đại lý, chỉ URL WebSocket được xây dựng từ khóa API của bạn.
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.



