
Anh Tuan
Data Science Expert
Đã xuất bản Oct 29, 2026
Đã cập nhật Oct 29, 2026 · đọc tối thiểu

Hai tác nhân trình duyệt gặp CAPTCHA được hỗ trợ trong hai tác vụ riêng biệt, đã được ủy quyền. Tác nhân A bắt đầu trước, nhưng tác nhân B lại nhận được kết quả trước. Nếu ứng dụng chỉ đơn giản gán kết quả tiếp theo cho tab đang chờ đầu tiên, cả hai công việc đều có thể bị ảnh hưởng dù mỗi yêu cầu tới solver đều hợp lệ.
Đây là một vấn đề tương quan tác vụ. Thử lại nhiều lần sẽ không sửa được một kết quả đã được giao tới sai trang. Ứng dụng cần ghi nhớ hạng mục công việc trình duyệt nào đã tạo mỗi tác vụ solver và liệu hạng mục đó còn “hiện hành” khi phản hồi đến hay không.
CapSolver trả về các định danh tác vụ cho công việc API bất đồng bộ. Hướng dẫn này giải thích cách bảo toàn mối liên kết đó giữa các tác nhân chạy song song, với một ví dụ nhỏ chạy cục bộ mà bạn có thể dùng trước khi kết nối solver thật. Bài không đưa ra chỉ số benchmark về song song hay tỉ lệ thành công CAPTCHA trong môi trường sản xuất.
Một tác nhân trình duyệt nên giữ lại job của ứng dụng, chủ sở hữu trang, và ID tác vụ solver gắn với một lần thử.
API createTask trả về taskId cho một tác vụ bất đồng bộ. Hãy lưu lại khi phản hồi tạo tác vụ được chấp nhận. API getTaskResult nhận định danh đó để truy xuất kết quả tương ứng.
Ứng dụng của bạn cũng cần định danh hạng mục công việc riêng và một tham chiếu tới chủ sở hữu trình duyệt. Đây là các trường thuộc về ứng dụng, không phải tham số bổ sung gửi lên CapSolver. Một nhãn trang như page-a trong ví dụ dùng để nhận diện worker sở hữu trang; nó không phải handle trình duyệt có thể tái sử dụng hay thông tin xác thực API.
Thêm một phiên bản nhỏ cho lần thử, được gọi là epoch bên dưới. Tăng nó lên khi có điều hướng mới hoặc lần thử thử thách mới khiến kết quả đang chờ trước đó không còn phù hợp. Chỉ URL là không đủ: hai job có thể truy cập cùng một URL, và một trang có thể tải trạng thái khác nhau mà không đổi địa chỉ.
Tài liệu về browser-context của Playwright giải thích về trạng thái trình duyệt độc lập. Cô lập context và tương quan tác vụ giải quyết hai vấn đề khác nhau. Cookie tách biệt không tự động định tuyến kết quả solver tới đúng worker.
Thứ tự hoàn thành mô tả thời điểm kết quả đến, chứ không phải job trình duyệt nào sở hữu chúng.
Tài liệu asyncio.as_completed của Python mô tả cách xử lý các awaitable khi chúng hoàn thành. Nếu cách điều phối của bạn dùng callback theo thứ tự hoàn thành, mỗi kết quả phải mang theo liên kết riêng thay vì dựa vào vị trí trong danh sách các trang đang chờ.
Hãy coi việc tạo tác vụ và gắn kết nó là một bước bàn giao cục bộ: xác thực phản hồi tạo tác vụ, lưu ID trả về cùng với hạng mục công việc, rồi mới cho phép truy vấn kết quả. Một triển khai dựa trên callback cần một kế hoạch tương đương cho các kết quả đến trước khi liên kết cục bộ của nó được hiển thị. Đừng bỏ qua race đó như một “trang không rõ” và lập tức tạo thêm một tác vụ trả phí khác.
Giao diện hàng đợi của Python có thể giúp chuyển một hạng mục công việc hoàn chỉnh giữa các worker cục bộ. Hàng đợi không thay thế cho bảng ánh xạ: hãy mang định danh đi cùng kết quả cho tới khi tới được chủ sở hữu trang.
Chấp nhận kết quả để giao đến chỉ khi ID tác vụ được biết đến và lần thử đã ghi nhận vẫn thuộc về trang đang hoạt động.
Dùng một chủ sở hữu duy nhất để cập nhật trạng thái này trong ứng dụng nhỏ. Trong dịch vụ phân tán, hãy dùng lưu trữ bền vững và một bước claim nguyên tử hoặc kiểm soát đồng thời tương đương. Một dictionary Python được chia sẻ một cách “tùy tiện” giữa các tiến trình không thể đảm bảo điều đó.
Ví dụ dưới đây là một fixture định tuyến cục bộ, không phải phương thức SDK chính thức hay tích hợp solver hoàn chỉnh. Nó sử dụng các ID tác vụ được bịa ra và một fixture_marker, không phải token CAPTCHA hay trường giải pháp CapSolver. Chạy nó với Python 3; không cần gói bên thứ ba, khóa API, trình duyệt, hay request mạng.
def accept_result(reply, pending, current_epochs):
task_id = reply.get('taskId')
if not isinstance(task_id, str) or type(reply.get('errorId')) is not int:
return 'malformed_reply', None
job = pending.get(task_id)
if job is None:
return 'unknown_or_duplicate', None
if current_epochs.get(job['page_id']) != job['epoch']:
pending.pop(task_id)
return 'stale_page', None
if reply.get('errorId', 0) != 0:
pending.pop(task_id)
return 'solver_error', None
if reply.get('status') != 'ready':
return 'pending', None
if not reply.get('solution'):
pending.pop(task_id)
return 'missing_solution', None
pending.pop(task_id)
return 'ready_for_owner', (job['page_id'], reply['solution'])
pending = {
'fixture-task-a': {'page_id': 'page-a', 'epoch': 1},
'fixture-task-b': {'page_id': 'page-b', 'epoch': 1},
}
epochs = {'page-a': 1, 'page-b': 1}
for task_id in ['fixture-task-b', 'fixture-task-a']:
reply = {'taskId': task_id, 'errorId': 0, 'status': 'ready',
'solution': {'fixture_marker': task_id}}
state, target = accept_result(reply, pending, epochs)
print(task_id, state, target[0] if target else None)
Ví dụ in ra hai dòng sau:
fixture-task-b ready_for_owner page-b
fixture-task-a ready_for_owner page-a
Tác vụ B hoàn thành trước và vẫn được trả về cho trang B. Hàm cố ý bàn giao kết quả cho chủ sở hữu mà không điền hay submit vào trang. Chỉ thay thế fixture sau khi bạn đã có bộ phân tích kết quả theo từng loại tác vụ được ghi chép rõ, và thao tác trình duyệt được hỗ trợ.
Với một worker kiểu polling, hãy giữ lại ID tác vụ dùng trong request như một phần của hạng mục công việc cục bộ. Nếu phản hồi có kèm ID tác vụ, hãy xác minh rằng nó trùng khớp; đừng dùng một ID phản hồi không tin cậy hoặc không khớp để gán nhãn lại request. Fixture giả định rằng liên kết này đã được xác thực trước khi accept_result được gọi.
Nhận mã thưởng CapSolver của bạn
Tăng ngân sách automation ngay lập tức!
Dùng mã thưởng CAP26 khi nạp tiền vào tài khoản CapSolver để nhận thêm 5% bonus cho mỗi lần nạp — không giới hạn.
Đổi mã ngay trong Bảng điều khiển CapSolver
Kết quả đến muộn hoặc lặp lại nên tạo ra trạng thái rõ ràng thay vì được áp dụng cho tab đang hoạt động bất kỳ.
Đánh dấu lần thử cũ là stale khi trang đóng, điều hướng, hoặc bắt đầu một thử thách thay thế. Fixture so sánh epoch lưu trữ với current_epochs; việc xóa một trang đã đóng khỏi bảng cũng làm phép kiểm tra đó thất bại. Đừng chuyển một kết quả cũ sang lần thử mới chỉ vì hostname giống nhau.
Chủ sở hữu trang nên kiểm tra lại lần thử ngay trước khi dùng kết quả đã được giao. Kiểm tra của fixture và hành động trình duyệt sau đó là hai thao tác riêng. Giữ việc điều hướng trang và áp dụng kết quả dưới cùng một chủ sở hữu giúp ngăn worker khác thay đổi trang trong khoảng giữa.
Giữ liên kết tác vụ hiện tại khi solver báo trạng thái chưa kết thúc. Hãy làm theo hướng dẫn polling của tài liệu tác vụ hiện hành và deadline job của bạn. Tạo tác vụ thay thế mỗi khi kết quả chưa sẵn sàng có thể làm tăng số công việc đang chờ mà không giải quyết được yêu cầu ban đầu.
Ghi nhận lỗi vào hạng mục công việc tương ứng. Fixture tách lỗi solver, phong bì (envelope) sai định dạng, và thiếu solution. Parser trong môi trường production phải bổ sung kiểm tra chính xác các trường solution cho loại tác vụ đã chọn; một dict không rỗng là chưa đủ để chứng minh token dùng được.
Chỉ claim việc giao một lần. Fixture cục bộ xóa liên kết đã ở trạng thái ready, nên lần lặp lại sẽ bị phân loại là không rõ hoặc trùng lặp. Các worker trong môi trường production cần bản ghi kết thúc bền vững và chính sách xác nhận nếu việc giao hoặc thực thi trên trình duyệt có thể thất bại. Đừng dùng ví dụ trong bộ nhớ này như một hàng đợi phân tán “chính xác-một-lần”.
Hãy xác minh quyền sở hữu và hành vi từ chối đúng đắn trước khi rút kết luận về thông lượng.
Các kiểm tra cục bộ đã thử: thứ tự hoàn thành đảo ngược, một tác vụ đang chạy, ID không rõ, lần thử thay đổi, trang đóng, phản hồi lỗi, solution rỗng, phong bì sai định dạng, và giao trùng lặp. Những kiểm tra này đã thành công với hàm được công bố. Chúng không kiểm thử việc solve CAPTCHA thật, điền lại vào trình duyệt, hay ứng dụng chấp nhận.
Với một bài test end-to-end đã được ủy quyền, hãy thêm các lệnh gọi tạo và lấy kết quả tác vụ thật, giữ kết quả nhạy cảm trong worker trình duyệt, và xác nhận kết quả ứng dụng dự kiến sau bước solve đã được ghi chép. Nếu trang vẫn hiển thị thử thách hoặc bản ghi mong đợi không xuất hiện, hãy ghi lại kết quả đó riêng biệt với trạng thái sẵn sàng của solver.
Giữ log ở dạng hữu ích mà không sao chép token, cookie, hay khóa API thô. Lưu ID hạng mục công việc, ID tác vụ, tên giai đoạn, và thông tin lỗi đã được khử nhạy cảm. Hướng dẫn timeout API hiện có nói về hành vi chờ; bài viết này tập trung vào job nào nhận được kết quả cuối cùng. Bảng thuật ngữ về đồng thời cung cấp bối cảnh về công việc đồng thời mà không ngụ ý một cam kết hiệu năng.
Giữ mỗi lần solve được hỗ trợ gắn với hạng mục công việc đã yêu cầu nó. CapSolver cung cấp kết quả solver; ứng dụng của bạn định tuyến kết quả đó, kiểm tra liệu lần thử còn hiệu lực, và xác minh tác vụ trình duyệt. Sự tách biệt đó cho phép các tác nhân song song vẫn độc lập khi kết quả đến lệch thứ tự.
Hỏi: Hai tác nhân trình duyệt có thể dùng chung một biến “tác vụ đang chờ” không?
Một biến có thể thay đổi duy nhất là không an toàn nếu công việc về sau ghi đè liên kết trước đó. Hãy lưu một liên kết riêng cho từng tác vụ solver đang hoạt động và chủ sở hữu trang của nó.
Hỏi: URL trang có đủ để nhận diện điểm đích không?
Không. Các tab khác nhau có thể dùng chung một URL, và một trang có thể đổi trạng thái tại cùng một địa chỉ. Hãy giữ định danh hạng mục công việc và phiên bản lần thử hiện tại.
Hỏi: Tôi có thể tái sử dụng một kết quả “ready” sau khi trang đã điều hướng không?
Đừng cho rằng nó vẫn còn áp dụng được. Hãy coi lần thử cũ là stale và kiểm tra trang mới trước khi quyết định về bất kỳ lần solve được phép nào tiếp theo.
Hỏi: Ví dụ này có solve hay submit CAPTCHA thật không?
Không. Nó chỉ kiểm thử việc định tuyến cục bộ bằng các định danh bịa ra và kết quả “trơ”. Solve trả phí và ứng dụng chấp nhận cần các bài kiểm thử tích hợp riêng.
Hỏi: Ví dụ dictionary này có an toàn giữa các worker phân tán không?
Không. Nó giả định một chủ sở hữu duy nhất trong một process. Thực thi phân tán cần trạng thái tác vụ bền vững, các bước claim giao nguyên tử, và một chính sách xử lý lỗi.

Anh Tuan
Data Science Expert
Turning task outcomes into actionable insights.
GIỚI THIỆU TÁC GIẢ
Đọc đúng kết quả từ công cụ CAPTCHA: phân biệt lỗi truyền tải, tác vụ đang chờ xử lý, kết quả từ bộ giải và việc trình duyệt đã thành công trước khi cho phép một tác nhân AI tiếp tục.

Hãy chọn một API CAPTCHA hoặc MCP cho tác nhân AI của bạn bằng cách so sánh khả năng kiểm soát tác vụ, khám phá công cụ, xử lý kết quả và trách nhiệm của trình duyệt trước khi bạn tích hợp.
