セプテーニさんのScalaもくもく会に参加させて頂いた際に、Scalaの勉強用に簡易クローラーを作成してみました。その作業ログになります。
HTMLパーサー
とりあえずXPathを使用できるHTMLパーサーが必要だなということで調べてみたところ、HtmlUnitDriver
が使い勝手が良さそう&情報も多そうだったのでこれを使ってみます。
HtmlUnitDriverを使ってHTMLスクレイピング in Scala - Qiita
HtmlUnitDriverのバージョン
上記の、rkanekoさんとyutakikuchiさんの記事ではwebdriver-htmlunit
というjarファイルが使用されていたのですが、これがどうもかなり古い(2009年で更新が止まっている)ようなので、ちょっと調べてみたところHtmlUnitDriver
には下記3種類のjarファイルが存在しているようです。
groupId | artifactId | Latest Version | Updated |
---|---|---|---|
org.seleniumhq.webdriver | webdriver-htmlunit | 0.9.7376 | 08-Oct-2009 |
org.seleniumhq.selenium | selenium-htmlunit-driver | 2.52.0 | 12-Feb-2016 |
org.seleniumhq.selenium | htmlunit-driver | 2.23.2 | 26-Oct-2016 |
更新日付が最も新しいのはorg.seleniumhq.selenium.htmlunit-driver
のようなので、これを使ってみます。
サンプルコード
name := "crawler_sample_scala"
version := "1.0"
scalaVersion := "2.12.0"
libraryDependencies ++= Seq(
"org.seleniumhq.selenium" % "htmlunit-driver" % "2.23.2",
"org.seleniumhq.selenium" % "selenium-support" % "3.0.1",
"net.sourceforge.htmlunit" % "htmlunit" % "2.23"
)
package com.polysoft
import scala.collection.JavaConverters._
import org.openqa.selenium.htmlunit.HtmlUnitDriver
import org.openqa.selenium.{ WebElement, By }
object Crawler {
def main(args: Array[String]) = {
val url = "https://sep-ori-mokumoku-day.connpass.com/event/44613/"
crawl(url)
}
private def crawl(url: String): Unit = {
val driver = new HtmlUnitDriver()
driver.get(url)
println(s"title: ${driver.getTitle}")
val content = driver
.findElement(By.xpath("//div[contains(@class, 'event_detail_area')]"))
.getText
println(s"content: ${content}")
driver.findElements(By.xpath("//div[contains(@class, 'event_p_area')]/div"))
.asScala
.foreach{ we: WebElement =>
val member = we.findElement(By.xpath("p[@class='name']/a")).getText
println(s"member: ${member}")
}
}
}
実行すると、Scalaもくもく会のconpassのページをクローリングして、ページのタイトル、コンテンツ、および参加者の方のハンドルネーム一覧を表示します。
補足
sbtは外部ライブラリのpom.xmlに記載されている依存性を自動的に解決してくれない(?)ようで、HtmlUnitDriver
が依存しているnet.sourceforge.htmlunit.htmlunit
を持ってきてくれないため、build.sbt
のlibraryDependencies
に直接追記しました。
あまりよろしくない手法だと思うので、どなたか正しい方法をご存知の方がいらっしゃいましたら情報頂けますと幸いですm(__)m