Quay lại blog

Cách Thu Thập Dữ Liệu Nhiều Trang Web với Python và Scrapeless

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

12-Oct-2026

Tóm tắt ngắn gọn:

  • Thu thập nhiều trang cần một sổ cái đầu vào và một hàng đợi có giới hạn. Lưu lại kết quả cho mọi URL đã được chuẩn hóa thay vì coi một vòng lặp đã hoàn tất là bằng chứng đã bao phủ hết.
  • Khử trùng lặp URL và khử trùng lặp bản ghi giải quyết những vấn đề khác nhau. Một đầu vào lặp lại không nên tạo thêm yêu cầu mới, trong khi nội dung lặp lại cần một quy tắc nhận diện bản ghi.
  • Một trang trống cần bằng chứng dương tính từ nguồn. Chỉ thiếu bộ chọn (selector) không đủ để khẳng định nguồn không chứa bản ghi nào.
  • Kiểm tra xuất dữ liệu phải mở lại các tệp. So sánh định danh bản ghi trong CSV và JSONL, và đối chiếu các trang hoàn tất, trống và lỗi với hàng đợi.

Thu thập dữ liệu từ nhiều trang biến công việc từ một lần trích xuất thành một quy trình sưu tập. Quy trình cần biết nó được yêu cầu truy cập những gì, đã chấp nhận những trang nào, và các bản ghi được ghi ra đến từ đâu.

Vì vậy, học cách thu thập dữ liệu từ nhiều trang web bắt đầu từ phạm vi và công tác ghi chép. Vòng lặp Python chỉ là cơ chế lấy dữ liệu. Hướng dẫn này xây dựng một hàng đợi URL có giới hạn, kiểm tra từng nguồn, lưu kết quả trang, khử trùng lặp bản ghi và kiểm tra lại các tệp đã xuất.

Bản trình diễn công khai sử dụng Quotes to Scrape thông qua đường dẫn HTTP trực tiếp. Cùng một chương trình cũng bao gồm một nhánh thu thập đã được tài liệu hóa cho Scrapeless Web Unlocker, nhánh này cần khóa tài khoản của bạn và vẫn được gắn nhãn là điều kiện tiên quyết. Phân trang tương tác là một quy trình trình duyệt riêng khi nguồn yêu cầu điều đó.

Pipeline tổng quan

Pipeline chuyển một danh sách URL đã được phê duyệt thành các kết quả trang đã đối chiếu và các tệp dữ liệu đã chấp nhận. Giữ riêng các hiện vật đó để một lỗi không bị ẩn bên trong một tệp xuất trống.

Giai đoạn Thao tác Hiện vật
Phạm vi Xác định URL được phép và các trường bắt buộc Danh sách đầu vào và hợp đồng nguồn
Hàng đợi Chuẩn hóa và khử trùng lặp URL đầu vào Hàng đợi duy nhất có giới hạn
Thu thập Lấy HTML nguồn Ghi nhận danh tính và kết quả phản hồi
Trích xuất Kiểm tra và phân tích từng trang Bản ghi được chấp nhận hoặc lý do lỗi
Khử trùng lặp So sánh danh tính bản ghi Bản ghi duy nhất kèm liên kết nguồn
Xuất Ghi và mở lại CSV và JSONL Các tệp và bản tóm tắt đối chiếu

Giữ hoạt động nguồn và lược đồ ứng dụng tách biệt. Cùng một nguồn có thể tạo ra nhiều bản ghi, không có bản ghi, hoặc một phản hồi không dùng được, nên số trang và số bản ghi cần được đặt tên khác nhau.

Chọn danh sách URL hoặc phân trang từ nguồn

Một danh sách URL đã lưu phù hợp với tác vụ có phạm vi nguồn đã được biết trước. Phân trang phù hợp với tác vụ tìm ra trang được phép tiếp theo từ điều hướng của chính nguồn.

Với danh sách, giữ cả đầu vào gốc và hàng đợi đã chuẩn hóa. Với phân trang, lưu lại trang hiện tại, liên kết hoặc tương tác “tiếp theo” quan sát được, tập đã truy cập và ngân sách trang. Đừng cho rằng một tham số số trang tùy ý sẽ khớp với điều hướng thực tế của trang web.

Bài so sánh quy trình phân trang giải thích các điều kiện tiến và dừng khác nhau. Hướng dẫn này dùng một danh sách hữu hạn để mọi trang được thử đều có thể được đối chiếu trực tiếp với một đầu vào.

Chuẩn hóa URL mà không làm mất ý nghĩa

Chuẩn hóa URL nên loại bỏ những khác biệt không liên quan đến việc thu thập, đồng thời giữ lại các tham số ảnh hưởng đến nguồn. Trong ví dụ này, một bản sao chỉ khác phần fragment bị loại bỏ, trong khi path và query vẫn được giữ nguyên.

Các thành phần URI và việc phân giải tham chiếu phân biệt fragment với path và query. Tránh xóa các tham số query chỉ vì hai URL trông giống nhau; chúng có thể chọn các bản ghi hoặc bộ lọc khác nhau.

Chương trình cũng giới hạn đầu vào vào host trình diễn đã được phê duyệt. Một bộ thu thập thực tế nên sử dụng manifest nguồn của nó thay vì chấp nhận các đích mới được phát hiện một cách tùy tiện.

Điều kiện tiên quyết và cài đặt

Ví dụ cần Python với requests và beautifulsoup4 được cài trong môi trường dự án. Môi trường được kiểm tra sử dụng Requests 2.34.2 và Beautiful Soup 4.15.0; hãy ghi lại phiên bản trong dự án của riêng bạn khi tái hiện.

Chế độ trực tiếp sử dụng các trang trình diễn công khai và không cần thông tin xác thực Scrapeless API. Chế độ unlocker cần SCRAPELESS_API_KEY, quyền truy cập tài khoản vào Web Unlocker và quyền thu thập nguồn đã chọn.
Web Unlocker là sản phẩm thu thập dữ liệu theo định hướng phản hồi. Cấu hình rendering hiện tại của nó sử dụng endpoint yêu cầu v2 và các trường jsRender lồng nhau. Nhánh API yêu cầu HTML, cung cấp dữ liệu cho cùng bộ phân tích chuyên biệt theo nguồn như chế độ trực tiếp.

Hãy rà soát phạm vi nguồn trước khi thực thi. Ví dụ chạy tuần tự trên một danh sách cố định ngắn; nó không phải là một bộ thu thập dữ liệu không giới hạn hoặc một mẫu để tăng khối lượng yêu cầu mà không có quyền.

Chạy Bộ Thu Thập Bị Giới Hạn Hoàn Chỉnh

Bộ thu thập loại bỏ trùng lặp các URL đầu vào, ghi lại kết quả cho mỗi trang được đưa vào hàng đợi và chỉ xuất các bản ghi được chấp nhận. Hợp đồng nguồn của nó khớp với bố cục Quotes to Scrape đã kiểm tra.

Bản demo xuất tên tác giả, thẻ, băm bản ghi và URL nguồn. Nó sử dụng đoạn trích dẫn nội dung nội bộ để xây dựng định danh nội dung nhưng không tái tạo đầy đủ các trích dẫn trong tập dữ liệu xuất.

Lưu ý: Chế độ trực tiếp được thực thi trên các trang demo công khai. Nhánh unlocker yêu cầu khóa API Scrapeless thật và quyền truy cập tài khoản và đã không được thực thi. Các trường yêu cầu của nó đã được kiểm tra so với tài liệu hiện tại; kết quả chế độ trực tiếp không được báo cáo như hiệu năng của Web Unlocker.

python Copy
import csv
import hashlib
import json
import os
from datetime import datetime, timezone
from pathlib import Path
from urllib.parse import urlsplit, urlunsplit
import requests
from bs4 import BeautifulSoup

INPUT = [
    "https://quotes.toscrape.com/page/1/",
    "https://quotes.toscrape.com/page/2/",
    "https://quotes.toscrape.com/page/2/#top",
    "https://quotes.toscrape.com/page/99/",
    "https://quotes.toscrape.com/missing/"
]
MODE = os.environ.get("FETCH_MODE", "direct")
if MODE not in {"direct", "unlocker"}:
    raise ValueError("Unsupported acquisition mode")

def normalize(url):
    parts = urlsplit(url)
    if parts.scheme != "https" or parts.hostname != "quotes.toscrape.com":
        raise ValueError("URL is outside the permitted demo scope")
    return urlunsplit((parts.scheme, parts.netloc.lower(),
                      parts.path or "/", parts.query, ""))

queue = list(dict.fromkeys(normalize(url) for url in INPUT))
pages = []
records = {}
duplicate_records = 0
with requests.Session() as client:
    for url in queue:
        page = {"requested_url": url}
        try:
            if MODE == "unlocker":
                response = client.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": url, "jsRender": {
                              "enabled": True, "response": {"type": "html"}}}},
                    timeout=60
                )
                response.raise_for_status()
                envelope = response.json()
                html = envelope.get("data")
                if envelope.get("code") != 200 or not isinstance(html, str):
                    raise ValueError("Expected a successful HTML envelope")
                page["final_url"] = None
            else:
                response = client.get(url, timeout=30)
                response.raise_for_status()
                html = response.text
                page["final_url"] = response.url
            soup = BeautifulSoup(html, "html.parser")
            heading = soup.select_one("h1 a")
            grids = soup.select("div.container > div.row > div.col-md-8")
            if not heading or heading.get_text(strip=True) != "Quotes to Scrape" or not grids:
                raise ValueError("Source identity does not match the demo contract")
            grid = grids[-1]
            cards = grid.select("div.quote")
            if not cards and (grid.select_one("ul.pager") is None or
                              "No quotes found!" not in grid.get_text(" ", strip=True)):
                raise ValueError("Empty state is not confirmed")
            extracted = []
            for card in cards:
                text_node = card.select_one("span.text")
                author_node = card.select_one("small.author")
                if not text_node or not author_node:
                    raise ValueError("Required source field missing")
                text = text_node.get_text(strip=True)
                author = author_node.get_text(strip=True)
                if not text or not author:
                    raise ValueError("Required source field empty")
                digest = hashlib.sha256((text + "\n" + author).encode()).hexdigest()
                extracted.append({"record_id": digest, "author": author,
                                  "tags": [x.get_text(strip=True) for x in card.select("a.tag")],
                                  "source_urls": [url]})
            for record in extracted:
                digest = record["record_id"]
                if digest in records:
                    duplicate_records += 1
                    records[digest]["source_urls"].append(url)
                else:
                    records[digest] = record
            page.update(status="completed" if cards else "empty", records=len(cards),
                        captured_at=datetime.now(timezone.utc).isoformat())
        except (requests.RequestException, ValueError, KeyError) as error:
            page.update(status="failed", reason=type(error).__name__)
        pages.append(page)

rows = list(records.values())
with Path("records.jsonl").open("w", encoding="utf-8") as output:
    for row in rows:
        output.write(json.dumps(row, ensure_ascii=False) + "\n")
with Path("records.csv").open("w", encoding="utf-8", newline="") as output:
    writer = csv.DictWriter(output, fieldnames=["record_id", "author", "tags", "source_urls"])
    writer.writeheader()
    for row in rows:
        writer.writerow({**row, "tags": json.dumps(row["tags"], ensure_ascii=False),
                         "source_urls": json.dumps(row["source_urls"])})
with Path("records.csv").open(encoding="utf-8", newline="") as source:
    csv_rows = list(csv.DictReader(source))
jsonl_rows = [json.loads(line) for line in Path("records.jsonl").read_text().splitlines()]
assert [r["record_id"] for r in csv_rows] == [r["record_id"] for r in jsonl_rows]
summary = {"mode": MODE, "input_urls": len(INPUT), "duplicate_inputs": len(INPUT)-len(queue),
           "queued_pages": len(queue), "completed": sum(p["status"]=="completed" for p in pages),
           "empty": sum(p["status"]=="empty" for p in pages),
           "failed": sum(p["status"]=="failed" for p in pages),
           "unique_records": len(rows), "duplicate_records": duplicate_records,
           "csv_rows": len(csv_rows), "jsonl_rows": len(jsonl_rows)}
assert summary["completed"] + summary["empty"] + summary["failed"] == len(queue)
Path("pages.json").write_text(json.dumps(pages, indent=2), encoding="utf-8")
Path("summary.json").write_text(json.dumps(summary, indent=2), encoding="utf-8")
print(json.dumps(summary))

Lưu chương trình dưới tên multi_page.py và chạy nó trong thư mục dự án. Khi không có ghi đè chế độ, nó sử dụng thu thập trực tiếp. Chỉ chọn FETCH_MODE=unlocker sau khi đã hoàn tất thông tin xác thực cho nhánh đó và các điều kiện tiên quyết về quyền truy cập nguồn.

Chương trình giữ lại một kết quả trang cho mỗi URL được đưa vào hàng đợi duy nhất. Nó kiểm tra tiêu đề nguồn mong đợi trước khi phân tích các thẻ nội dung, và nó yêu cầu thông báo không có kết quả đã quan sát và vùng điều hướng trước khi chấp nhận một trang rỗng.

Bắt đầu Scraping với Scrapeless

Tăng tốc quy trình web scraping và tự động hóa của bạn với Scrapeless!
Đăng ký hôm nay và nhận $5 tín dụng miễn phí — không cần thẻ tín dụng.

Nhận tín dụng miễn phí ngay trong Scrapeless Dashboard.

Trích Xuất và Xác Thực Mỗi Bản Ghi

Việc xác thực bản ghi nên yêu cầu các trường nhận diện dữ liệu nguồn có ý nghĩa. Ví dụ yêu cầu cả đoạn trích dẫn được dùng để băm và tên tác giả quan sát được trước khi chấp nhận các bản ghi của một trang.

Các selector thuộc về nguồn demo đã kiểm tra: div.quote, span.text, small.author và a.tag. Vùng chứa dữ liệu chính là cột nội dung khớp cuối cùng, tách biệt với cột tiêu đề. Hãy kiểm tra lại các giả định này khi nguồn thay đổi.

Ngữ nghĩa phản hồi HTTP mô tả kết quả giao thức, không phải tính đúng đắn của các trường nguồn này. Một phản hồi thành công vẫn phải thỏa mãn hợp đồng ứng dụng.

Bộ phân tích xây dựng các bản ghi ứng viên của một trang trước khi thêm chúng vào tập kết quả. Một trường bắt buộc bị thiếu sẽ loại bỏ trang đó thay vì âm thầm xuất một phần dữ liệu nhưng coi là hoàn chỉnh.

Theo Dõi Các Trang Hoàn Tất, Thất Bại và Rỗng

Kết quả trang nên giải thích điều gì đã xảy ra với mỗi nguồn được đưa vào hàng đợi. Bản demo phân biệt trang có bản ghi hợp lệ, trang rỗng đã được xác nhận và lỗi HTTP hoặc lỗi hợp đồng nguồn.

Lần chạy bị giới hạn sử dụng năm URL đầu vào. Việc loại bỏ một bản sao chỉ khác phần fragment để lại bốn trang trong hàng đợi. Lần chạy thu thập trực tiếp tạo ra hai trang hoàn tất, một trang rỗng đã xác nhận và một trang thất bại, với 20 bản ghi duy nhất được ghi vào cả hai tệp.

Observation Run result Interpretation
Raw URL inputs 5 Phạm vi tác vụ ban đầu
Duplicate inputs removed 1 Nguồn đã chuẩn hóa bị lặp lại
Unique queued pages 4 Các trang cần có kết quả
Completed pages 2 Hợp đồng nguồn và bản ghi được chấp nhận
Confirmed empty pages 1 Trạng thái không có kết quả của nguồn đã được quan sát
Failed pages 1 Trường hợp đường dẫn cố ý không sẵn dùng
Unique exported records 20 Bản ghi được chấp nhận sau khử trùng lặp nội dung

Các số liệu này mô tả bản demo công khai có giới hạn, không phải kết quả được bảo đảm cho một trang khác hoặc chuẩn hiệu năng cho dịch vụ thu thập được quản lý. Đường dẫn không sẵn dùng được đưa vào để kiểm tra việc đối chiếu kết quả; nó không được gửi lặp lại cho đến khi biến mất khỏi danh sách thất bại.

Khử Trùng Lặp Bản Ghi và Giữ Gốc Gác Nguồn

Việc khử trùng lặp bản ghi so sánh một định danh nội dung đã xác định sau khi trích xuất. Ví dụ băm đoạn trích dẫn và tác giả cùng nhau và giữ lại URL nguồn khi cùng một định danh xuất hiện lần nữa.
Đây là một quy tắc đồng nhất chính xác cho kiểu bản ghi được minh họa. Mã định danh sản phẩm, bản sửa đổi hoặc ngôn ngữ có thể cần một khóa khác. Không sử dụng một băm văn bản dùng chung để gộp các bản ghi mà khác biệt của chúng có ý nghĩa đối với tác vụ.

Giữ tài liệu nguồn cùng với dữ liệu đã được chấp nhận. Loại bỏ trùng lặp phải giữ lại mối quan hệ với các lần thu thập nguồn thay vì xóa bỏ nơi đã quan sát thấy nội dung lặp lại.

Xuất CSV và JSONL, Sau Đó Đối Chiếu Chúng

Xác minh xuất phải đọc lại các hiện vật sau khi tuần tự hóa. Chương trình mở lại CSV và JSONL và so sánh các mã định danh bản ghi theo thứ tự trước khi báo cáo tóm tắt của nó.

Bản minh họa tạo ra 20 hàng CSV và 20 bản ghi JSONL với mã định danh khớp nhau. summary.json giữ lại các số lượng đó, trong khi pages.json lưu các kết quả theo từng trang.

Trích dẫn trường CSV xử lý các chi tiết tuần tự hóa. Tính hợp lệ của định dạng tách biệt với việc chấp nhận nguồn, nên cả hai bước kiểm tra đều cần thiết. Ví dụ này lưu các trường có giá trị dạng danh sách thành chuỗi JSON bên trong ô CSV và dưới dạng mảng trong JSONL.

Các kiểm tra bảo toàn rất đơn giản: số trang hoàn tất cộng trống cộng lỗi bằng với kích thước hàng đợi duy nhất, và các mã định danh đã xuất khớp nhau giữa các tệp. Những kiểm tra này không thể chứng minh tất cả các sự kiện nguồn, nhưng chúng có thể phát hiện các trang bị bỏ sót hoặc hiện vật không nhất quán.

Khi Phân Trang Cần Tương Tác Trình Duyệt

Phân trang tương tác cần một quy trình trình duyệt khi trạng thái tiếp theo của nguồn đòi hỏi một cú nhấp hoặc hành động trang khác. Việc render một tài liệu HTML được trả về không tự động là một phiên nhiều bước bền vững.

Chọn một quy trình Trình Duyệt Agent chuyên dụng cho trường hợp đó, kiểm tra điều khiển tiếp theo thực tế, và chờ các bản ghi mới cần thiết. Giữ cùng ngân sách trang, theo dõi trạng thái đã truy cập và chính sách chấp nhận bản ghi quanh quá trình thu thập bằng trình duyệt.

Không được trộn các đường đi một cách không rõ ràng. Ghi nhận liệu nguồn được lấy thông qua HTTP trực tiếp, phản hồi Web Unlocker, hay một phiên trình duyệt tương tác. Thay đổi phương thức thu thập có thể thay đổi trạng thái trang hoặc phạm vi nội dung.

Xử Lý Phạm Vi Nguồn Một Cách Có Trách Nhiệm

Một tác vụ nhiều trang nên nằm trong danh sách nguồn đã được phê duyệt và chỉ sử dụng dữ liệu cần thiết cho mục đích của nó. Xem lại các điều khoản và quy tắc loại trừ robots trước khi kích hoạt một bộ thu thập rộng hơn.

Giữ ngân sách trên mỗi máy chủ ở mức thận trọng. Ví dụ này là tuần tự; một thử nghiệm sử dụng đồng thời nên ở trong chính sách thu thập được cho phép, chẳng hạn giới hạn ba tác nhân mỗi máy chủ thay vì giả định mức tối đa của dịch vụ.

Giữ lại các kết quả chưa được giải quyết để xem xét. Danh sách lỗi là một phần bằng chứng của công việc đã hoàn tất, không phải một sự phiền toái có thể bỏ qua trong báo cáo cuối cùng.

Kết Luận

Việc scrape nhiều trang web bằng Python cần một hàng đợi có giới hạn, quy tắc chấp nhận phụ thuộc nguồn và đối chiếu tệp. Quy trình thu thập chỉ hoàn tất khi mỗi đầu vào đã xếp hàng có một kết quả và các hiện vật đã ghi khớp với các bản ghi đã được chấp nhận.

Sử dụng thu thập trực tiếp cho các nguồn tĩnh được cho phép phù hợp, nhánh Web Unlocker đã được ghi chép khi tác vụ cần đường đi hướng-tới-phản-hồi của nó, và một quy trình trình duyệt riêng cho phân trang tương tác. Giữ sổ cái và hợp đồng đầu ra ổn định giữa các lựa chọn đó.

Sẵn Sàng Xây Dựng Một Job Thu Thập Đã Đối Chiếu?

Lên kế hoạch một quy trình có giới hạn với Scrapeless và đánh giá yêu cầu thu thập so với bảng giá hiện tại. Thảo luận về hàng đợi và hợp đồng xuất trên Telegram.

Câu Hỏi Thường Gặp

H: Tính công khai có đồng nghĩa với quyền được thu thập nhiều trang không?

Tính công khai không tạo lập quyền cho mọi hình thức thu thập hoặc sử dụng. Xem lại điều khoản nguồn và các yêu cầu áp dụng, và tham vấn cố vấn pháp lý đủ điều kiện khi hoạt động dự định không chắc chắn.

H: Khi nào người thu thập nên dùng danh sách URL thay vì phân trang?

Dùng danh sách URL khi tập nguồn được cho phép đã được biết. Dùng phân trang nguồn khi tác vụ khám phá trang tiếp theo của nó từ một liên kết hoặc tương tác đã kiểm tra.

H: Kết quả selector rỗng có phải là một trang rỗng hợp lệ không?

Kết quả selector rỗng tự nó là chưa được giải quyết. Yêu cầu bằng chứng trạng thái rỗng dương tính từ nguồn và xác nhận danh tính trang trước khi ghi nhận một kết quả rỗng hợp lệ.

H: Một job có thể chứng minh rằng nó đã xử lý mọi URL đầu vào như thế nào?

Giữ lại các đầu vào thô, hàng đợi đã loại trùng, và một kết quả cho mỗi nguồn đã xếp hàng. Đối chiếu các kết quả hoàn tất, trống và lỗi với hàng đợi đó.

H: Nhánh Web Unlocker có cần một proxy được cấu hình riêng không?

Yêu cầu được quản lý được hiển thị sử dụng trường country đã được ghi trong tài liệu. Thông tin xác thực proxy được cấp riêng là cần thiết khi chính client của bạn sử dụng sản phẩm proxy độc lập thay vì vậy.

Hỏi: Điều gì nên xảy ra với tài liệu dạng thử thách hoặc bị từ chối truy cập?

Trình thu thập phải từ chối nội dung nguồn không phù hợp và giữ lại lý do thu thập. Mã trạng thái HTTP thành công không khiến một tài liệu thử thách trở thành một trang dữ liệu được chấp nhận.

Hỏi: Điều gì nên thay đổi khi đánh dấu (markup) nguồn thay đổi luân phiên?

Kiểm tra lại danh tính trang và các trường bắt buộc, sau đó cập nhật các bộ chọn đặc thù cho nguồn và các kiểm tra trạng thái trống. Không được coi đánh dấu thay đổi là bằng chứng rằng nguồn không có bản ghi.

Hỏi: Hướng dẫn nên sử dụng mức độ song song (concurrency) như thế nào?

Trình thu thập được minh họa chạy tuần tự. Một giai đoạn thử nghiệm được cho phép có thể đặt một giới hạn thận trọng cho mỗi host như ba worker, rồi đánh giá hoạt động trước khi mở rộng.

Hỏi: Quy trình này có cần một tác nhân AI không?

Hàng đợi Python, việc trích xuất và các kiểm tra xuất chạy mà không cần tác nhân AI. Một tác nhân có thể tiêu thụ các bản ghi đã được chấp nhận hoặc giám sát một tác vụ xoay quanh các thành phần quyết định này.

Hỏi: URL được yêu cầu nên được lưu thành URL cuối cùng hay URL chuẩn tắc (canonical)?

Lưu URL được yêu cầu tách biệt với danh tính cuối cùng hoặc chuẩn tắc được quan sát. Chế độ trực tiếp ghi lại URL cuối cùng của phản hồi; nhánh API được minh họa để trường đó ở trạng thái không xác định thay vì bịa ra một kết quả chuyển hướng đí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.

Bài viết phổ biến nhất

Danh mục