Cách giải Captcha trong Browser4 với tích hợp CapSolver

Anh Tuan
Data Science Expert
21-Jan-2026

Đối với tự động hóa web, Browser4 (từ PulsarRPA) đã trở thành động cơ trình duyệt nhanh như chớp, an toàn với coroutine, được thiết kế dành riêng cho trích xuất dữ liệu được hỗ trợ bởi AI. Với khả năng hỗ trợ 100k-200k truy cập trang phức tạp mỗi máy mỗi ngày, Browser4 được xây dựng để mở rộng quy mô. Tuy nhiên, khi trích xuất dữ liệu từ các trang web được bảo vệ, các thách thức CAPTCHA trở thành rào cản quan trọng.
CapSolver cung cấp sự kết hợp hoàn hảo với khả năng tự động hóa của Browser4, cho phép các đại diện của bạn dễ dàng vượt qua các trang web bị bảo vệ bằng CAPTCHA. Sự tích hợp này kết hợp khả năng tự động hóa trình duyệt tốc độ cao của Browser4 với giải pháp CAPTCHA hàng đầu ngành.
Browser4 là gì?
Browser4 là khung phần mềm tự động hóa trình duyệt hiệu năng cao được xây dựng bằng Kotlin. Nó được thiết kế dành riêng cho các ứng dụng AI yêu cầu khả năng tự động hóa đại diện, tốc độ xử lý cực cao và trích xuất dữ liệu kết hợp giữa LLM, thuật toán học máy và phương pháp dựa trên bộ chọn.
Tính năng chính của Browser4
- Tốc độ cực cao: 100k-200k truy cập trang phức tạp mỗi máy mỗi ngày
- An toàn với coroutine: Được xây dựng bằng Kotlin coroutines để xử lý song song hiệu quả
- Đại diện được hỗ trợ bởi AI: Các đại diện trình duyệt tự động có khả năng suy luận và thực hiện các nhiệm vụ nhiều bước
- Trích xuất kết hợp: Kết hợp trí tuệ LLM, thuật toán học máy và bộ chọn CSS/XPath
- Truy vấn X-SQL: Ngôn ngữ SQL mở rộng cho trích xuất dữ liệu phức tạp
- Tính năng chống bot: Xoay profile, hỗ trợ proxy và lịch trình bền bỉ
Các phương thức API chính
| Phương thức | Mô tả |
|---|---|
session.open(url) |
Tải trang và trả về một PageSnapshot |
session.parse(page) |
Chuyển đổi snapshot thành tài liệu trong bộ nhớ |
driver.selectFirstTextOrNull(selector) |
Lấy văn bản từ DOM đang chạy |
driver.evaluate(script) |
Thực thi JavaScript trong trình duyệt |
session.extract(document, fieldMap) |
Ánh xạ các bộ chọn CSS thành các trường có cấu trúc |
CapSolver là gì?
CapSolver là dịch vụ giải CAPTCHA hàng đầu cung cấp các giải pháp dựa trên AI để vượt qua các thách thức CAPTCHA khác nhau. Với hỗ trợ cho nhiều loại CAPTCHA và thời gian phản hồi nhanh như chớp, CapSolver tích hợp dễ dàng vào các quy trình tự động hóa.
Các loại CAPTCHA được hỗ trợ
- reCAPTCHA v2 (Hình ảnh & Không hiển thị)
- reCAPTCHA v3
- Cloudflare Turnstile
- Cloudflare Challenge (5s)
- AWS WAF
- Và nhiều loại khác...
Tại sao nên tích hợp CapSolver với Browser4?
Khi xây dựng tự động hóa Browser4 tương tác với các trang web được bảo vệ—dù là để trích xuất dữ liệu, theo dõi giá cả hay nghiên cứu thị trường—các thách thức CAPTCHA trở thành rào cản quan trọng. Dưới đây là lý do tại sao sự tích hợp này quan trọng:
- Trích xuất tốc độ cao liên tục: Duy trì hơn 100k truy cập trang mỗi ngày mà không bị chặn bởi CAPTCHA
- Vận hành mở rộng quy mô: Xử lý CAPTCHA trên các phiên bản thực thi coroutine song song
- Quy trình làm việc liền mạch: Giải CAPTCHA như một phần trong luồng trích xuất của bạn
- Hiệu quả về chi phí: Chỉ trả tiền cho các CAPTCHA được giải thành công
- Tỷ lệ thành công cao: Độ chính xác hàng đầu ngành cho tất cả các loại CAPTCHA được hỗ trợ
Cài đặt
Yêu cầu
- Java 17 hoặc cao hơn
- Maven 3.6+ hoặc Gradle
- Một khóa API CapSolver

Thêm phụ thuộc
Maven (pom.xml):
xml
<dependencies>
<!-- Browser4/PulsarRPA -->
<dependency>
<groupId>ai.platon.pulsar</groupId>
<artifactId>pulsar-boot</artifactId>
<version>2.2.0</version>
</dependency>
<!-- Client HTTP cho CapSolver -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- Phân tích JSON -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<!-- Coroutines Kotlin -->
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
Gradle (build.gradle.kts):
kotlin
dependencies {
implementation("ai.platon.pulsar:pulsar-boot:2.2.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.google.code.gson:gson:2.10.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
}
Cài đặt môi trường
Tạo một tệp application.properties:
properties
# Cấu hình CapSolver
CAPSOLVER_API_KEY=khóa_api_capsolver_của_bạn
# Cấu hình LLM (tùy chọn, cho trích xuất AI)
OPENROUTER_API_KEY=khóa_api_openrouter_của_bạn
# Cấu hình proxy (tùy chọn)
PROXY_ROTATION_URL=địa chỉ_proxy_của_bạn
Tạo dịch vụ CapSolver cho Browser4
Dưới đây là một dịch vụ Kotlin có thể tái sử dụng tích hợp CapSolver với Browser4:
Dịch vụ CapSolver cơ bản
kotlin
import com.google.gson.Gson
import com.google.gson.JsonObject
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import kotlinx.coroutines.delay
import java.util.concurrent.TimeUnit
data class TaskResult(
val gRecaptchaResponse: String? = null,
val token: String? = null,
val cookies: List<Map<String, String>>? = null,
val userAgent: String? = null
)
class CapSolverService(private val apiKey: String) {
private val client = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
private val gson = Gson()
private val baseUrl = "https://api.capsolver.com"
private val jsonMediaType = "application/json".toMediaType()
private suspend fun createTask(taskData: Map<String, Any>): String {
val payload = mapOf(
"clientKey" to apiKey,
"task" to taskData
)
val request = Request.Builder()
.url("$baseUrl/createTask")
.post(gson.toJson(payload).toRequestBody(jsonMediaType))
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
if (result.get("errorId").asInt != 0) {
throw Exception("Lỗi CapSolver: ${result.get("errorDescription").asString}")
}
return result.get("taskId").asString
}
private suspend fun getTaskResult(taskId: String, maxAttempts: Int = 60): TaskResult {
val payload = mapOf(
"clientKey" to apiKey,
"taskId" to taskId
)
repeat(maxAttempts) {
delay(2000)
val request = Request.Builder()
.url("$baseUrl/getTaskResult")
.post(gson.toJson(payload).toRequestBody(jsonMediaType))
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
when (result.get("status")?.asString) {
"ready" -> {
val solution = result.getAsJsonObject("solution")
return TaskResult(
gRecaptchaResponse = solution.get("gRecaptchaResponse")?.asString,
token = solution.get("token")?.asString,
userAgent = solution.get("userAgent")?.asString
)
}
"failed" -> throw Exception("Nhiệm vụ thất bại: ${result.get("errorDescription")?.asString}")
}
}
throw Exception("Hết thời gian chờ đợi giải pháp CAPTCHA")
}
suspend fun solveReCaptchaV2(websiteUrl: String, websiteKey: String): String {
val taskId = createTask(mapOf(
"type" to "ReCaptchaV2TaskProxyLess",
"websiteURL" to websiteUrl,
"websiteKey" to websiteKey
))
val result = getTaskResult(taskId)
return result.gRecaptchaResponse ?: throw Exception("Không có gRecaptchaResponse trong giải pháp")
}
suspend fun solveReCaptchaV3(
websiteUrl: String,
websiteKey: String,
pageAction: String = "submit"
): String {
val taskId = createTask(mapOf(
"type" to "ReCaptchaV3TaskProxyLess",
"websiteURL" to websiteUrl,
"websiteKey" to websiteKey,
"pageAction" to pageAction
))
val result = getTaskResult(taskId)
return result.gRecaptchaResponse ?: throw Exception("Không có gRecaptchaResponse trong giải pháp")
}
suspend fun solveTurnstile(
websiteUrl: String,
websiteKey: String,
action: String? = null,
cdata: String? = null
): String {
val taskData = mutableMapOf(
"type" to "AntiTurnstileTaskProxyLess",
"websiteURL" to websiteUrl,
"websiteKey" to websiteKey
)
// Thêm thông tin tùy chọn
if (action != null || cdata != null) {
val metadata = mutableMapOf<String, String>()
action?.let { metadata["action"] = it }
cdata?.let { metadata["cdata"] = it }
taskData["metadata"] = metadata
}
val taskId = createTask(taskData)
val result = getTaskResult(taskId)
return result.token ?: throw Exception("Không có token trong giải pháp")
}
suspend fun checkBalance(): Double {
val payload = mapOf("clientKey" to apiKey)
val request = Request.Builder()
.url("$baseUrl/getBalance")
.post(gson.toJson(payload).toRequestBody(jsonMediaType))
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
return result.get("balance")?.asDouble ?: 0.0
}
}
Giải quyết các loại CAPTCHA khác nhau
reCAPTCHA v2 với Browser4
kotlin
import ai.platon.pulsar.context.PulsarContexts
import ai.platon.pulsar.skeleton.session.PulsarSession
import kotlinx.coroutines.runBlocking
class ReCaptchaV2Extractor(
private val capSolver: CapSolverService
) {
suspend fun extractWithCaptcha(targetUrl: String, siteKey: String): Map<String, Any?> {
println("Giải reCAPTCHA v2...")
// Giải CAPTCHA trước tiên
val token = capSolver.solveReCaptchaV2(targetUrl, siteKey)
println("CAPTCHA đã được giải, độ dài token: ${token.length}")
// Tạo phiên và mở trang
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
// Chèn token vào ô nhập văn bản ẩn bằng thuộc tính value (an toàn)
driver?.evaluate("""
(function() {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = arguments[0];
})('$token');
""")
// Gửi biểu mẫu
driver?.evaluate("document.querySelector('form').submit();")
// Chờ đợi điều hướng
Thread.sleep(3000)
// Trích xuất dữ liệu từ trang kết quả
val document = session.parse(page)
mapOf(
"title" to document.selectFirstTextOrNull("h1"),
"content" to document.selectFirstTextOrNull(".content"),
"success" to (document.body().text().contains("success", ignoreCase = true))
)
}
}
fun main() = runBlocking {
val apiKey = System.getenv("CAPSOLVER_API_KEY") ?: "khóa_api_của_bạn"
val capSolver = CapSolverService(apiKey)
val extractor = ReCaptchaV2Extractor(capSolver)
val result = extractor.extractWithCaptcha(
targetUrl = "https://example.com/trang-bi-bao-ve",
siteKey = "6LcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxABC"
)
println("Kết quả trích xuất: $result")
}
reCAPTCHA v3 với Browser4
kotlin
class ReCaptchaV3Extractor(
private val capSolver: CapSolverService
) {
suspend fun extractWithCaptchaV3(
targetUrl: String,
siteKey: String,
action: String = "submit"
): Map<String, Any?> {
println("Giải reCAPTCHA v3 với hành động: $action")
// Giải reCAPTCHA v3 với hành động trang tùy chỉnh
val token = capSolver.solveReCaptchaV3(
websiteUrl = targetUrl,
websiteKey = siteKey,
pageAction = action
)
println("Token đã được lấy thành công")
// Tạo phiên và mở trang
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
// Chèn token vào trường ẩn (sử dụng gán giá trị an toàn)
driver?.evaluate("""
(function(tokenValue) {
var input = document.querySelector('input[name="g-recaptcha-response"]');
if (input) {
input.value = tokenValue;
} else {
var hidden = document.createElement('input');
hidden.type = 'hidden';
hidden.name = 'g-recaptcha-response';
hidden.value = tokenValue;
var form = document.querySelector('form');
if (form) form.appendChild(hidden);
}
})('$token');
""")
// Nhấn nút gửi
driver?.evaluate("document.querySelector('#submit-btn').click();")
Thread.sleep(3000)
val document = session.parse(page)
mapOf(
"kết quả" to document.selectFirstTextOrNull(".result-data"),
"trạng thái" to "thành công"
)
}
}
Cloudflare Turnstile với Browser4
kotlin
class TurnstileExtractor(
private val capSolver: CapSolverService
) {
suspend fun extractWithTurnstile(targetUrl: String, siteKey: String): Map<String, Any?> {
println("Giải Cloudflare Turnstile...")
// Giải với thông tin tùy chọn (hành động và cdata)
val taskId = capSolver.createTask(mapOf(
"type" to "AntiTurnstileTaskProxyLess",
"websiteURL" to targetUrl,
"websiteKey" to siteKey
))
val result = capSolver.getTaskResult(taskId)
return mapOf(
"token" to result.token,
"userAgent" to result.userAgent
)
}
}
val token = capSolver.solveTurnstile(
targetUrl,
siteKey,
action = "login", // tùy chọn
cdata = "0000-1111-2222-3333-example" // tùy chọn
)
println("Turnstile đã được giải!")
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
// Chèn token Turnstile (sử dụng gán giá trị an toàn)
driver?.evaluate("""
(function(tokenValue) {
var input = document.querySelector('input[name="cf-turnstile-response"]');
if (input) input.value = tokenValue;
})('$token');
""")
// Gửi biểu mẫu
driver?.evaluate("document.querySelector('form').submit();")
Thread.sleep(3000)
val document = session.parse(page)
mapOf(
"title" to document.selectFirstTextOrNull("title"),
"content" to document.selectFirstTextOrNull("body")?.take(500)
)
}
}
---
## Tích hợp với Browser4 X-SQL
X-SQL của Browser4 cung cấp khả năng trích xuất mạnh mẽ. Dưới đây là cách kết hợp nó với việc giải CAPTCHA:
```kotlin
class XSqlCaptchaExtractor(
private val capSolver: CapSolverService
) {
suspend fun extractProductsWithCaptcha(
targetUrl: String,
siteKey: String
): List<Map<String, Any?>> {
// Giải CAPTCHA trước
val token = capSolver.solveReCaptchaV2(targetUrl, siteKey)
// Tạo phiên và thiết lập phiên đã xác thực
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
driver?.evaluate("""
(function(tokenValue) {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = tokenValue;
document.querySelector('form').submit();
})('$token');
""")
Thread.sleep(3000)
// Bây giờ phân tích trang và trích xuất dữ liệu sản phẩm
val document = session.parse(page)
// Trích xuất dữ liệu sản phẩm bằng phương thức phiên tích hợp
val products = mutableListOf<Map<String, Any?>>()
val productElements = document.select(".product-item")
for ((index, element) in productElements.withIndex()) {
if (index >= 50) break // GIỚI HẠN 50
products.add(mapOf(
"name" to element.selectFirstTextOrNull(".product-name"),
"price" to element.selectFirstTextOrNull(".price")?.let {
"""(\d+\.?\d*)""".toRegex().find(it)?.groupValues?.get(1)?.toDoubleOrNull() ?: 0.0
},
"rating" to element.selectFirstTextOrNull(".rating")
))
}
return products.map { row ->
mapOf(
"name" to row["name"],
"price" to row["price"],
"rating" to row["rating"],
"image_url" to row["image_url"]
)
}
}
}
Mẫu xác thực trước
Đối với các trang yêu cầu CAPTCHA trước khi truy cập nội dung, sử dụng quy trình xác thực trước:
kotlin
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.HttpUrl
class PreAuthenticator(
private val capSolver: CapSolverService
) {
data class AuthSession(
val cookies: Map<String, String>,
val userAgent: String?
)
suspend fun authenticateWithCaptcha(
loginUrl: String,
siteKey: String
): AuthSession {
// Giải CAPTCHA
val captchaToken = capSolver.solveReCaptchaV2(loginUrl, siteKey)
// Gửi CAPTCHA để lấy cookie phiên
val client = OkHttpClient.Builder()
.cookieJar(object : CookieJar {
private val cookies = mutableListOf<Cookie>()
override fun saveFromResponse(url: HttpUrl, cookieList: List<Cookie>) {
cookies.addAll(cookieList)
}
override fun loadForRequest(url: HttpUrl): List<Cookie> = cookies
})
.build()
val formBody = okhttp3.FormBody.Builder()
.add("g-recaptcha-response", captchaToken)
.build()
val request = Request.Builder()
.url(loginUrl)
.post(formBody)
.build()
val response = client.newCall(request).execute()
// Trích xuất cookie từ phản hồi
val responseCookies = response.headers("Set-Cookie")
.associate { cookie ->
val parts = cookie.split(";")[0].split("=", limit = 2)
parts[0] to (parts.getOrNull(1) ?: "")
}
return AuthSession(
cookies = responseCookies,
userAgent = response.request.header("User-Agent")
)
}
}
class AuthenticatedExtractor(
private val preAuth: PreAuthenticator,
private val capSolver: CapSolverService
) {
suspend fun extractWithAuth(
loginUrl: String,
targetUrl: String,
siteKey: String
): Map<String, Any?> {
// Xác thực trước
val authSession = preAuth.authenticateWithCaptcha(loginUrl, siteKey)
println("Phiên đã được thiết lập với ${authSession.cookies.size} cookie")
// Tạo phiên Browser4
val session = PulsarContexts.createSession()
// Cấu hình phiên với cookie
val cookieScript = authSession.cookies.entries.joinToString(";") { (k, v) ->
"$k=$v"
}
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
// Thiết lập cookie
driver?.evaluate("document.cookie = '$cookieScript';")
// Tải lại với phiên đã xác thực
driver?.evaluate("location.reload();")
Thread.sleep(2000)
// Trích xuất dữ liệu
val document = session.parse(page)
return mapOf(
"authenticated" to true,
"content" to document.selectFirstTextOrNull(".protected-content"),
"userData" to document.selectFirstTextOrNull(".user-profile")
)
}
}
Tích hợp OpenRouter cho trích xuất dựa trên LLM
Các khả năng AI của Browser4 có thể được nâng cao bằng OpenRouter, một cổng API thống nhất để truy cập nhiều mô hình LLM. Điều này cho phép trích xuất nội dung thông minh, thích ứng với các cấu trúc trang khác nhau.
Dịch vụ OpenRouter
kotlin
import com.google.gson.Gson
import com.google.gson.JsonObject
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import java.util.concurrent.TimeUnit
data class ChatMessage(val role: String, val content: String)
data class ChatCompletion(val content: String, val model: String, val usage: TokenUsage)
data class TokenUsage(val promptTokens: Int, val completionTokens: Int, val totalTokens: Int)
class OpenRouterService(private val apiKey: String) {
private val client = OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build()
private val gson = Gson()
private val baseUrl = "https://openrouter.ai/api/v1"
private val jsonMediaType = "application/json".toMediaType()
fun chat(
messages: List<ChatMessage>,
model: String = "openai/gpt-4o-mini"
): ChatCompletion {
val payload = mapOf(
"model" to model,
"messages" to messages.map { mapOf("role" to it.role, "content" to it.content) }
)
val request = Request.Builder()
.url("$baseUrl/chat/completions")
.header("Authorization", "Bearer $apiKey")
.post(gson.toJson(payload).toRequestBody(jsonMediaType))
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
val choice = result.getAsJsonArray("choices")?.get(0)?.asJsonObject
val content = choice?.getAsJsonObject("message")?.get("content")?.asString ?: ""
val usage = result.getAsJsonObject("usage")
return ChatCompletion(
content = content,
model = result.get("model")?.asString ?: model,
usage = TokenUsage(
promptTokens = usage?.get("prompt_tokens")?.asInt ?: 0,
completionTokens = usage?.get("completion_tokens")?.asInt ?: 0,
totalTokens = usage?.get("total_tokens")?.asInt ?: 0
)
)
}
fun extractStructuredData(html: String, schema: String): String {
val prompt = """
Trích xuất dữ liệu sau từ nội dung HTML này.
Trả về CHỈ JSON hợp lệ khớp với lược đồ này: $schema
HTML:
${html.take(4000)}
""".trimIndent()
return chat(listOf(ChatMessage("user", prompt))).content
}
fun listModels(): List<String> {
val request = Request.Builder()
.url("$baseUrl/models")
.header("Authorization", "Bearer $apiKey")
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
return result.getAsJsonArray("data")?.mapNotNull {
it.asJsonObject.get("id")?.asString
} ?: emptyList()
}
}
Trích xuất thông minh với LLM và giải CAPTCHA
Kết hợp giải CAPTCHA với trích xuất dữ liệu thông minh:
kotlin
class SmartExtractor(
private val capSolver: CapSolverService,
private val openRouter: OpenRouterService
) {
suspend fun extractWithAI(
targetUrl: String,
siteKey: String?,
extractionPrompt: String
): Map<String, Any?> {
// Bước 1: Giải CAPTCHA nếu cần
val captchaToken = siteKey?.let {
println("Giải CAPTCHA...")
capSolver.solveReCaptchaV2(targetUrl, it)
}
// Bước 2: Tạo phiên và mở trang
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
captchaToken?.let { token ->
driver?.evaluate("""
(function(tokenValue) {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = tokenValue;
var form = document.querySelector('form');
if (form) form.submit();
})('$token');
""")
Thread.sleep(3000)
}
// Bước 3: Trích xuất nội dung trang
val document = session.parse(page)
val pageContent = document.body().text().take(8000)
// Bước 4: Sử dụng LLM để trích xuất dữ liệu có cấu trúc
val llmResponse = openRouter.chat(listOf(
ChatMessage("system", "Bạn là một trợ lý trích xuất dữ liệu. Trích xuất dữ liệu có cấu trúc từ các trang web."),
ChatMessage("user", """
$extractionPrompt
Nội dung trang:
$pageContent
""".trimIndent())
))
println("LLM đã sử dụng ${llmResponse.usage.totalTokens} token")
return mapOf(
"url" to targetUrl,
"captchaSolved" to (captchaToken != null),
"extractedData" to llmResponse.content,
"tokensUsed" to llmResponse.usage.totalTokens
)
}
}
// Cách sử dụng
fun main() = runBlocking {
val capSolver = CapSolverService(System.getenv("CAPSOLVER_API_KEY")!!)
val openRouter = OpenRouterService(System.getenv("OPENROUTER_API_KEY")!!)
val extractor = SmartExtractor(capSolver, openRouter)
val result = extractor.extractWithAI(
targetUrl = "https://example.com/products",
siteKey = "6LcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxABC",
extractionPrompt = """
Trích xuất tất cả sản phẩm với:
- tên
- giá (dưới dạng số)
- tình trạng tồn kho (trong kho/đã hết)
- đánh giá (1-5)
Trả về dưới dạng mảng JSON.
""".trimIndent()
)
println("Kết quả trích xuất: ${result["extractedData"]}")
}
Tạo bộ chọn thích ứng
Sử dụng LLM để tạo các bộ chọn CSS cho các cấu trúc trang chưa biết:
kotlin
class AdaptiveExtractor(
private val capSolver: CapSolverService,
private val openRouter: OpenRouterService
) {
suspend fun extractWithAdaptiveSelectors(
targetUrl: String,
siteKey: String?,
dataFields: List<String>
): Map<String, Any?> {
// Giải CAPTCHA trước tiên
val token = siteKey?.let { capSolver.solveReCaptchaV2(targetUrl, it) }
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
token?.let { t ->
driver?.evaluate("""
(function(tokenValue) {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = tokenValue;
})('$t');
""")
}
// Lấy cấu trúc HTML của trang
val htmlSample = driver?.evaluate("document.body.innerHTML")?.toString()?.take(5000) ?: ""
// Yêu cầu LLM tạo các bộ chọn
val selectorPrompt = """
Phân tích HTML này và cung cấp các bộ chọn CSS cho các trường sau: ${dataFields.joinToString(", ")}
Mẫu HTML:
$htmlSample
Trả về JSON như: {"fieldName": "css-selector", ...}
""".trimIndent()
val selectorsJson = openRouter.chat(listOf(ChatMessage("user", selectorPrompt))).content
val selectors = Gson().fromJson(selectorsJson, Map::class.java) as Map<String, String>
// Trích xuất bằng các bộ chọn được tạo
val document = session.parse(page)
val extractedData = selectors.mapValues { (_, selector) ->
document.selectFirstTextOrNull(selector)
}
return mapOf(
"url" to targetUrl,
"selectors" to selectors,
"data" to extractedData
)
}
}
Trích xuất song song với Coroutines
Thiết kế an toàn coroutine của Browser4 cho phép xử lý CAPTCHA hiệu quả theo cách song song:
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
data class ExtractionJob(
val url: String,
val siteKey: String?
)
data class ExtractionResult(
val url: String,
val data: Map<String, Any?>?,
val captchaSolved: Boolean,
val error: String?,
val duration: Long
)
class ParallelExtractor(
private val capSolver: CapSolverService,
private val concurrency: Int = 5
) {
suspend fun extractAll(jobs: List<ExtractionJob>): List<ExtractionResult> = coroutineScope {
val channel = Channel<ExtractionJob>(Channel.UNLIMITED)
val results = mutableListOf<ExtractionResult>()
// Gửi tất cả công việc đến kênh
jobs.forEach { channel.send(it) }
channel.close()
// Xử lý với độ đồng thời giới hạn
val workers = (1..concurrency).map { workerId ->
async {
val workerResults = mutableListOf<ExtractionResult>()
// Mỗi công nhân tạo phiên riêng để đảm bảo an toàn luồng
val workerSession = PulsarContexts.createSession()
for (job in channel) {
val startTime = System.currentTimeMillis()
var captchaSolved = false
try {
// Giải CAPTCHA nếu có site key
val token = job.siteKey?.let {
captchaSolved = true
capSolver.solveReCaptchaV2(job.url, it)
}
// Trích xuất dữ liệu
val page = workerSession.open(job.url)
token?.let { t ->
val driver = workerSession.getOrCreateBoundDriver()
driver?.evaluate("""
(function(tokenValue) {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = tokenValue;
})('$t');
""")
}
val document = workerSession.parse(page)
workerResults.add(ExtractionResult(
url = job.url,
data = mapOf(
"title" to document.selectFirstTextOrNull("title"),
"h1" to document.selectFirstTextOrNull("h1")
),
captchaSolved = captchaSolved,
error = null,
duration = System.currentTimeMillis() - startTime
))
} catch (e: Exception) {
workerResults.add(ExtractionResult(
url = job.url,
data = null,
captchaSolved = captchaSolved,
error = e.message,
duration = System.currentTimeMillis() - startTime
))
}
}
workerResults
}
}
workers.awaitAll().flatten()
}
}
// Cách sử dụng
fun main() = runBlocking {
val capSolver = CapSolverService(System.getenv("CAPSOLVER_API_KEY")!!)
val extractor = ParallelExtractor(capSolver, concurrency = 5)
val jobs = listOf(
ExtractionJob("https://site1.com/data", "6Lc..."),
ExtractionJob("https://site2.com/data", null),
ExtractionJob("https://site3.com/data", "6Lc..."),
)
val results = extractor.extractAll(jobs)
val solved = results.count { it.captchaSolved }
println("Hoàn thành ${results.size} trích xuất, giải được $solved CAPTCHA")
results.forEach { r ->
println("${r.url}: ${r.duration}ms - ${r.error ?: "thành công"}")
}
}
Các Nguyên Tắc Tốt
1. Xử Lý Lỗi Với Tái Thử
kotlin
suspend fun <T> withRetry(
maxRetries: Int = 3,
initialDelay: Long = 1000,
block: suspend () -> T
): T {
var lastException: Exception? = null
repeat(maxRetries) { attempt ->
try {
return block()
} catch (e: Exception) {
lastException = e
println("Lần thử ${attempt + 1} thất bại: ${e.message}")
delay(initialDelay * (attempt + 1))
}
}
throw lastException ?: Exception("Đạt giới hạn thử lại")
}
// Cách sử dụng
val token = withRetry(maxRetries = 3) {
capSolver.solveReCaptchaV2(url, siteKey)
}
2. Quản Lý Số Dư
kotlin
suspend fun ensureSufficientBalance(
capSolver: CapSolverService,
minBalance: Double = 1.0
) {
val balance = capSolver.checkBalance()
if (balance < minBalance) {
throw Exception("Số dư CapSolver không đủ: $${"%.2f".format(balance)}. Vui lòng nạp thêm.")
}
println("Số dư CapSolver: $${"%.2f".format(balance)}")
}
3. Bộ Đệm Token
kotlin
class TokenCache(private val ttlMs: Long = 90_000) {
private data class CachedToken(val token: String, val timestamp: Long)
private val cache = mutableMapOf<String, CachedToken>()
private fun getKey(domain: String, siteKey: String) = "$domain:$siteKey"
fun get(domain: String, siteKey: String): String? {
val key = getKey(domain, siteKey)
val cached = cache[key] ?: return null
if (System.currentTimeMillis() - cached.timestamp > ttlMs) {
cache.remove(key)
return null
}
return cached.token
}
fun set(domain: String, siteKey: String, token: String) {
val key = getKey(domain, siteKey)
cache[key] = CachedToken(token, System.currentTimeMillis())
}
}
// Cách sử dụng với bộ đệm
class CachedCapSolver(
private val capSolver: CapSolverService,
private val cache: TokenCache = TokenCache()
) {
suspend fun solveReCaptchaV2Cached(websiteUrl: String, websiteKey: String): String {
val domain = java.net.URL(websiteUrl).host
cache.get(domain, websiteKey)?.let {
println("Sử dụng token đã lưu")
return it
}
val token = capSolver.solveReCaptchaV2(websiteUrl, websiteKey)
cache.set(domain, websiteKey, token)
return token
}
}
Tùy Chỉnh Cấu Hình
| Thiết lập | Mô tả | Mặc định |
|---|---|---|
CAPSOLVER_API_KEY |
Mã API của bạn | - |
OPENROUTER_API_KEY |
Mã API OpenRouter cho tính năng LLM | - |
PROXY_ROTATION_URL |
URL dịch vụ thay đổi proxy | - |
Browser4 sử dụng application.properties cho cấu hình bổ sung |
Kết Luận
Việc tích hợp CapSolver với Browser4 tạo ra một sự kết hợp mạnh mẽ cho trích xuất dữ liệu web quy mô lớn. Kiến trúc an toàn coroutine và khả năng hiệu suất cực cao của Browser4, kết hợp với khả năng giải CAPTCHA đáng tin cậy của CapSolver, cho phép trích xuất dữ liệu ở quy mô lớn.
Các mẫu tích hợp chính:
- Chèn Token Trực tiếp: Chèn token đã giải quyết thông qua đánh giá JavaScript
- Đăng nhập Trước: Giải CAPTCHA để thiết lập phiên trước khi trích xuất
- Xử lý Đồng thời: Tận dụng coroutine để xử lý CAPTCHA song song
- Tích hợp X-SQL: Kết hợp giải CAPTCHA với ngôn ngữ truy vấn mạnh mẽ của Browser4
Dù bạn đang xây dựng hệ thống theo dõi giá cả, quy trình nghiên cứu thị trường hay nền tảng tổng hợp dữ liệu, sự kết hợp Browser4 + CapSolver cung cấp độ tin cậy và khả năng mở rộng cần thiết cho môi trường sản xuất.
Sẵn sàng bắt đầu chưa? Đăng ký CapSolver và sử dụng mã khuyến mãi BROWSER4 để nhận thêm 6% tiền thưởng cho lần nạp đầu tiên!
Câu Hỏi Thường Gặp
Browser4 là gì?
Browser4 là khung phần mềm tự động hóa trình duyệt hiệu suất cao, an toàn với coroutine từ PulsarRPA. Được xây dựng bằng Kotlin, nó được thiết kế cho trích xuất dữ liệu được hỗ trợ AI, hỗ trợ 100.000-200.000 lần truy cập trang phức tạp mỗi máy mỗi ngày.
CapSolver tích hợp với Browser4 như thế nào?
CapSolver tích hợp với Browser4 thông qua lớp dịch vụ giải CAPTCHA qua API CapSolver. Các token đã giải được chèn vào trang bằng khả năng đánh giá JavaScript của Browser4 (driver.evaluate()).
Những loại CAPTCHA nào mà CapSolver có thể giải?
CapSolver hỗ trợ reCAPTCHA v2, reCAPTCHA v3, Cloudflare Turnstile, Cloudflare Challenge (5s), AWS WAF, GeeTest v3/v4 và nhiều loại khác.
Chi phí của CapSolver là bao nhiêu?
CapSolver cung cấp giá cả cạnh tranh dựa trên loại và khối lượng CAPTCHA được giải. Truy cập capsolver.com để xem giá hiện tại. Sử dụng mã BROWSER4 để nhận 6% tiền thưởng.
Ngôn ngữ lập trình nào Browser4 sử dụng?
Browser4 được xây dựng bằng Kotlin và chạy trên JVM (Java 17+). Nó cũng có thể được sử dụng từ các ứng dụng Java.
Browser4 có xử lý giải CAPTCHA song song được không?
Có! Thiết kế an toàn coroutine của Browser4 cho phép xử lý hiệu quả song song. Kết hợp với API CapSolver, bạn có thể giải nhiều CAPTCHA đồng thời trên các công việc trích xuất khác nhau.
Làm thế nào để tìm khóa site CAPTCHA?
Khóa site thường được tìm thấy trong mã nguồn HTML của trang:
- reCAPTCHA: thuộc tính
data-sitekeytrên phần tử.g-recaptcha - Turnstile: thuộc tính
data-sitekeytrên phần tử.cf-turnstile - Hoặc kiểm tra các yêu cầu mạng để tìm khóa trong các cuộc gọi API
Tuyên bố Tuân thủ: Thông tin được cung cấp trên blog này chỉ mang tính chất tham khảo. CapSolver cam kết tuân thủ tất cả các luật và quy định hiện hành. Việc sử dụng mạng lưới CapSolver cho các hoạt động bất hợp pháp, gian lận hoặc lạm dụng là hoàn toàn bị cấm và sẽ bị điều tra. Các giải pháp giải captcha của chúng tôi nâng cao trải nghiệm người dùng trong khi đảm bảo tuân thủ 100% trong việc giúp giải quyết các khó khăn về captcha trong quá trình thu thập dữ liệu công khai. Chúng tôi khuyến khích việc sử dụng dịch vụ của chúng tôi một cách có trách nhiệm. Để biết thêm thông tin, vui lòng truy cập Điều khoản Dịch vụ và Chính sách Quyền riêng tư.
Thêm

Cách giải Captcha trong Maxun với tích hợp CapSolver
Một hướng dẫn thực tế về việc tích hợp CapSolver với Maxun cho quét web thực tế. Học cách xử lý reCAPTCHA, Cloudflare Turnstile và các trang web được bảo vệ bằng CAPTCHA bằng cách sử dụng quy trình xác thực trước và luồng công việc robot.

Anh Tuan
21-Jan-2026

Cách giải Captcha trong Browser4 với tích hợp CapSolver
Tự động hóa Browser4 tỷ lệ xử lý cao kết hợp với CapSolver để xử lý các thách thức CAPTCHA trong việc trích xuất dữ liệu web quy mô lớn.

Anh Tuan
21-Jan-2026

Bot rút trích là gì và cách xây dựng một cái
Học về bot quét và cách xây dựng một bot để trích xuất dữ liệu tự động. Khám phá các công cụ hàng đầu, kỹ thuật vượt qua bảo mật và thực hành trích xuất dữ liệu có đạo đức.

Anh Tuan
15-Jan-2026

Scrapy so với Selenium: Cái nào tốt nhất cho Dự án Ghi dữ liệu từ Web của bạn?
Khám phá các điểm mạnh và sự khác biệt giữa Scrapy và Selenium trong việc quét dữ liệu trên web. Học cách chọn công cụ phù hợp nhất với dự án của bạn và cách xử lý các thách thức như CAPTCHAs.

Rajinder Singh
14-Jan-2026

Cách sử dụng Selenium Driverless để quét web hiệu quả
Học cách sử dụng Selenium Driverless để quét web hiệu quả. Hướng dẫn này cung cấp các bước từng bước để cài đặt môi trường của bạn, viết script Selenium Driverless đầu tiên của bạn và xử lý nội dung động. Tối ưu hóa các nhiệm vụ quét web bằng cách tránh sự phức tạp trong quản lý WebDriver truyền thống, giúp quy trình trích xuất dữ liệu của bạn trở nên đơn giản hơn, nhanh hơn và dễ di chuyển hơn.

Sora Fujimoto
14-Jan-2026

Giải quyết lỗi 403 Truy cập bị từ chối khi quét trang web bằng Python
Học cách vượt qua các lỗi 403 Forbidden khi quét trang web bằng Python. Hướng dẫn này bao gồm quay vòng IP, giả mạo user-agent, kiểm soát tần suất yêu cầu, xử lý xác thực và sử dụng trình duyệt không đầu để vượt qua các hạn chế truy cập và tiếp tục quét web thành công.

Sora Fujimoto
13-Jan-2026


