Python은 유용한 언어입니다. 그러나 스크립팅 언어로 유형을 엄격하게 평가하지 않거나 일부 고부하 작업에서 잘 수행되지 않을 수 있습니다. 거대해지고, 병렬성이 요구되는 프로그램에서는, Python의 재현성이 없는 에러에 대해 고민되는 경우가 많았습니다. 아무렇지도 않게 만난 Kotlin은 상당히 사용하기 쉽고, Python3에서 구현하고 있던 Scraper를 이식해 보았습니다.
(덧붙여서 나는 자바를 흔들어 본 적이 없다)
Kotlin Newby이지만 Python의 스레드와 Kotlin의 스레드는 동작이 다르게 보입니다.
Kotlin의 Thread에서는 프로세스가 분할하지 않는데, CPU의 사용률이 100%를 넘기 때문에, 복수 CPU를 사용한 효율적인 Threading가 행해지고 있는 것 같습니다 (즉, Multiprocess로 분할한 뒤, Thread를 아래에서 실행해야 할 것 같습니다)
우분투에 설치하는 방법입니다.
$ curl -s https://get.sdkman.io | bash
$ sdk install kotlin
환경 변수 JAVA_OPT에 JVM의 메모리가 적혀있는 것 같고, 보통으로 사용하면 메모리 부족으로 떨어지므로 지금 바람에 다시 두는 것이 좋을 것입니다.
JAVA_OPTS= " -Xmx3000M -Xms3000M "
저는 자바가 약하고 자바를 최대한 피하는 경력 계획을 걷고 싶었지만, 그것은 주로 이클립스나 IDE 등의 툴 자체의 학습 비용이 많다고 느끼고 있어 힘들다고 생각한다 일이 많았기 때문입니다.
Kotlin도 IDE를 사용하면 편리합니다만, CUI로 컴파일&실행으로 문제가 생기지 않는 한은 CUI로 좋다고 생각하고 있습니다.
컴파일에는, 여러가지 있습니다만, runtime을 포함해, jar 파일에 굳혀 버리는 것이 유저빌리티 높였습니다.
$ kotlinc foo.kt -include-runtime -d foo.jar
이제 컴파일할 수 있습니다.
여러 파일을 함께 jar로 만들 수 있습니다.
$ kotlinc foo.kt bar.kt -include-runtime -d foo.jar
Java의 Maven 등으로 컴파일하여 얻을 수 있는 jar 파일을 classpath에 추가하는 것으로 이용 가능합니다.
많은 자바 자산을 재사용 할 수 있기 때문에 매우 도움이됩니다.
$ kotlinc foo.kt bar.kt -cp alice.jar:bob.jar -include-runtime foo.jar
예를 들면, 외부의 jar 파일을 이용한 kotlin의 jar를 실행할 때에는 이러한 명령이 됩니다.
$ kotlin -cp alice.jar:bob.jar:foo.jar FooKt
이 FooKt라는 이름은 main 함수를 포함하는 foo.kt 파일을 지정하는 데 사용되는 것 같습니다.
JavaScript에 의한 비동기의 데이터 로드가 있는 경우, 단순히 취득해 jsoup등으로 해석하는 것만으로는, 컨텐츠를 취할 수 없습니다 JavaScript를 동작시켜 인간이 보고 있는 것과 같은 상태를 만들지 않으면 안 되기 때문에 , selenum을 통해 phamtomjs를 실행하여 자바 스크립트를 실행 예를 들어, MicrosoftBing의 이미지 검색은 Ajax로 그려져 있으며 JavaScritp가 작동하지 않는 환경에서는 작동하지 않습니다.
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()
html이라는 변수에 JavaScript가 동작한 뒤 그려진 상태의 html이 들어갑니다. 이것을 jsoup에 넣는 것으로, 각종 이미지의 src의 URL을 알 수 있습니다 발견한 이미지의 URL을 바탕으로, wget 커멘드로 임의 디렉토리 아래 폴더에 저장
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는 이 사이트에서 컴파일된 바이너리를 다운로드하여 PATH가 통과한 곳에 있어야 합니다.
몇 가지 쓰기가 있는 것 같습니다만, 가장 간단하게 할 수 있었던 구현입니다.
스크레이핑 하는 로직 전체를 {}로 둘러싼 부분이 thread의 인스턴스가 되어, 그 thread를 start 시키거나, join 하거나 해 병렬로 움직일 수가 있습니다.
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
}
jackson이라는 직렬화 모듈이 한정적으로 사용할 수있는 것 같습니다.
Java 라이브러리만으로는 작동하지 않는 것으로 보이며 Kotlin 용 모듈을 별도로로드해야합니다.
한정적이라는 것은 MutableMap<String, DataClass>를 직렬화, deserialize 해 보았는데 잘 가지 않았습니다.
MutableMap<String, String>은 잘 가기 때문에, 중첩 구조가 안 되는지, Data Class에 대응하고 있지 않는지 잘 알고 있지 않습니다.
직렬화의 예
val mapper = ObjectMapper ().registerKotlinModule()
val serialzied = mapper.writeValueAsString(url_details)
디시리얼라이즈의 예
val mapper = ObjectMapper ().registerKotlinModule()
val url_details = mapper.readValue< MutableMap < String , String >>(json)
먼저 git clone
$ git clone https://github.com/GINK03/kotlin-phantomjs-selenium-jsoup-parser.git
지금까지 두 종류의 스크래핑까지 구현이 완료되고 있어 단순히 자바스크립트를 평가하지 않고 폭 우선 탐색으로 깊이 100까지 스크레이핑을 한다.
(자신의 사이트의 스크래핑에 사용하고 있었기 때문에, 특별히 제한은 마련하고 있지 않습니다만, 50 병렬 이상의 병렬 액세스로 표준으로 액세스 하므로, 적절히 조정해 주세요.)
$ sh run.scraper.sh widthSearch ${yourOwnSite}
Microsoft Bing을 이용하여 이미지 검색 화면에서 검색합니다. 하지 않는 것이라고 생각합니다.
검색 목록은 github의 kancolle.txt 파일을 참조하십시오.
sh run.scraper.sh image ${検索クエリリスト} ${出力ディレクトリ}