【问题标题】:Kotlin Selenium Chromedriver doesn't existKotlin Selenium Chromedriver 不存在
【发布时间】:2019-03-20 17:51:54
【问题描述】:

我正在尝试使用 Kotlin 制作网页抓取应用。由于我要抓取的网站是 JS 生成的,所以我一直在尝试让 Selenium 工作,但我一直被这个错误所困扰。

java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:353)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.IllegalStateException: The driver executable does not exist: /home/nexus/Downloads/chromedriver

我已经在驱动程序中使用了“chmod 777”,并在 AUR 版本中也尝试过。

这是我的抓取功能的代码

package com.example.nexus.scraper

import android.os.AsyncTask
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver

class Scrape(): AsyncTask<Void, Void, Void>() {
    override fun doInBackground(vararg params: Void?): Void? {
        System.setProperty("webdriver.chrome.driver","/home/nexus/Downloads/chromedriver")
        var driver: WebDriver = ChromeDriver()
        driver.get("www.google.com")
        return null
    }
}

这是我的 build.gradle

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.example.nexus.scraper"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        packagingOptions {
            exclude 'META-INF/DEPENDENCIES'
            exclude 'META-INF/LICENSE'
            exclude 'META-INF/LICENSE.txt'
            exclude 'META-INF/license.txt'
            exclude 'META-INF/NOTICE'
            exclude 'META-INF/NOTICE.txt'
            exclude 'META-INF/notice.txt'
            exclude 'META-INF/ASL2.0'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"    
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '2.41.0'
    implementation 'com.android.support:support-annotations:27.1.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

谢谢!

【问题讨论】:

    标签: linux selenium web-scraping kotlin


    【解决方案1】:

    我强烈建议使用webdriver manager 而不是自己设置浏览器二进制文件。

    要安装一个新的 chrome 驱动程序,我会在我的代码中放置一个这样的函数:

    fun chrome(): WebDriver {
        WebDriverManager.chromedriver().setup()
        return ChromeDriver(chromeOptions())
    }
    

    现在您可以使用这个函数来返回您的 chrome 驱动程序,如下所示:

    val driver = chrome()
    driver.get("www.google.com")
    

    webdriver manager 将根据您当前的操作系统自动设置驱动程序二进制文件。 有关可以在不同浏览器或驱动程序设置之间动态切换以及完整的 selenium 设置的更复杂示例,请查看here

    因为你想抓取一个网站,我猜你应该选择 chrome 无头模式,因为它在浏览器启动时间等方面效率更高。

    一般来说,我建议使用 skrape{it} 而不是 selenium 来完成这项工作(只要您不必单击某处)。它是一个用 kotlin 编写的库,专门设计用于抓取网站并支持抓取 javascript 呈现的网站。例如,你可以做这样的事情,你就完成了(不需要硒开销):

    val githubName = skrape {
        url = "https://github.com/skrapeit"
        mode = Mode.DOM
        extract {
            element(".h-card .p-nickname").text()
        }
    }
    

    这也适用于更复杂的数据,例如:

    data class MyScrapedData(
        val userName: String, 
        val repositoryNames: List<String>
    )
    
    fun main() {
        val githubUserData = skrape {
            url = "https://github.com/skrapeit"
            mode = Mode.DOM
    
            extract {
                MyScrapedData(
                    userName = element(".h-card .p-nickname").text(),
                    repositoryNames = elements("span.repo").map { it.text() }
                )
            }
        }
        println("${githubUserData.userName}'s repos are ${githubUserData.repositoryNames}")
    }
    

    有关如何使用 skrape{it} 抓取 javascript 呈现的网站的完整示例,请查看其对应的 docs section

    【讨论】:

      【解决方案2】:

      你必须在 gradle.build 中应用 chromedriver 目录:

       '--webdriver.chrome.driver=/home/nexus/Downloads/chromedriver'
      

      【讨论】:

      • gradle.build 在哪里?谢谢
      • 我不太清楚。我想作为依赖项下的一个单独部分。我的 gradle.build 中的配置也是如此。我使用 gradle/chromedriver/java/kotlin。我将一些代码转换为 kotlin,在这种情况下 gradle.build 没有什么不同。
      • 我得到一个“在 org.gradle.api.Project 类型的项目 ':app' 上找不到参数 [build_2xxhsdyepkutmlh7n527jg8dp$_run_closure3@6ecb0f76] 的方法 bootRun()。”错误
      • 问题是如何将 args 添加到 gradle.build 以用于 android-app。我的示例来自 springboot-app。这个问题不只属于kotlin,java也是一样。这是关于 gradle 和 chromedriver 的。
      【解决方案3】:

      错误是由使用 Selenium 而不是 Selendium 引起的

      【讨论】:

        猜你喜欢
        • 2021-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-10
        • 1970-01-01
        • 2017-02-09
        • 2018-04-11
        相关资源
        最近更新 更多