#
Быстрый старт
На предыдущих страницах было много информации о бесконечных кодах ответа и кодах выхода.
Вам действительно нужны все эти сложности прямо сейчас? Ну, возможно. А может и нет. Можем сказать с уверенность, что
некоторые из них вам нужны, все зависит от вашего варианта использования и от того, насколько вы хотите что бы ваша система была самодостаточной и насколько подвержена ошибкам.
#
Начните с малого, стремитесь к высокому
Мы рекомендуем начинать с наименьшего количества кода и сложности и добавлять его по мере необходимости. Вы абсолютно сможете использовать автоматизацию, не перехватывая ни одного кода выхода. Если вы единственный пользователь кластера (то есть вы используете свой кластер исключительно для автоматизации и ничего больше) - тогда вы не увидите добрую половину возможных кодов ошибок.
Вы можете начать создавать свое приложение, не обрабатывая никаких ошибок, а только выводя их на консоль на случай появления ошибок, а затем добавьте код, чтобы отловить их позже, если они у вас случаются часто.
Тот же подход можно применить и к шагам сеанса браузера. Например. вы можете пропустить операции с папками и остановку профиля и добавить их только тогда, когда облачное хранилище станет для вас актуальным. Посмотрите, насколько коротким может выглядеть ваш старт:
val apiUrl = "https://api.surfinite.com"
val apiKey = "MY_API_KEY"
val profileId = "my_profile_id"
val url = "$apiUrl/profiles/$profileId/start?use_lock=false&api_key=$apiKey"
val browserKey = runCatching {
HttpClient(CIO) { expectSuccess = true }.use { client ->
val responseBodyString = client.post(url).bodyAsText()
Json.parseToJsonElement(responseBodyString)
.jsonObject["browserKey"]!!
.jsonPrimitive.content
}
}.getOrElse {
it.printStackTrace()
return
}
val profileDir = File("profiledirs").combineSafe(profileId)
val options = ChromeOptions()
options.addArguments(
"--user-data-dir=\"${profileDir.absolutePath}\"",
"--profile-id=$profileId",
"--browser-key=$browserKey"
)
options.setBinary("/home/myuser/.surfinite/browser/chrome")
System.setProperty("webdriver.chrome.driver", "/home/myuser/.surfinite/browser/chromedriver")
val driver = runCatching { ChromeDriver(options) }
.getOrElse {
it.printStackTrace()
return
}
driver["https://example.com"]
Этот код длиной 36 строк способен запустить браузер. Вы сможете протестировать свою логику Selenium.
#
Добавляйте сложность по мере продвижения
После добавления шагов загрузки и выгрузки папки (и даже обработки кода выхода «4») код остается длинной в 84 строки.
val apiUrl = "https://api.surfinite.com"
val apiKey = "MY_API_KEY"
val profileId = "my_profile_id"
val url = "$apiUrl/profiles/$profileId/start?use_lock=false&api_key=$apiKey"
val browserKey = runCatching {
HttpClient(CIO) { expectSuccess = true }.use { client ->
val responseBodyString = client.post(url).bodyAsText()
Json.parseToJsonElement(responseBodyString)
.jsonObject["browserKey"]!!
.jsonPrimitive.content
}
}.getOrElse {
it.printStackTrace()
return
}
val profileDir = File("profiledirs").combineSafe(profileId)
var process = ProcessBuilder(
listOf(
"/home/myuser/.surfinite/aemulari/aemulari",
"create-folder",
"--profile-id", profileId,
"--path", profileDir.absolutePath,
"--api-key", apiKey
)
)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start()
process.waitFor()
var code = process.exitValue()
if (code != 0) {
println("Download folder exited with code $code")
return
}
val options = ChromeOptions()
options.addArguments(
"--user-data-dir=\"${profileDir.absolutePath}\"",
"--profile-id=$profileId",
"--browser-key=$browserKey"
)
options.setBinary("/home/myuser/.surfinite/browser/chrome")
System.setProperty("webdriver.chrome.driver", "/home/myuser/.surfinite/browser/chromedriver")
val driver = runCatching { ChromeDriver(options) }
.getOrElse {
it.printStackTrace()
return
}
driver["https://example.com"]
// ...
driver.quit()
process = ProcessBuilder(
listOf(
"/home/myuser/.surfinite/aemulari/aemulari",
"upload-folder",
"--profile-id", profileId,
"--path", profileDir.absolutePath,
"--api-key", apiKey,
"--delete"
)
)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start()
process.waitFor()
code = process.exitValue()
if (code != 0) {
if (code == 4) profileDir.deleteRecursively()
else {
println("Upload folder exited with code $code")
return
}
}
Мы пытаемся сказать: не бойтесь всех этих возможных неудач. Это функции для вашей будщей разработки, а не требования. Вам придется потратить еще немного времени на то, чтобы все заработало, хотя когда дело доходит до оптимизации - у вас будет полный контроль над каждым шагом и большая гибкость, что означает более быстрое развитие для вас!