Upgrade to Pro — share decks privately, control downloads, hide ads and more …

何となくわかってきた Twitter API と仲良く付き合う方法 #apihack

何となくわかってきた Twitter API と仲良く付き合う方法 #apihack

6月7日(金) (Twitter) API 勉強会/API1.0告別式 @恵比寿 @engineyard_jp #apihack のトーク資料です。
http://www.zusaar.com/event/751003

E77287648aff5484ac7659748e45c936?s=128

KOMIYA Atsushi

June 07, 2013
Tweet

Transcript

  1. 何となくわかってきた Twitter API と 仲よく付き合う方法 2013.6.7 (Twitter) API 勉強会 at

    恵比寿 engineyard_jp #apihack @komiya_atsushi 1
  2. Agenda 1. 自己紹介 2. 今日のお話の背景 3. Twitter API と仲良く付き合うために 知っておくべき

    6 つのこと 4. まとめ 2
  3. 1. 自己紹介 3

  4. KOMIYA Atsushi @komiya_atsushi 4

  5. 分析力をコアとする 情報最適化企業 5

  6. で Twitter API を一心不乱に、ただひたすら しばく機械学習寄りなエンジニアやってます 6

  7. #TokyoWebmining 事務局 分析/機械学習/アドテク等のネタで お話していただける講師を募集中デス! 7

  8. 2. 今日のお話の 背景 8

  9. 僕と Twitter API •2010 ~ 2011 年 •Twitter API (v1)

    を認証なしでひたすらしばく お仕事 •特定アカウントからのフォロー・フォロワー 関係をクローリングするなど •2012 年 ~ •Twitter API (v1 → v1.1) を OAuth 認証して ただただ殴るお仕事 •ツイートを蓄積して後から参照できるように するなど 9
  10. 僕と Twitter API •2010 ~ 2011 年 •Twitter API (v1)

    を認証なしでひたすらしばく お仕事 •特定アカウントからのフォロー・フォロワー 関係をクローリングするなど •2012 年 ~ •Twitter API (v1 → v1.1) を OAuth 認証して ただただ殴るお仕事 •ツイートを蓄積して後から参照できるように するなど Twitter API を利用して 情報を蓄積したり分析したり するお仕事をしてきました 10
  11. 今日お話すること •主に Java (& Twitter4J) を用いてツ イートをデータベースに蓄積するに あたって •「えっ何これ? こんな仕様ドキュメント

    に書いてないじゃん/食い違ってるじゃ ん…」 •「こんなデータが来るとは想定していな かった…」 的なことをゆるく語っていきます 11
  12. 3. Twitter API と 仲良く付き合う ために知っておく べき 6 つのこと 12

  13. 【1】 アプリケーション の登録に注意する 13

  14. アプリケーション登録時に最も注意すべきこと 14

  15. アプリケーション登録時に最も注意すべきこと 15

  16. アプリケーション登録時に最も注意すべきこと http://twitter.com/hogehoge Web サイトは準備中だから、 ひとまず Twitter の URL を入れておこう… 16

  17. 突然の Suspended!!! アプリケーション名 アカウント名 アプリケーション名 (;・∀・)ハッ? 17

  18. 突然の Suspended!!! アプリケーション名 アカウント名 アプリケーション名 (;・∀・)ハッ? 18

  19. 突然の Suspended!!! アプリケーション名 アカウント名 アプリケーション名 (;・∀・)ハッ? HTTP ステータスコード 401 メッセージ

    “Could not authenticate you” が返却されるようになります 19
  20. それ、ヘルプセンターに書いてあるよ https://support.twitter.com/articles/438104-api 20

  21. それ、ヘルプセンターに書いてあるよ https://support.twitter.com/articles/438104-api 21

  22. それ、ヘルプセンターに書いてあるよ https://support.twitter.com/articles/438104-api 22

  23. 結論 •アプリケーション URL (Website) は ちゃんと入力しましょう •ヘルプセンターをよく読みましょう 23

  24. 【2】 絵文字に負けない 24

  25. 絵文字を含むツイート https://twitter.com/alb_komiya/status/342343210422661121 25

  26. 絵文字を含むツイート https://twitter.com/alb_komiya/status/342343210422661121 26 ツイートを DB に蓄積しよう とすると問題が・・・

  27. MySQL 特有の事情 CREATE TABLE status( id BIGINT PRIMARY KEY ,tweet

    VARCHAR(140) ); 27
  28. 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
  29. MySQL 特有の事情 •絵文字(Unicode 追加面の文字)を 含むテキストを DB に格納するには utf8mb4 の文字エンコーディングを指 定する必要があり

    •かつ、絵文字は VARCHAR 4 文字分消 費するので x 4 した桁数が必要に •参考 •http://blog.k11i.biz/2012/11/utf-8-mysql- jdbc.html 29
  30. 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
  31. 結論 •MySQL でツイートを蓄積するときは 絵文字の存在を考慮し、文字エンコー ディングと VARCAHR の桁数に注意し ましょう •CREATE TABLE

    (~) CHARSET utf8mb4; •character-set-server=utf8mb4 •※ツイートに限らず、「名前」や 「プロフィール」など、フリー入力欄 はすべて考慮する必要があります 31
  32. 【3】 ヌル文字に 負けない 32

  33. 再現方法は不明ですが… •ときどきツイートにヌル文字 ¥u0000 が紛れ込むことがあるようです •このようなツイートを PostgreSQL に 投入しようとすると… 33

  34. 再現方法は不明ですが… •ときどきツイートにヌル文字 ¥u0000 が紛れ込むことがあるようです •このようなツイートを PostgreSQL に 投入しようとすると… org.postgresql.util.PSQLException: ERROR:

    invalid byte sequence for encoding "UTF8": 0x00 34
  35. 結論 •PostgreSQL でツイートを蓄積する場 合、ヌル文字を含むツイートは •ヌル文字を除外して取り扱う •諦める …とするのがよいでしょう 35

  36. 【4】 NFD/NFKD に 負けない 36

  37. 一見すると 140 文字に見えますが… https://twitter.com/alb_komiya/status/342528279581949952 37

  38. でも実際は 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
  39. でも実際は 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
  40. でも実際は 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
  41. でも実際は 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
  42. Unicode 正規化 •等価な文字や文字の並びを統一的な内 部表現に変換することでテキストの比 較を容易にする、テキスト正規化処理 の一種 •合成:n + ~ →

    ñ •分解:ñ → n + ~ •参考 •http://ja.wikipedia.org/wiki/Unicode%E6%A D%A3%E8%A6%8F%E5%8C%96 42
  43. 「合成」しておきましょう •PostgreSQL で のような定義をしている場合は としましょう String text = Normalizer.normalize(Status.getText(), Normalizer.Form.NFKC);

    CREATE TABLE status( id BIGINT PRIMARY KEY ,tweet VARCHAR(140) ); 43
  44. 結論 •Unicode の文字合成を積極的にしま しょう •RDBMS に PostgreSQL を利用して ツイートを蓄積する場合、文字合成を しないとカラム桁数超過のエラーが

    発生し得ます 44
  45. 【5】 user が常に在る とは限らない 45

  46. search/tweets を 呼び出しているとたまに出くわします •「status[“user”] が存在しないんですけど どういうこと!?」という現象 •今まで調べてきた限りでは以下の状況で発 生するようです 1. あるユーザ

    @a が “ほげほげ” とつぶやく 2. ユーザ @b がそれを RT する 3. @a がアカウントを削除する(された?) 4. “ほげほげ” で search/tweets すると、 @b の RT が検索に引っかかってしまう 46
  47. search/tweets を 呼び出しているとたまに出くわします •「status[“user”] が存在しないんですけど どういうこと!?」という現象 •今まで調べてきた限りでは以下の状況で発 生するようです 1. あるユーザ

    @a が “ほげほげ” とつぶやく 2. ユーザ @b がそれを RT する 3. @a がアカウントを削除する(された?) 4. “ほげほげ” で search/tweets すると、 @b の RT が検索に引っかかってしまう ツイートした人を表すオブジェクト 47
  48. 以下の書き方には要注意! QueryResult res = twitter.search(new Query().query("hoge")); for (Status s :

    res.getTweets()) { String userName = s.getUser().getName(); // 何かの処理… } 48
  49. 以下の書き方には要注意! QueryResult res = twitter.search(new Query().query("hoge")); for (Status s :

    res.getTweets()) { String userName = s.getUser().getName(); // 何かの処理… } ここで NullPointerException が 発生するかも \(^o^)/ 49
  50. 結論 •search/tweets で得られるツイートの オブジェクトでは 、status[“user”] が 存在しない可能性を考慮しましょう •null チェック必須! 50

  51. 【6】 Twitter の screen_name が 最大 15 文字 であるはずがない 51

  52. 【6】 Twitter の screen_name が 最大 15 文字 であるはずがない @~

    52
  53. Twitter の仕様的には… 省略 https://support.twitter.com/articles/249172 53

  54. Twitter の仕様的には… 省略 https://support.twitter.com/articles/249172 最大 15 文字 54

  55. Twitter の仕様的には… 省略 https://support.twitter.com/articles/249172 最大 15 文字 のはずなのですが・・・ 55

  56. 実際は 56

  57. 実際は 16 文字ありますね… vittoriopasteris 1234567890123456 57

  58. では本当の最大文字数は? https://groups.google.com/forum/#!msg/twitter-development-talk/Fff5M- CqFew/h4aVf0edm7sJ 58

  59. では本当の最大文字数は? https://groups.google.com/forum/#!msg/twitter-development-talk/Fff5M- CqFew/h4aVf0edm7sJ 最大 20 文字だった時期があるらしい… 59

  60. 結論 •screen_name は (現行仕様では最大で 15 文字だけれども) 最大 20 文字まで 許容できるようにしましょう

    60
  61. 4. まとめ 61

  62. まとめ 1. アプリケーションの登録に注意する 2. ヌル文字に負けない 3. 絵文字に負けない 4. NFD/NFKD に負けない

    5. ユーザが常に在るとは限らない 6. Twitter の screen_name が 最大 15 文字であるはずがない 62
  63. ご清聴ありがとう ございました! 63