Quay lại blog

Cách Xây Dựng Một Quy Trình Trích Xuất Web Tăng Dần Với Scrapeless

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

10-Sep-2026

TL;DR:

  • Yêu cầu điều kiện biến một trang không thay đổi thành 304 với một thân 0 byte — phản hồi đầy đủ là 50,388 byte, và mười kiểm tra điều kiện đã chạy trong 4.21 giây so với 5.52 giây cho mười lần lấy đầy đủ.
  • Băm nội dung phát hiện thay đổi nhưng không tiết kiệm băng thông: lần lấy thứ hai của một trang không có trình xác thực vẫn chuyển 11,064 byte trước khi băm có thể được so sánh.
  • Dấu vân tay theo bản ghi là thứ thu nhỏ việc ghi. Một giá chuyển động đã đưa một trang 20 bản ghi xuống chỉ còn 1 dòng được ghi lại.
  • Băm các trường bạn quan tâm thay vì toàn bộ bản ghi, hoặc một trường không liên quan thay đổi sẽ làm mọi thứ trở nên bẩn.
  • Các trình xác thực HTTP mô tả tài liệu mà máy chủ đã gửi, vì vậy chúng trở nên kém hữu ích ngay khi các bản ghi đến thông qua việc tạo nội dung phía client.
  • Một 304 chỉ khả dụng nếu lần chạy trước đã lưu trữ trình xác thực, điều này làm cho bảng trạng thái là một phần của quy trình thay vì một tối ưu hóa.
  • Đặt một crawl gia tăng trên các trang đã được hiển thị với Gói miễn phí Scrapeless.

Hầu hết các trình thu thập thông tin đã lên lịch tải lại mọi thứ, phân tích lại mọi thứ và viết lại mỗi dòng, sau đó báo cáo thành công. Điều đó có hiệu quả cho đến khi danh mục phát triển, tại thời điểm đó công việc hàng ngày tiêu tốn hầu hết thời gian của nó để xác nhận rằng dữ liệu của ngày hôm qua vẫn là dữ liệu của ngày hôm qua.

Gỡ lỗi gia tăng là sắp xếp ngược lại: hỏi điều gì đã thay đổi, và chỉ làm việc khi câu trả lời là có. Câu hỏi có thể được đặt ra ở ba cấp độ, và mỗi cấp tiết kiệm một cái gì đó khác nhau — băng thông, phân tích, hoặc ghi. Mỗi lớp dưới đây đã được đo lường so với cùng một trang danh mục trực tiếp, vì vậy các đánh đổi đến với các con số thay vì tính từ.

Pipeline at a Glance

Lớp Câu hỏi Cơ chế Kết quả đo được
HTTP Tài liệu có thay đổi không? If-None-Match / If-Modified-Since 304, 0 byte so với 50,388
Tài liệu Các byte có thay đổi không? SHA-256 của thân phát hiện, nhưng vẫn chuyển 11,064 byte
Bản ghi Các dòng nào đã thay đổi? dấu vân tay theo trường bản ghi 1 trong 20 dòng được ghi

Luồng là kiểm tra → chỉ lấy nếu thay đổi → trích xuất → so sánh dấu vân tay → chỉ ghi những khác biệt. Các lớp xếp chồng lên nhau: kiểm tra HTTP là rẻ nhất và ít khả dụng nhất, kiểm tra bản ghi luôn khả dụng và tốn một lần lấy đầy đủ.

Kiểm tra ít thường xuyên hơn là nửa kia của cùng một vấn đề. Giao thức loại trừ Robot là nơi một trang web tuyên bố những gì nó muốn được thu thập, và một thiết kế gia tăng là giúp cho trình thu thập thông tin tôn trọng một nhịp độ chậm hơn mà không bị tụt lại phía sau — mỗi lần kiểm tra đều tốn một lượt đi thay vì một lần chuyển đầy đủ.

Layer 1: Để Máy Chủ Trả Lời

Một trình xác thực HTTP là quan điểm riêng của máy chủ về việc liệu đại diện của nó có thay đổi hay không. Có hai loại: ETag, một mã thông báo phiên bản mờ, và Last-Modified, một dấu thời gian. Phản hồi đầu tiên mang chúng.

python Copy
import requests

URL = "https://books.toscrape.com/catalogue/category/books/mystery_3/index.html"
first = requests.get(URL, timeout=30)
first.raise_for_status()
etag = first.headers["ETag"]
print(f"first  GET  {first.status_code}  {len(first.content)} bytes  ETag={etag}")

second = requests.get(URL, headers={"If-None-Match": etag}, timeout=30)
print(f"second GET  {second.status_code}  {len(second.content)} bytes")
print(f"bytes avoided: {len(first.content) - len(second.content)}")
text Copy
first  GET  200  50388 bytes  ETag=W/"63e40de8-c4d4"
second GET  304  0 bytes
bytes avoided: 50388

304 hoàn toàn không có thân. Cơ chế yêu cầu điều kiện được định nghĩa để client giữ bản sao mà nó đã có, điều đó có nghĩa là trình thu thập thông tin phải đã giữ một bản.

Last-Modified hoạt động theo cách tương tự thông qua một tiêu đề khác:

python Copy
third = requests.get(URL, headers={"If-Modified-Since": first.headers["Last-Modified"]}, timeout=30)
print(first.headers["Last-Modified"], "->", third.status_code, len(third.content), "bytes")
text Copy
Wed, 08 Feb 2023 21:02:32 GMT -> 304 0 bytes

Ưu tiên ETag khi cả hai đều có mặt. Đặc tả ngữ nghĩa HTTP làm Last-Modified thành một dấu thời gian có độ phân giải một giây, vì vậy hai thay đổi trong cùng một giây là không thể phân biệt, trong khi một tag thực thể có thể thay đổi trong bất kỳ lần chỉnh sửa nào.

Tiết kiệm là có thật nhưng không phải là toàn bộ quá trình:

text Copy
10 conditional GETs   4.21s
10 full GETs          5.52s

Kiểm tra điều kiện chạy nhanh hơn 1.31 lần và đã để lại 492 KB không được chuyển. Yêu cầu vẫn tốn một lượt đi — cái biến mất là thân, không phải kết nối.

Layer 2: Băm Tài Liệu Khi Máy Chủ Nói Không Gì

Nhiều mục tiêu không gửi trình xác thực nào. Do đó, cách duy nhất để biết liệu tài liệu đã thay đổi hay chưa là lấy nó và nhìn vào. Một hàm băm mật mã là công cụ tiêu chuẩn cho việc so sánh đó — tiêu chuẩn SHA-256 cung cấp một giá trị cố định, nơi bất kỳ sự khác biệt nào chỉ 1 byte đều tạo ra một băm không liên quan, vì vậy sự bình đẳng là một tín hiệu đáng tin cậy "không có gì bị di chuyển".

python Copy
import hashlib
import requests

q1 = requests.get("https://quotes.toscrape.com/", timeout=30)
q1.raise_for_status()
print("ETag:", q1.headers.get("ETag"), " Last-Modified:", q1.headers.get("Last-Modified"))

q2 = requests.get("https://quotes.toscrape.com/", timeout=30)
h1 = hashlib.sha256(q1.content).hexdigest()
h2 = hashlib.sha256(q2.content).hexdigest()
print(f"sha256 run 1: {h1[:16]}...")
print(f"sha256 run 2: {h2[:16]}...")
print(f"unchanged: {h1 == h2}   bytes still transferred: {len(q2.content)}")
text Copy
ETag: None  Last-Modified: None
sha256 run 1: efdc2605a2062dce...
sha256 run 2: efdc2605a2062dce...
unchanged: True   bytes still transferred: 11064

Lưu ý những gì lớp này làm và không làm. Hàm băm báo cáo chính xác không có thay đổi, và 11,064 byte đã vượt qua mạng. Băm tài liệu tiết kiệm phân tích, ghi cơ sở dữ liệu, cảnh báo phía dưới và bất kỳ việc nhúng lại nào — không bao giờ tiết kiệm băng thông.
Nó cũng gặp vấn đề về xác suất sai với các số ở đây không hiển thị. Các trang mang theo một mã phiên, một quảng cáo xoay vòng hoặc một dấu thời gian đã được kết xuất tạo ra một băm khác nhau trong mỗi lần lấy dữ liệu trong khi dữ liệu là giống nhau. Băm các bản ghi đã trích xuất thay vì thân dữ liệu thô là điều làm cho tín hiệu ổn định, đó là lớp tiếp theo.

Lớp 3: Lấy Dấu Vân Tay Của Các Bản Ghi

Các lớp trên trả lời các câu hỏi về một tài liệu. Những gì một đường ống thường cần biết là hàng nào sẽ được ghi.

python Copy
import json, hashlib

def fingerprint(record):
    payload = json.dumps({k: record[k] for k in ("price", "rating")}, sort_keys=True)
    return hashlib.sha256(payload.encode()).hexdigest()[:16]

Việc lấy dấu vân tay của một tập hợp chọn lọc các trường thay vì toàn bộ bản ghi là quyết định làm cho điều này hoạt động. Bao gồm một trường tự thay đổi — số lượng lượt xem, một dấu thời gian "đã thấy gần đây", một vị trí trong danh sách xếp hạng — và mỗi bản ghi trông sẽ bẩn trong mỗi lần chạy.

Lưu một dấu vân tay cho mỗi bản ghi, sau đó so sánh lần thu thập tiếp theo với nó:

python Copy
known = {title: (fp, price) for title, fp, price in conn.execute("SELECT title, fp, price FROM snap")}
new, changed, same = [], [], 0
for record in second_pass:
    previous = known.get(record["title"])
    if previous is None:
        new.append(record)
    elif previous[0] != fingerprint(record):
        changed.append((record["title"], previous[1], record["price"]))
    else:
        same += 1

Chống lại trang 20 bản ghi trực tiếp với một giá thay đổi để đại diện cho một sự di chuyển thực tế:

text Copy
parsed 20 records from the live page
stored baseline: 20 fingerprints
example fingerprint: 'Sharp Objects' -> e974692e9d935048

unchanged 19 | changed 1 | new 0
  CHANGED A Murder in Time                     £16.64 -> £99.99

rows written downstream: 1 of 20

Một hàng được ghi thay vì hai mươi. Trên một danh mục mà thực tế hàng ngày là hầu như không có gì di chuyển, tỷ lệ đó là toàn bộ lập luận cho việc lấy dấu vân tay: khối lượng ghi chú theo dõi tỷ lệ thay đổi thay vì kích thước danh mục.

Giữ giá trị trước đó cùng với dấu vân tay là điều biến việc phát hiện thành một sự kiện có thể sử dụng. £16.64 -> £99.99 là một bản ghi thay đổi giá; một cờ bẩn chỉ là một gợi ý rằng điều gì đó đã xảy ra.

Chạy một lượt thu thập gia tăng chống lại các trang render phía khách hàng? Kế hoạch miễn phí Scrapeless bao phủ đủ yêu cầu để xây dựng cơ sở cơ bản và một vài sự khác biệt đầu tiên.

Nơi Lớp HTTP Ngừng Áp Dụng

Một bộ xác thực mô tả tài liệu mà máy chủ đã gửi. Khi các bản ghi đến qua việc render phía khách hàng, tài liệu đó là vỏ ứng dụng, và ETag của nó theo dõi việc triển khai của vỏ thay vì danh mục.

Hệ quả là cụ thể: một trang có thể trả lại 304 trong khi giá cả phía sau đã di chuyển, vì vỏ thực sự không thay đổi. Bất kỳ mục tiêu nào mà nội dung được lắp ráp trong trình duyệt đều phải được kiểm tra ở lớp bản ghi, sử dụng Universal Scraping API để render trước khi so sánh.

Điều tương tự cũng áp dụng cho một điểm cuối JSON nội bộ mà trang gọi. Những cái đó thường gửi bộ xác thực, và khi chúng làm vậy, lớp trên lại hoạt động chống lại payload thực sự mang các bản ghi.

Lưu Trữ Trạng Thái

Không có gì trong số này hoạt động nếu không có nơi nào để giữ những gì lần chạy cuối cùng đã học được. Trạng thái mà một đường ống cần là nhỏ:

Cột Mục đích
url những gì đã được kiểm tra
etag / last_modified phát lại như là tiêu đề có điều kiện
body_sha256 so sánh cấp độ tài liệu khi không có bộ xác thực
checked_at khi câu trả lời được xác nhận lần cuối

Mỗi bản ghi, bảng lưu giữ khóa, dấu vân tay, và bất kỳ giá trị trước đó nào mà bạn muốn báo cáo. Cả hai đều phù hợp với dữ liệu đã thu thập trong cùng một cơ sở dữ liệu, và hình dạng ETL pipeline không thay đổi — một bước kiểm tra được thêm vào trước khi lấy.

Một lưu ý hoạt động dễ bị bỏ qua: một ETag chỉ có giá trị cho URL đã phát hành nó. Phát lại một thẻ được lưu trữ chống lại một chuỗi truy vấn khác hoặc một biến thể phân trang sẽ tạo ra một 200 và một thân đầy đủ, điều này là hành vi đúng đắn chứ không phải là một lỗi.

Kết Luận

Lấy dữ liệu gia tăng là ba câu hỏi, và biết câu hỏi nào bạn đang hỏi quyết định những gì bạn lưu. Bộ xác thực HTTP lưu trữ thân — 50,388 byte trở thành một 304 bằng 0 byte. Băm tài liệu lưu trữ việc phân tích và ghi chú nhưng không bao giờ băng thông, vì 11,064 byte đến trước khi so sánh. Dấu vân tay bản ghi lưu trữ việc ghi, và đưa một trang 20 bản ghi xuống còn một hàng.

Bắt đầu với bộ xác thực khi máy chủ cung cấp một cái, quay lại với việc băm các bản ghi đã trích xuất chứ không phải thân dữ liệu thô, và lấy dấu vân tay chỉ các trường mà bạn thực sự quan tâm đến việc di chuyển. Giá cả liệt kê những gì các lần lấy còn lại có giá sau khi những lần không thay đổi ngừng xảy ra.

Sẵn sàng ngừng lấy lại các trang không di chuyển? Bắt đầu với kế hoạch miễn phí Scrapeless và xây dựng cơ sở cơ bản mà lần chạy tiếp theo của bạn so sánh chống lại.

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

Q: Web scraping gia tăng là gì?

Web scraping chỉ lấy những gì đã thay đổi kể từ lần chạy trước, thay vì thu thập lại toàn bộ mục tiêu. Nó được thực hiện như một bước kiểm tra trước khi lấy dữ liệu hoặc trước khi ghi: một yêu cầu HTTP có điều kiện, so sánh hàm băm tài liệu, hoặc so sánh dấu vân tay theo bản ghi. Hiệu ứng đo được ở đây là 50.388 byte đã được tiết kiệm ở lớp HTTP và 19 trong 20 hàng đã bị bỏ qua ở lớp bản ghi.

Q: Tôi nên sử dụng ETag trong trình thu thập dữ liệu như thế nào?

Lưu tiêu đề ETag từ phản hồi, sau đó gửi lại nó dưới dạng If-None-Match trong yêu cầu tiếp theo cho cùng một URL đó. Một máy chủ đồng ý rằng không có gì thay đổi sẽ trả lời 304 với một thân rỗng, đây là tín hiệu để bỏ qua phần còn lại của quy trình. Thẻ này liên kết với URL chính xác, vì vậy một thẻ đã lưu nếu được phát lại với một chuỗi truy vấn khác sẽ trả về một 200 bình thường.

Q: Nếu một trang không gửi ETag hoặc Last-Modified thì sao?

Thay vào đó, hãy lấy và so sánh các hàm băm. Băm các bản ghi đã trích xuất thay vì HTML thô — một hàm băm thân thô sẽ thay đổi khi một mã thông báo phiên, quảng cáo hoặc dấu thời gian được render thay đổi, điều này đánh dấu trang là "bẩn" trong khi dữ liệu là giống nhau. Việc này tốn băng thông dù theo cách nào; tiết kiệm nằm ở việc phân tích cú pháp, ghi và bất kỳ thứ gì tiếp theo.

Q: Tôi nên băm toàn bộ bản ghi hay các trường cụ thể?

Các trường cụ thể. Một hàm băm toàn bộ bản ghi bao gồm bất cứ thứ gì mà trang web mang, vì vậy một vị trí xếp hạng hoặc bộ đếm "lần cuối xem" khiến mỗi bản ghi trông như đã thay đổi trong mỗi lần chạy. Việc chỉ băm các trường mà sự chuyển động là quan trọng là điều đã tạo ra kết quả ổn định 19 không thay đổi ở trên.

Q: Liệu một trang có thể trả về 304 trong khi dữ liệu của nó thực sự đã thay đổi không?

Có, trên các trang được render bởi khách hàng. Bộ xác thực mô tả tài liệu HTML mà máy chủ đã gửi, mà đối với một ứng dụng một trang là vỏ bọc chứ không phải các bản ghi, vì vậy thẻ theo dõi các triển khai của vỏ bọc. Những mục tiêu này cần phải so sánh ở lớp bản ghi sau khi render, hoặc so với điểm cuối JSON nội bộ mang dữ liệu.

Q: Web scraping gia tăng thực sự tiết kiệm được bao nhiêu?

Nó phụ thuộc vào lớp nào trả lời. Trong phép đo ở trên, các yêu cầu có điều kiện đã loại bỏ hoàn toàn thân phản hồi và chạy nhanh hơn 1,31 lần trong mười lần kiểm tra, và lớp bản ghi đã cắt giảm việc ghi dữ liệu tới 95% trên một trang nơi một trong hai mươi mục đã chuyển động. Chuyến đi vòng đi vẫn tồn tại trong mọi trường hợp, vì vậy việc tiết kiệm tỷ lệ với kích thước trang và tỷ lệ thay đổi chứ không phải với số lượng yêu cầu.

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