JavaとSeleniumで自分のツイートを抽出する

今日3本目の投稿。さすがにエンジンかけすぎて疲れてきた。

次は宣言通り、こちらの記事と同じことをJavaでやります。

taikomegane.hatenablog.jp

今回のコードはこちらから
getTweet_var.java · GitHub

目次

やりたいこと

  • https://twitter.com/にアクセス
  • inputタグにユーザー名とパスワードを記入、ログイン
  • 最初のページから、マイページへ移動
  • 何もせずに出ている20ツイートくらいをテキストで抽出
  • 抽出したツイートをターミナルで表示+csv出力

前回はdockerで準備が出来ているところからのスタートだったのが、今回はSeleniumをダウンロードするところから、、辛かった

まずは下準備

今回Javaでやるには、手元でSeleniumを動かせるようにセッティングする必要がありました。

しかもPhantomJSでやるのもありかもしれないけれど、やり方よくわからないということで、Chromeで実行することに。

さらにEclipseを使わないと使えないので、そこで動くようにしてあげないといけない。

ここだけで1時間以上格闘していました。。

参考記事はこちら javaworld.helpfulness.jp

やりたい人がいるとは思えないけど、ここから必要なものはダウンロードできます。 http://www.seleniumhq.org/download/

JavaSeleniumは「Selenium Client & WebDriver Language Bindings」から、ChromeのWebDriverは「Third Party Drivers, Bindings, and Plugins」からダウンロードできます。

ちょっと余談ですが、ここで僕はzipファイルが解凍できない謎現象に襲われたので、こちらを元に解決しました。 takasumi.hatenablog.com

基本は最初の参考記事の通りにしてもらえればいいと思います。

一応、最終的なファイル構造はこんな感じ。

f:id:cyclemem:20170701194748p:plain

最後にcsv出力がしたかったのでoutputフォルダを追加しています。

実際にやってみる

1. chromeのブラウザを取得

最初に、前回PhantomJSでやっていたことをChromeでやるので、ブラウザを生成します。

//正直ちょっとよくわからないけど、ドライバの場所を教えてあげてるぽい
System.setProperty("webdriver.chrome.driver", "./driver/chromedriver");

//Webドライバを生成
WebDriver driver = new ChromeDriver();

2. Twitterにアクセス

もうStringが懐かしすぎて、いかにPythonが楽ちんに書けるかを実感する時間。

やっていることは前回と変わらず、

  • TwitterのURLを指定
  • driver.getでURLにアクセス
//Twitterにアクセス
String url = "https://twitter.com";
driver.get(url);
Thread.sleep(millis); //ちょっと休憩、今回millis=5000

結果は、こんな感じ。chromeでやってると実際にブラウザが立ち上がるので楽しい。 f:id:cyclemem:20170701195414p:plain

ただなぜかこっちだと英語版のページに飛ぶ。

余談ですが、javaでの遅延方法はこちらを参照 azuma006.hatenablog.com

3. ログインする

この辺が下準備後一番の山場でした。今まで型指定なしで取得してたから、途方にくれてたよね。

ここまでくるともうドキュメントを読み漁りながら進めるしかなく泣きながら書きました。

Generated Documentation (Untitled)

www.seleniumqref.com

こちらもやっていることは変わらず、ユーザIDとパスワードのテキストボックスを取得し、指定していた文字列をsendKeysで入力

//ユーザIDとパスワードを入力
WebElement e = driver.findElement(By.id("signin-email"));
e.clear();
e.sendKeys(user); //ユーザIDを入力

e = driver.findElement(By.id("signin-password"));
e.clear();
e.sendKeys(pass); //パスワードを入力
Thread.sleep(millis); //ちょっと休憩

記入されるとこんな感じ。実際に記入されていくのを見れるので超楽しい。 f:id:cyclemem:20170701195956p:plain

記入が確認できたらログインする。

ここで明らかに見えているのに「ログインボタンが見つからない」というエラーが。

ソースを見てみると、見えなくなっているログインボタンが上の方にあるらしく、invisibleなものは押せないというエラーのよう。というわけで今回はX-pathで指定。

//ログインボタンをクリック
e = driver.findElement(By.xpath("//*[@id='front-container']/div[2]/div[2]/form/table/tbody/tr/td[2]/button"));
e.click();
Thread.sleep(millis); //ちょっと休憩

ログイン出来たことを確認。ここからは日本語 f:id:cyclemem:20170701200145p:plain

4. マイページに移動

ここまできちゃうともう簡単。pythonのときと同じ指定でいける。

//マイページに移動
e = driver.findElement(By.cssSelector(".DashboardProfileCard-bg"));
e.click();
Thread.sleep(millis); //ちょっと休憩

f:id:cyclemem:20170701200259p:plain

5. ツイートを抽出して、コンソールに出力

ここも基本は同じ。型指定がしっかりあるので、ツイート情報はListにいれる。あとでcsv出力するために、String型でツイートをいれるArrayListも一応用意しておく。

これも余談ですが、拡張for文も最初書き方忘れてて苦しみました。python自由度高すぎる、、

//ツイート情報を取得
List<WebElement> tweetsElements = driver.findElements(By.cssSelector(".tweet-text"));

//csv出力用のリストを生成
ArrayList<String> tweets = new ArrayList<String>();

//ツイート情報から、テキストだけ取り出してコンソール出力
for (WebElement t : tweetsElements){
    String tweet = t.getText();
    tweets.add(tweet); //リストにも追加しておく
    System.out.println(tweet);
}

この結果コンソールに出力されたのがこちら f:id:cyclemem:20170701200620p:plain

いい加減見飽きてきた同じツイート群

6. csvに出力

最後にcsvファイルに出力します。ここはほとんどこの記事をぱくりました。

CSVファイルを書き出す - Javaちょこっとリファレンス

try {
            //出力先を作成する
            FileWriter fw = new FileWriter("./output/test.csv", false);
            PrintWriter pw = new PrintWriter(new BufferedWriter(fw));

            //csvの頭作成
            pw.print("tweet\n");

            //内容を指定する
            for(String tweet: tweets){
                pw.print(tweet);
                pw.println();
            }

            //ファイルに書き出す
            pw.close();

            //終了メッセージを画面に出力する
            System.out.println("出力が完了しました。");

        } catch (IOException ex) {
            ex.printStackTrace();
        }

急にtry catchでくくりだす感じにあふれ出ている。

基本さっき作ったArrayListを順番にcsvファイルに書き込むだけです。一応終わったら「出力が完了しました」と書くようになってます。

結果がこちら f:id:cyclemem:20170701200828p:plain

あとはブラウザを閉じて終わり。

まとめ

こんな感じでJavaでもSeleniumを使ってスクレイピングが出来ました。

これはそのまま業務で使えるからイイネ。ガンガン使っていこう。

正直両方やってみて、初めて使う技術はPythonでいろいろ遊んでみて、Javaでしっかり仕組み理解しながら書くってのが結構効果的な気がした。findElementでとってきてるのがWebElementだってpythonのときは意識しなかったし。

ひとまずここまで。では。