はじめに
・JAVAは未経験
・qiita初投稿
・kotlinは本を1冊読んで手を動かして遊んだ程度
・普段はPHPやrails
・理解度が浅いため、全体的にふんわりしています。ご指摘等頂ければ幸いです
dockerで環境を作る。
まずはkotlinがコンパイル出来るよう、環境を作っていきます。
docker-hubのdockerfileをベースにしますが
gradle
が足りないので入れます(gradleについては後述)
gradle公式dockerfileを参考にしました
alpine-linuxは軽量なため、コマンドが最小限です。
curlなども入っていないので必要なものはapkで入れています。
FROM openjdk:8-jdk-alpine
RUN apk update \
&& apk upgrade \
&& apk add coreutils curl
ARG BUILD_DATE
ARG VCS_REF
# Set Appropriate Environmental Variables
ENV GRADLE_HOME /usr/lib/gradle
ENV GRADLE_VERSION 4.7
ENV GRADLE_FOLDER=/root/.gradle
ARG GRADLE_DOWNLOAD_SHA256=fca5087dc8b50c64655c000989635664a73b11b9bd3703c7d6cabd31b7dcdb04
RUN set -o errexit -o nounset \
&& echo "Installing build dependencies" \
&& apk add --no-cache --virtual .build-deps \
ca-certificates \
openssl \
unzip \
\
&& echo "Downloading Gradle" \
&& wget -O gradle.zip "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" \
\
&& echo "Checking download hash" \
&& echo "${GRADLE_DOWNLOAD_SHA256} *gradle.zip" | sha256sum -c - \
\
&& echo "Installing Gradle" \
&& unzip gradle.zip \
&& rm gradle.zip \
&& mkdir /opt \
&& mv "gradle-${GRADLE_VERSION}" "${GRADLE_HOME}/" \
&& ln -s "${GRADLE_HOME}/bin/gradle" /usr/bin/gradle \
\
&& apk del .build-deps \
\
&& echo "Adding gradle user and group" \
&& addgroup -S -g 1000 gradle \
&& adduser -D -S -G gradle -u 1000 -s /bin/ash gradle \
&& mkdir /home/gradle/.gradle \
&& chown -R gradle:gradle /home/gradle \
\
&& echo "Symlinking root Gradle cache to gradle Gradle cache" \
&& ln -s /home/gradle/.gradle /root/.gradle
LABEL org.label-schema.build-date=$BUILD_DATE \
org.label-schema.description="Kotlin docker images built upon official openjdk alpine images" \
org.label-schema.name="alpine-kotlin" \
org.label-schema.schema-version="1.0.0-rc1" \
org.label-schema.usage="https://github.com/Zenika/alpine-kotlin/blob/master/README.md" \
org.label-schema.vcs-url="https://github.com/Zenika/alpine-kotlin" \
org.label-schema.vcs-ref=$VCS_REF \
org.label-schema.vendor="Zenika" \
org.label-schema.version="1.2-jdk8"
RUN apk add --no-cache bash && \
apk add --no-cache -t build-dependencies wget && \
cd /usr/lib && \
wget https://github.com/JetBrains/kotlin/releases/download/v1.2.41/kotlin-compiler-1.2.41.zip && \
unzip kotlin-compiler-*.zip && \
rm kotlin-compiler-*.zip && \
rm kotlinc/bin/*.bat && \
apk del --no-cache build-dependencies
ENV PATH $PATH:/usr/lib/kotlinc/bin
RUN apk del coreutils curl
# コンテナのワークディレクトリの指定
WORKDIR /app
CMD ["kotlinc"]
VOLUME $GRADLE_FOLDER
version: '2'
services:
kotlin:
build: .
command: bash -c "gradle run"
volumes:
- .:/app
これでdocker-compose build
後、
docker-compose up
をすれば
gradle run
を実行してくれます
2 gradleを書く
gradleはビルドの自動化ツールです。
Android開発者ならbuild.gradle
を見たことがあると思います。
「ライブラリとか追加するときに編集する奴」程度の認識で
あまりgradleの恩恵を分かっていませんでした
今回はAndroidではなくコマンドライン上での実行になるため、
kotlinc
コマンド でコンパイルし、kotlin
やjava
で実行をしますが
ライブラリ等の依存関係管理がとても面倒です。
ここでgradleが登場します。
gradle
を使えばライブラリの管理やビルド、実行を全て行ってくれます。
(厳密にはそれ以外にもなんでも出来るみたいです)
build.gradle
に依存関係やmainクラス名を書きます。
その後gradle run
を叩けばでビルドと実行をやってくれます
android studio
で開発するときもエディタが自動で認識して
コーディングヒントを与えてくれます
gradleの理解が曖昧だったためここに一番時間がかかりましたが、結局こうなりました。
build.gradle
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName = "ScrapingKt"
buildscript {
ext.kotlin_version = '1.2.41'
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jsoup:jsoup:1.10.3"
compile "org.apache.httpcomponents:httpclient:4.5"
}
allprojects {
repositories {
jcenter()
}
}
4 動くか確認
くそコードで動くか確認。
build.gradleでスクレイピング用ライブラリJsoup
を足しているので
それが使えるかの確認です。
import org.jsoup.Jsoup
//Jsoupが使えているかのテスト。引数とかはまだ特に関係ない。
class Hoge(val url: String) {
fun test() {
val doc = org.jsoup.Jsoup.parse("<div id='a'>aiueo</div><div id='b'>bbb</div>")
println(doc.select("#a"))
}
}
fun main(args: Array<String>) {
val foo = Hoge("test")
foo.test()
}
docker-compose up
を叩き、<div id='a'>aiueo</div>
とコンソールに出れば成功です
3 スクレイピングする。
準備が整ったのでスクレイピングしていきます。
まずはkotlinうんぬんの前に、
「どのURLにどういう値を投げれば、何が返ってくるのか」
を
ChromeのDeveloper Toolで確認
https://search.yahoo.co.jp/image/paginationjs
というAPIが関係してそう。
GETなのでブラウザのURLに直接入れて確認。
投げる値を変更したり、余計そうなのを無くしてみたり。
.crumb
.ncrumb
が必須みたい?
てかjsonで帰ってくるけど、中身はほぼhtmlなのかー。(エスケープ処理はしている?)
エスケープシーケンスの\を取り除いてjsoupに流し込めば、セレクタ使ってほしいものがとれそう。
やっかいなのは。
.crumb
.ncrumb
最初はGET値決め打ちで通信出来たけど、時間がたつと失敗してしまう。
.ncrumb
が時間とともに変わってるくさい。
じゃあこいつらはどこで生成されてるんだ、どうせhidden
だろうと思ったが
https://search.yahoo.co.jp/image/search
中でjavascriptにより生成されている
セレクタ使えないじゃんーってことで正規表現でゴリゴリ取得。
ちなみにUser Agent見てるらしく、適当だとこの部分だけ生成してくれない。
かなり苦戦。
APIの仕様が分かれば、後はセレクタで欲しいものを指定して、
ループ処理をするだけ。
ファイル保存関連はググればJAVAのコードがたくさん出てきます
最終的に
最終的にこんな感じになりました
docker-compose up
をすると南ことりちゃんの画像が自動でsaveディレクトリに保存されるようになりました
以下感想
エディタについて
最初はatomでやってましたが、
最終的にはandroid-studioで作業しました。
この神IDEを無料で使えるのが強みの1つだと思います。
JAVAのコードを貼ると自動でkotlinに変えてくれるので、JAVA未経験マンにとってはとても助かりました
スクレイピング
結局はセレクタ使うので、ある程度ベースができればjavascriptやpythonでのスクレピングとあんまり変らないかも
Javaの広大な知見がそのまま使えるのが非常に助かります、
画像の質
ディープラーニング用の画像を集める という目的もあったのですが
個々の画像の精度に関してはyahoo画像検索よりもpinterestのほうが良さそうでした。
pinterestからディープラーニング用二次元画像を集める
とは言えyahoo画像検索の画像数は大量のため、絞り込み条件をうまく使えば
実用的だなぁと思いまいた
最後に
・kotlin、名前に惹かれて勉強したけどかなり良い言語
・Android Studio神
・間違い等あると思いますのでご指摘お待ちしております
・rootが取れなくてインテリアになった【作ってみた】スクフェス専用コントローラー