Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
何となくわかってきた Twitter API と 仲よく付き合う方法 2013.6.7 (Twitter) API 勉強会 at 恵比寿 engineyard_jp #apihack @komiya_atsushi 1
Slide 2
Slide 2 text
Agenda 1. 自己紹介 2. 今日のお話の背景 3. Twitter API と仲良く付き合うために 知っておくべき 6 つのこと 4. まとめ 2
Slide 3
Slide 3 text
1. 自己紹介 3
Slide 4
Slide 4 text
KOMIYA Atsushi @komiya_atsushi 4
Slide 5
Slide 5 text
分析力をコアとする 情報最適化企業 5
Slide 6
Slide 6 text
で Twitter API を一心不乱に、ただひたすら しばく機械学習寄りなエンジニアやってます 6
Slide 7
Slide 7 text
#TokyoWebmining 事務局 分析/機械学習/アドテク等のネタで お話していただける講師を募集中デス! 7
Slide 8
Slide 8 text
2. 今日のお話の 背景 8
Slide 9
Slide 9 text
僕と Twitter API •2010 ~ 2011 年 •Twitter API (v1) を認証なしでひたすらしばく お仕事 •特定アカウントからのフォロー・フォロワー 関係をクローリングするなど •2012 年 ~ •Twitter API (v1 → v1.1) を OAuth 認証して ただただ殴るお仕事 •ツイートを蓄積して後から参照できるように するなど 9
Slide 10
Slide 10 text
僕と Twitter API •2010 ~ 2011 年 •Twitter API (v1) を認証なしでひたすらしばく お仕事 •特定アカウントからのフォロー・フォロワー 関係をクローリングするなど •2012 年 ~ •Twitter API (v1 → v1.1) を OAuth 認証して ただただ殴るお仕事 •ツイートを蓄積して後から参照できるように するなど Twitter API を利用して 情報を蓄積したり分析したり するお仕事をしてきました 10
Slide 11
Slide 11 text
今日お話すること •主に Java (& Twitter4J) を用いてツ イートをデータベースに蓄積するに あたって •「えっ何これ? こんな仕様ドキュメント に書いてないじゃん/食い違ってるじゃ ん…」 •「こんなデータが来るとは想定していな かった…」 的なことをゆるく語っていきます 11
Slide 12
Slide 12 text
3. Twitter API と 仲良く付き合う ために知っておく べき 6 つのこと 12
Slide 13
Slide 13 text
【1】 アプリケーション の登録に注意する 13
Slide 14
Slide 14 text
アプリケーション登録時に最も注意すべきこと 14
Slide 15
Slide 15 text
アプリケーション登録時に最も注意すべきこと 15
Slide 16
Slide 16 text
アプリケーション登録時に最も注意すべきこと http://twitter.com/hogehoge Web サイトは準備中だから、 ひとまず Twitter の URL を入れておこう… 16
Slide 17
Slide 17 text
突然の Suspended!!! アプリケーション名 アカウント名 アプリケーション名 (;・∀・)ハッ? 17
Slide 18
Slide 18 text
突然の Suspended!!! アプリケーション名 アカウント名 アプリケーション名 (;・∀・)ハッ? 18
Slide 19
Slide 19 text
突然の Suspended!!! アプリケーション名 アカウント名 アプリケーション名 (;・∀・)ハッ? HTTP ステータスコード 401 メッセージ “Could not authenticate you” が返却されるようになります 19
Slide 20
Slide 20 text
それ、ヘルプセンターに書いてあるよ https://support.twitter.com/articles/438104-api 20
Slide 21
Slide 21 text
それ、ヘルプセンターに書いてあるよ https://support.twitter.com/articles/438104-api 21
Slide 22
Slide 22 text
それ、ヘルプセンターに書いてあるよ https://support.twitter.com/articles/438104-api 22
Slide 23
Slide 23 text
結論 •アプリケーション URL (Website) は ちゃんと入力しましょう •ヘルプセンターをよく読みましょう 23
Slide 24
Slide 24 text
【2】 絵文字に負けない 24
Slide 25
Slide 25 text
絵文字を含むツイート https://twitter.com/alb_komiya/status/342343210422661121 25
Slide 26
Slide 26 text
絵文字を含むツイート https://twitter.com/alb_komiya/status/342343210422661121 26 ツイートを DB に蓄積しよう とすると問題が・・・
Slide 27
Slide 27 text
MySQL 特有の事情 CREATE TABLE status( id BIGINT PRIMARY KEY ,tweet VARCHAR(140) ); 27
Slide 28
Slide 28 text
MySQL 特有の事情 CREATE TABLE status( id BIGINT PRIMARY KEY ,tweet VARCHAR(140) ); java.sql.SQLException: Incorrect string value: '...' for column 'col_name' at row 1 28
Slide 29
Slide 29 text
MySQL 特有の事情 •絵文字(Unicode 追加面の文字)を 含むテキストを DB に格納するには utf8mb4 の文字エンコーディングを指 定する必要があり •かつ、絵文字は VARCHAR 4 文字分消 費するので x 4 した桁数が必要に •参考 •http://blog.k11i.biz/2012/11/utf-8-mysql- jdbc.html 29
Slide 30
Slide 30 text
MySQL 特有の事情 CREATE TABLE status( id BIGINT PRIMARY KEY ,tweet VARCHAR(140) ) ENGINE InnoDB CHARSET utf8mb4; 30 # my.cnf (my.ini) ... [mysqld] character-set-server=utf8mb4
Slide 31
Slide 31 text
結論 •MySQL でツイートを蓄積するときは 絵文字の存在を考慮し、文字エンコー ディングと VARCAHR の桁数に注意し ましょう •CREATE TABLE (~) CHARSET utf8mb4; •character-set-server=utf8mb4 •※ツイートに限らず、「名前」や 「プロフィール」など、フリー入力欄 はすべて考慮する必要があります 31
Slide 32
Slide 32 text
【3】 ヌル文字に 負けない 32
Slide 33
Slide 33 text
再現方法は不明ですが… •ときどきツイートにヌル文字 ¥u0000 が紛れ込むことがあるようです •このようなツイートを PostgreSQL に 投入しようとすると… 33
Slide 34
Slide 34 text
再現方法は不明ですが… •ときどきツイートにヌル文字 ¥u0000 が紛れ込むことがあるようです •このようなツイートを PostgreSQL に 投入しようとすると… org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00 34
Slide 35
Slide 35 text
結論 •PostgreSQL でツイートを蓄積する場 合、ヌル文字を含むツイートは •ヌル文字を除外して取り扱う •諦める …とするのがよいでしょう 35
Slide 36
Slide 36 text
【4】 NFD/NFKD に 負けない 36
Slide 37
Slide 37 text
一見すると 140 文字に見えますが… https://twitter.com/alb_komiya/status/342528279581949952 37
Slide 38
Slide 38 text
でも実際は public static void main(String[] args) throws TwitterException { Twitter twitter = TwitterFactory.getSingleton(); Status status = twitter.showStatus(342528279581949952L); System.out.println("文字数 " + status.getText().length()); char[] chars = status.getText().toCharArray(); System.out.println(chars[0] + " / " + (int)chars[0]); System.out.println(chars[1] + " / " + (int)chars[1]); } // 出力 文字数 280 a / 97 ̈ / 776 38
Slide 39
Slide 39 text
でも実際は public static void main(String[] args) throws TwitterException { Twitter twitter = TwitterFactory.getSingleton(); Status status = twitter.showStatus(342528279581949952L); System.out.println("文字数 " + status.getText().length()); char[] chars = status.getText().toCharArray(); System.out.println(chars[0] + " / " + (int)chars[0]); System.out.println(chars[1] + " / " + (int)chars[1]); } // 出力 文字数 280 a / 97 ̈ / 776 // 出力 文字数 280 a / 97 ̈ / 776 39
Slide 40
Slide 40 text
でも実際は public static void main(String[] args) throws TwitterException { Twitter twitter = TwitterFactory.getSingleton(); Status status = twitter.showStatus(342528279581949952L); System.out.println("文字数 " + status.getText().length()); char[] chars = status.getText().toCharArray(); System.out.println(chars[0] + " / " + (int)chars[0]); System.out.println(chars[1] + " / " + (int)chars[1]); } // 出力 文字数 280 a / 97 ̈ / 776 // 出力 文字数 280 a / 97 ̈ / 776 ä が a と̈ に分解されてたー \(^o^)/ 40
Slide 41
Slide 41 text
でも実際は public static void main(String[] args) throws TwitterException { Twitter twitter = TwitterFactory.getSingleton(); Status status = twitter.showStatus(342528279581949952L); System.out.println("文字数 " + status.getText().length()); char[] chars = status.getText().toCharArray(); System.out.println(chars[0] + " / " + (int)chars[0]); System.out.println(chars[1] + " / " + (int)chars[1]); } // 出力 文字数 280 a / 97 ̈ / 776 // 出力 文字数 280 a / 97 ̈ / 776 ä が a と̈ に分解されてたー \(^o^)/ スペイン語を扱ってるとよく遭遇する? 41
Slide 42
Slide 42 text
Unicode 正規化 •等価な文字や文字の並びを統一的な内 部表現に変換することでテキストの比 較を容易にする、テキスト正規化処理 の一種 •合成:n + ~ → ñ •分解:ñ → n + ~ •参考 •http://ja.wikipedia.org/wiki/Unicode%E6%A D%A3%E8%A6%8F%E5%8C%96 42
Slide 43
Slide 43 text
「合成」しておきましょう •PostgreSQL で のような定義をしている場合は としましょう String text = Normalizer.normalize(Status.getText(), Normalizer.Form.NFKC); CREATE TABLE status( id BIGINT PRIMARY KEY ,tweet VARCHAR(140) ); 43
Slide 44
Slide 44 text
結論 •Unicode の文字合成を積極的にしま しょう •RDBMS に PostgreSQL を利用して ツイートを蓄積する場合、文字合成を しないとカラム桁数超過のエラーが 発生し得ます 44
Slide 45
Slide 45 text
【5】 user が常に在る とは限らない 45
Slide 46
Slide 46 text
search/tweets を 呼び出しているとたまに出くわします •「status[“user”] が存在しないんですけど どういうこと!?」という現象 •今まで調べてきた限りでは以下の状況で発 生するようです 1. あるユーザ @a が “ほげほげ” とつぶやく 2. ユーザ @b がそれを RT する 3. @a がアカウントを削除する(された?) 4. “ほげほげ” で search/tweets すると、 @b の RT が検索に引っかかってしまう 46
Slide 47
Slide 47 text
search/tweets を 呼び出しているとたまに出くわします •「status[“user”] が存在しないんですけど どういうこと!?」という現象 •今まで調べてきた限りでは以下の状況で発 生するようです 1. あるユーザ @a が “ほげほげ” とつぶやく 2. ユーザ @b がそれを RT する 3. @a がアカウントを削除する(された?) 4. “ほげほげ” で search/tweets すると、 @b の RT が検索に引っかかってしまう ツイートした人を表すオブジェクト 47
Slide 48
Slide 48 text
以下の書き方には要注意! QueryResult res = twitter.search(new Query().query("hoge")); for (Status s : res.getTweets()) { String userName = s.getUser().getName(); // 何かの処理… } 48
Slide 49
Slide 49 text
以下の書き方には要注意! QueryResult res = twitter.search(new Query().query("hoge")); for (Status s : res.getTweets()) { String userName = s.getUser().getName(); // 何かの処理… } ここで NullPointerException が 発生するかも \(^o^)/ 49
Slide 50
Slide 50 text
結論 •search/tweets で得られるツイートの オブジェクトでは 、status[“user”] が 存在しない可能性を考慮しましょう •null チェック必須! 50
Slide 51
Slide 51 text
【6】 Twitter の screen_name が 最大 15 文字 であるはずがない 51
Slide 52
Slide 52 text
【6】 Twitter の screen_name が 最大 15 文字 であるはずがない @~ 52
Slide 53
Slide 53 text
Twitter の仕様的には… 省略 https://support.twitter.com/articles/249172 53
Slide 54
Slide 54 text
Twitter の仕様的には… 省略 https://support.twitter.com/articles/249172 最大 15 文字 54
Slide 55
Slide 55 text
Twitter の仕様的には… 省略 https://support.twitter.com/articles/249172 最大 15 文字 のはずなのですが・・・ 55
Slide 56
Slide 56 text
実際は 56
Slide 57
Slide 57 text
実際は 16 文字ありますね… vittoriopasteris 1234567890123456 57
Slide 58
Slide 58 text
では本当の最大文字数は? https://groups.google.com/forum/#!msg/twitter-development-talk/Fff5M- CqFew/h4aVf0edm7sJ 58
Slide 59
Slide 59 text
では本当の最大文字数は? https://groups.google.com/forum/#!msg/twitter-development-talk/Fff5M- CqFew/h4aVf0edm7sJ 最大 20 文字だった時期があるらしい… 59
Slide 60
Slide 60 text
結論 •screen_name は (現行仕様では最大で 15 文字だけれども) 最大 20 文字まで 許容できるようにしましょう 60
Slide 61
Slide 61 text
4. まとめ 61
Slide 62
Slide 62 text
まとめ 1. アプリケーションの登録に注意する 2. ヌル文字に負けない 3. 絵文字に負けない 4. NFD/NFKD に負けない 5. ユーザが常に在るとは限らない 6. Twitter の screen_name が 最大 15 文字であるはずがない 62
Slide 63
Slide 63 text
ご清聴ありがとう ございました! 63