うずまき2017 powered by Jun-Systems

耳管開放症, SAS, 統計解析, 人工知能, プログラミングそれに思考

*

SASで直接twitterを検索してTLをインポート(PROC HTTP/Twitter OAuth)

   

自分の思うことが実装できず非常に悔しいですが、これは仕様なので仕方がありません。(後述)
 
SASでtwitterのAPIを叩いて、検索ワードに当たったツイートを直接データセットに落とし込みます。
Twitterの生データに自由にアクセスするには色々と障壁が大きいので、こういうプログラムをうまく自動化して必要なツイートを蓄積して研究に使うみたいなDIY精神は大事にしてゆきたいものです。
 
ちなみにうまく自動化できたら面白いと思いますが、まだ改善点が多いです。
 
今回の記事は原則的に下のページのプログラムを改良しています。
How to import Twitter tweets in SAS DATA Step using OAuth 2 authentication style – SAS Voices
 
手順
1 twitterのデベロッパ登録
2 プログラムを(ちょっと)いじる
 

1 dev登録

まず、twitter APIを触るには無料の開発者登録が必要です。
細かいことは割愛しますが、まあこの辺りのページを参考にしてください。
Twitter APIで、アプリケーションを登録する方法
 
dev登録→新規アプリケーションを作成→CONSUMER KEYとCONSUMER SECRETをコピーしておく
 

2 プログラムをちょっといじる

下準備01

%let CONSUMER_KEY=あなたのCONSUMERKEYを入れよう;
%let CONSUME_SECRET=あなたのCONSUMERSECRETを入れよう;
%let JSON_TWEET_FILE=どっかのフォルダのフルパス\ResponseContent.txt;
%let CSV_TWEET_FILE=どっかのフォルダのフルパス\sastter\ResponseContent.csv;
%let groovyPath = どっかのフォルダのフルパス\groovy-all-2.4.0.jar;
%let groovyPath2 = どっかのフォルダのフルパス\groovy-all-2.4.0.jar;どっかのフォルダのフルパス\opencsv-2.3.jar;"
%let TWEET_QUERY=Twitterの検索キーワード;

コピーしたCONSUMER KEYとCONSUMER SECRETを貼り付ける
そしてどっかのフォルダに空っぽのテキストファイルでも作って、名前をResponseContent.txtとResponseContent.csvに変える。
さらにtwitterから引っ張ってきたJSONをうまくいじくるため、groovyとopencsvをダウンロードしてきて、当該ファイルを置いた場所をgroovyPath、Path2にぶち込む。ちなみにgroovy-allもopencsvもバージョンアップしてるんですが、最新版を使ったら普通にエラーで一切動かなかったので、元プログラムぐらいのバージョンを探し当てて使うことをお勧め致します。
 
ちなみにもっと効率的な方法があるはずですが、今回の目的はとりあえずTwitterからデータを引っ張ってくる事なので、細かい仕様の不便さには目を瞑っています。それこそgroovy-allやらopencsvやらについてもPROC HTTPのgetで直接持ってこられるわけなので、気が向いたら改良します。
 

 
 /* Create a temporary file name used for the XMLMap */
 %macro tempFile( fname );
  %if %superq(SYSSCPL) eq %str(z/OS) or %superq(SYSSCPL) eq %str(OS/390) %then
    %let recfm=recfm=vb;
  %else
    %let recfm=;
  filename &fname TEMP lrecl=2048 &recfm;
 %mend;
 
 /* create temp files for the content and header input streams */
 %tempFile(in);
 %tempFile(hdrin);

一時ファイルを作るマクロ。
まあ上のファイルも究極的には一時ファイルでいいはずなんですけど。

 /* keep the response permanently */
 filename out "&JSON_TWEET_FILE.";
 
 /* post request content is the grant_type */
 data _null_;
   file in;
   put "grant_type=client_credentials&";
 run;
 
 /* request the bearer token by providing consumer key and secret */
 data _null_;
   file hdrin;
   consumerKey = urlencode("&CONSUMER_KEY.");
   consumerSecret = urlencode("&CONSUME_SECRET.");
   encodedAccessToken  = put( compress(consumerKey || ":" || consumerSecret),$base64x32767.);
   put "Authorization: Basic " encodedAccessToken;
 run;

一時ファイルにtwitterのOAuth(twitter認証)APIを使うのに必要な情報を書き込む。
 

 proc http method="post"
    in=in out=out
    headerin=hdrin
    url="https://api.twitter.com/oauth2/token"
    ct="application/x-www-form-urlencoded;charset=UTF-8";
 run;
 
 /* Store bearer token in macro variable 'BEARER_TOKEN' */
 proc groovy classpath=&groovyPath;
    submit "&JSON_TWEET_FILE.";
      import groovy.json.JsonSlurper
      def input = new File(args[0]).text
      def result = new JsonSlurper().parseText(input)
      println "Recieved bearer token: ${result.access_token}"
      exports.putAt('BEARER_TOKEN',result.access_token)
    endsubmit;
 quit;

 /* Use the bearer token as authorization */
 data _null_;
    file hdrin;
    put "Authorization: Bearer &BEARER_TOKEN.";
 run;

twitterのBearer Tokenを取得する。ここが一番引っかかってめんどくさかった。
 

 /* Search for tweets; Limit output to 100 tweets */
 proc http method="get"
    out=out headerin=hdrin
    url="https://api.twitter.com/1.1/search/tweets.json?q=&TWEET_QUERY.%NRSTR(&)count=100"
    ct="application/x-www-form-urlencoded;charset=UTF-8";
 run;

twitterから検索する。urlのところの最後のcountの数字を適当にいじって取得件数を変えてください。
ただし取得件数を増やしても、twitterはAPIの縛りがアホみたいに厳しいので、おそらく1度に100件も取得できないんじゃないかと思います。だからこそ定期的にちびちび走らせることが重要なわけであります。
 

  /* parse JSON and generate temporary CSV file */
 proc groovy classpath=&groovyPath2;
   submit "&JSON_TWEET_FILE." "&CSV_TWEET_FILE.";
      import groovy.json.*
      import au.com.bytecode.opencsv.CSVWriter
 
      def input = new File(args[0]).text
      def output = new JsonSlurper().parseText(input)
      def csvoutput = new FileWriter(args[1])
 
      CSVWriter writer = new CSVWriter(csvoutput);
 
      String[] header = new String[15];
      header[0] = "id";
      header[1] = "text";
      header[2] = "truncated";
      header[3] = "created_at";
      header[4] = "user.id";
      header[5] = "user.name";
      header[6] = "user.screen_name";
      header[7] = "user.location";
      header[8] = "user.description";
      header[9] = "user.url";
      header[10] = "user.followers_count";
      header[11] = "user.friends_count";
      header[12] = "user.listed_count";
      header[13] = "retweet_count";
      header[14] = "favorite_count";
      writer.writeNext(header);
 
      output.statuses.each {
         String[] content = new String[15];
         content[0] = it.id.toString();
         content[1] = it.text.toString();
         content[2] = it.truncated.toString();
         content[3] = it.created_at.toString();
         content[4] = it.user.id.toString();
         content[5] = it.user.name.toString();
         content[6] = it.user.screen_name.toString();
         content[7] = it.user.location.toString();
         content[8] = it.user.description.toString();
         content[9] = it.user.url.toString();
         content[10] = it.user.followers_count.toString();
         content[11] = it.user.friends_count.toString();
         content[12] = it.user.listed_count.toString();
         content[13] = it.retweet_count.toString();
         content[14] = it.favorite_count.toString();
 
         writer.writeNext(content)
      }        
 
      writer.close();
 
    endsubmit;
 quit;

  /* Import the final tweets data set */
 proc import out=work.tweets datafile="&CSV_TWEET_FILE." dbms=csv replace;
    getnames=yes;
    datarow=2;
 run;

引っ張ってきたJSONをうまくいじくってインポートする。JSONは専門外なのでここは完全にそのままプログラムを使ってます。
 

問題点

元のプログラムからそうなんですが、日本語の改行ツイートが明らかにうまくインポートできていません。
まあ改行ツイートとか害悪でしかないのでぼくはDELETEしちゃいますが、うまくインポートするやり方を発見した方はぜひご教示ください。
本当はin_reply_toのyes/noとかまで取得できるといいんですが。
 
もともとはSASで作業が終わった時点でSASをtwitterクライアントとして認証かけてtwitterに投稿する形で通知をするようなシステムを考えていたんですが、twitterのApplicationOnly Authだとその仕様の関係上、どうもstatuses/updateのAPIを使わせてもらえず投稿はできないようだということがわかりました。
まあわざわざSASからTwitterのAuthかけるなんて馬鹿らしいことをするよりも、 SASからSMTP使ってGmail送ってメールでtwitterに投稿するよな形の方が自由度が高くていいかもしれませんぬ。
 
そんな感じです。
 
 


 - SAS, SAS Programming , , , , ,

Comment

  1. […] SASで直接twitterを検索してTLをインポート(PROC HTTP/Twitter OAuth) | うずまき(3rd G… 何をしているかというと,PROC […]

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

  関連記事

no image
2014年IT関連まとめ
【忘備録】SASで巨大データセットから先頭100Obsを抽出
no image
SASのPROC SQLで一括操作(変数名の変更 / ダミー変数操作など)
SASでカテゴリカルな変数をダミー変数化するマクロ
no image
データ分析の重要性とオープンデータ活用の潮流
no image
SASのPROC HTTPでe-statのAPIを叩く(叩くだけ)
no image
SAS上で走っているRとSASでのデータセットの受け渡し
no image
SASでウェブ上のcsvファイルを直接読み込む
SAS超基礎1 データの読み書き
no image
SAS上でRを走らせよう SAS/IML