linux - Kotlin Selenium Chromedriver 不存在

标签 linux selenium web-scraping kotlin

我正在尝试使用 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'
}

谢谢!

最佳答案

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

为了实例化一个新的 chrome 驱动程序,我会在我的代码中放置一个这样的函数:

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

现在你可以只使用这个函数,它会像这样返回你的 chrome 驱动程序:

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

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

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

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

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

关于linux - Kotlin Selenium Chromedriver 不存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55267236/

相关文章:

linux - 我可以在 INSMOD 或 MODPROBE 期间将参数传递给驱动程序吗?

c++ - 如何在单独的 Linux 和 Windows 计算机上使用代码块开发 C++ 项目?

testing - 我是使用 Selenium 进行自动化测试的新手。运行自动化测试需要什么?

python - scrapy 正则表达式也返回不匹配的 url

linux - 尾部最近的文件

php系统 "Syntax error: Bad fd number"

python - 如何仅在python selenium中获取第一层子元素

python - 允许 Firefox 使用 Selenium 自动下载文件。这可以用 PhantomJS 完成吗?

python - 我的脚本无法从网页获取食品店的名称

python - 无法准确抓取google新闻