Python es un lenguaje útil. Sin embargo, puede salir mal debido a la falta de evaluación de tipos estricta del lenguaje de secuencias de comandos y a algunas operaciones costosas. Según mi experiencia personal, a menudo me han preocupado errores irreproducibles en Python en programas donde el objetivo del análisis se vuelve grande y se requiere paralelismo. Casualmente probé Kotlin y descubrí que era bastante fácil de usar, así que intenté migrar el Scraper que se implementó en Python3.
(Por cierto, nunca he tocado Java)
Este es un novato en Kotlin, pero los subprocesos de Python y los subprocesos de Kotlin parecen comportarse de manera diferente.
Aunque el subproceso de Kotlin no divide el proceso, la tasa de uso de la CPU supera el 100%, por lo que parece que se están realizando subprocesos eficientes utilizando varias CPU. (En otras palabras, después de dividir con Multiproceso, parece que no hay necesidad de ejecutar Thread debajo de él)
Así es como se instala en Ubuntu.
$ curl -s https://get.sdkman.io | bash
$ sdk install kotlin
Parece que la memoria JVM está registrada en la variable de entorno JAVA_OPT, y si la usas normalmente, fallará por falta de memoria, por lo que sería mejor arreglarlo de una manera moderna. Tengo la configuración como esta.
JAVA_OPTS= " -Xmx3000M -Xms3000M "
No soy bueno en Java y estaba pensando en seguir un plan de carrera que evitaría Java tanto como fuera posible, pero siento que sería difícil aprender las herramientas en sí, principalmente Eclipse e IDE, porque había muchas. de las cosas.
Sería conveniente usar Kotlin con un IDE, pero creo que CUI está bien siempre que no haya problemas al compilar y ejecutar con CUI.
Hay muchas formas de compilar, pero nos resultó más útil compilarlo en un archivo jar, incluido el tiempo de ejecución.
$ kotlinc foo.kt -include-runtime -d foo.jar
Ahora puedes compilar.
Puede combinar varios archivos en un jar. (Puede consultar las funciones y la clase de bar.kt en foo.kt)
$ kotlinc foo.kt bar.kt -include-runtime -d foo.jar
Se puede usar agregando un archivo jar que se pueda compilar usando Maven de Java, etc. al classpath. (Supongamos que utiliza los archivos alice.jar y bob.jar)
Esto es muy útil ya que nos permite reutilizar muchos recursos de Java.
$ kotlinc foo.kt bar.kt -cp alice.jar:bob.jar -include-runtime foo.jar
Por ejemplo, al ejecutar un jar de Kotlin usando un archivo jar externo, el comando será así.
$ kotlin -cp alice.jar:bob.jar:foo.jar FooKt
Este nombre FooKt parece usarse para especificar el archivo foo.kt que contiene la función principal.
Cuando hay una carga de datos asincrónica usando JavaScript, si simplemente los recupera y analiza con jsoup, etc., no podrá obtener el contenido. Debe ejecutar JavaScript para crear un estado similar al que vería un humano. ejecute phamtomjs a través de selenium para que JavaScript funcione. Por ejemplo, la búsqueda de imágenes de Microsoft Bing se procesa con Ajax y no puede funcionar en un entorno donde JavaScript no funciona. (Esto es para fines experimentales, por lo que cuando extraiga imágenes, hágalo a través de la API).
val driver = PhantomJSDriver ()
driver.manage().window().setSize( Dimension ( 4096 , 2160 ))
driver.get( " https://www.bing.com/images/search?q= ${encoded} " )
//すべての画像が描画されるのを待つ
Thread .sleep( 3001 )
val html = driver.getPageSource()
La variable html contendrá el html renderizado después de que se ejecute JavaScript. Al poner esto en jsoup, puede encontrar la URL src de varias imágenes según la URL de la imagen que encontró, use el comando wget para almacenarla en una carpeta en cualquier directorio.
val doc = Jsoup .parse(html.toString(), " UTF-8 " )
println (doc.title())
doc.select( " img " ).filter { x ->
x.attr( " class " ) == " mimg "
}.map { x ->
val data_bm = x.attr( " data-bm " )
val src = x.attr( " src " )
Runtime .getRuntime().exec( " wget ${src} -O imgs/ ${name} / ${data_bm} .png " )
}
PhantomJS debe descargarse de este sitio y colocarse en la RUTA.
Parece haber varias formas de escribir esto, pero esta es la implementación más sencilla.
Toda la lógica que se eliminará incluida en {} se convierte en una instancia de subproceso y puede iniciar o unirse a ese subproceso para ejecutarlo en paralelo.
val threads = url_details.keys.map { url ->
val th = Thread {
if (url_details[url] !! == "まだ" ) {
_parser (url).map { next ->
urls.add(next)
}
println ( "終わりに更新 : $url " )
url_details[url] = "終わり"
// save urls
_save_conf ( mapper.writeValueAsString(url_details) )
}
}
th
}
Parece que un módulo de serialización llamado jackson se puede utilizar por tiempo limitado.
Parece que la biblioteca Java por sí sola no funciona y es necesario cargar el módulo para Kotlin por separado.
De forma limitada, intenté serializar y deserializar MutableMap<String, DataClass> y no funcionó.
MutableMap<String, String> funciona bien, por lo que no estoy seguro de si la estructura anidada es mala o si no admite la clase de datos.
Ejemplo de serialización
val mapper = ObjectMapper ().registerKotlinModule()
val serialzied = mapper.writeValueAsString(url_details)
Ejemplo de deserialización
val mapper = ObjectMapper ().registerKotlinModule()
val url_details = mapper.readValue< MutableMap < String , String >>(json)
Primero, clonar git
$ git clone https://github.com/GINK03/kotlin-phantomjs-selenium-jsoup-parser.git
Hasta ahora, se han implementado dos tipos de raspado: simplemente raspar hasta una profundidad de 100 utilizando la búsqueda en amplitud sin evaluar JavaScript.
(Como lo estaba usando para raspar mi propio sitio, no establecí ningún límite particular, pero el valor predeterminado es 50 o más accesos paralelos, así que ajústelo en consecuencia).
$ sh run.scraper.sh widthSearch ${yourOwnSite}
Utilice Microsoft Bing para buscar en la pantalla de búsqueda de imágenes. Este es un código experimental para ver si es posible dibujar contenido con Ajax sin usar la API, por lo que no creo que se deba acceder a él en grandes cantidades y causar problemas.
Consulte el archivo kancolle.txt en github para ver la lista de búsqueda.
sh run.scraper.sh image ${検索クエリリスト} ${出力ディレクトリ}