| 1 | use strict; |
|---|
| 2 | use warnings; |
|---|
| 3 | use utf8; |
|---|
| 4 | use Text::VimColor; |
|---|
| 5 | |
|---|
| 6 | use Plusen; |
|---|
| 7 | |
|---|
| 8 | my $p = Plusen->bootstrap({ |
|---|
| 9 | config => { |
|---|
| 10 | meta => { |
|---|
| 11 | title => 'acotieのドキドキPerlプログラミング', |
|---|
| 12 | author => 'acotie a.k.a Akiko yokoyama', |
|---|
| 13 | email => 'acotie <döt> acotie <at> gmail <döt> com', |
|---|
| 14 | }, |
|---|
| 15 | plugins => [ |
|---|
| 16 | { module => 'ScriptLoader::Simple' }, |
|---|
| 17 | # { module => 'Device::MozRepl', }, |
|---|
| 18 | { module => 'Device::Term', }, |
|---|
| 19 | { module => 'Device::Growl', }, |
|---|
| 20 | # { module => 'Device::ControlFromFile', config => { path => '/tmp/devsumi-ctl.txt' } }, |
|---|
| 21 | ], |
|---|
| 22 | }, |
|---|
| 23 | }); |
|---|
| 24 | |
|---|
| 25 | |
|---|
| 26 | __DATA__ |
|---|
| 27 | |
|---|
| 28 | === |
|---|
| 29 | title: はじめまして!はじめまして! |
|---|
| 30 | |
|---|
| 31 | === |
|---|
| 32 | title: 今日は初めてのyokohama.pmということで |
|---|
| 33 | |
|---|
| 34 | === |
|---|
| 35 | title: ものすごく緊張しています |
|---|
| 36 | |
|---|
| 37 | === |
|---|
| 38 | title: 一部の界隈でマニアックなファンがいる |
|---|
| 39 | |
|---|
| 40 | === |
|---|
| 41 | title: acotieです <br><img src="./acotie.jpg" WIDTH = "50%"> |
|---|
| 42 | |
|---|
| 43 | === |
|---|
| 44 | title: 尊敬するPerl Hackerの |
|---|
| 45 | |
|---|
| 46 | === |
|---|
| 47 | title: yappo氏が作った |
|---|
| 48 | |
|---|
| 49 | === |
|---|
| 50 | title: プラガブルプレゼンツール |
|---|
| 51 | |
|---|
| 52 | === |
|---|
| 53 | title: Plusenです |
|---|
| 54 | |
|---|
| 55 | === |
|---|
| 56 | title: で、本題 |
|---|
| 57 | |
|---|
| 58 | === |
|---|
| 59 | title: みなさんは自分の過去を振り返る習慣はありますか? |
|---|
| 60 | |
|---|
| 61 | === |
|---|
| 62 | title: 適度にフィードバックすることも大切です |
|---|
| 63 | |
|---|
| 64 | === |
|---|
| 65 | title: 今日は裏TwitterAPIを使ったサービスをご紹介します |
|---|
| 66 | |
|---|
| 67 | === |
|---|
| 68 | title: Twitterで特定のユーザの発言の解析 |
|---|
| 69 | |
|---|
| 70 | === |
|---|
| 71 | title: メインで使うモジュールは3つ |
|---|
| 72 | list: |
|---|
| 73 | - WWW::Mechanize |
|---|
| 74 | - XML::RSS |
|---|
| 75 | - MeCab |
|---|
| 76 | |
|---|
| 77 | === |
|---|
| 78 | title: WWW::Mechanize |
|---|
| 79 | list: |
|---|
| 80 | - httpアクセスできるモジュール |
|---|
| 81 | - LWP::UserAgenのサブクラス |
|---|
| 82 | - リンクをたどってアクセス可能 |
|---|
| 83 | - 規則的で面倒なことを代わりにしてくれる |
|---|
| 84 | - 標準入力されたユーザのRSSをページ10まで取得 |
|---|
| 85 | - API経由だと20件しか発言が取れないので強引に |
|---|
| 86 | |
|---|
| 87 | === |
|---|
| 88 | title: HTTP Access and Getting Twitter-FeedURL Code |
|---|
| 89 | code: | |
|---|
| 90 | |
|---|
| 91 | #!/usr/bin/perl |
|---|
| 92 | use strict; |
|---|
| 93 | use warnings; |
|---|
| 94 | use WWW::Mechanize; |
|---|
| 95 | |
|---|
| 96 | sub _get_twitter_rss{ |
|---|
| 97 | |
|---|
| 98 | #リンク先設定 |
|---|
| 99 | my $link_text = "RSS"; |
|---|
| 100 | |
|---|
| 101 | my $mech = new WWW::Mechanize( autocheck => 1,cookie_jar => undef ); |
|---|
| 102 | |
|---|
| 103 | # ユーザページにアクセス |
|---|
| 104 | $mech->get("http://twitter.com/$ARGV[0]"); |
|---|
| 105 | #リンクからrssをたどる |
|---|
| 106 | $mech->follow_link(text => $link_text); |
|---|
| 107 | |
|---|
| 108 | return my $url = $mech->uri(); |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | === |
|---|
| 112 | title: XML::RSS |
|---|
| 113 | list: |
|---|
| 114 | - XMLのパースを非常に楽にできるモジュール |
|---|
| 115 | - XML::Parserを使っていて、シンプルかつ定番 |
|---|
| 116 | - Date::Dumper,Smart::Comments等でデバッグ可能 |
|---|
| 117 | |
|---|
| 118 | === |
|---|
| 119 | title: Simple XML Parse Code |
|---|
| 120 | code: | |
|---|
| 121 | |
|---|
| 122 | sub main { |
|---|
| 123 | #url取得 |
|---|
| 124 | my $url = _get_twitter_rss(); |
|---|
| 125 | |
|---|
| 126 | #20post * 10page = 200post |
|---|
| 127 | for (my $i=1; $i<=10; $i++){ |
|---|
| 128 | my $next_url; |
|---|
| 129 | my $result_all; |
|---|
| 130 | |
|---|
| 131 | if (1 < $i){ |
|---|
| 132 | $next_url = $url . '?page=' . $i; |
|---|
| 133 | } |
|---|
| 134 | my $content = get($next_url); |
|---|
| 135 | |
|---|
| 136 | my $rss = new XML::RSS; |
|---|
| 137 | eval{$rss->parse($content)}; |
|---|
| 138 | |
|---|
| 139 | for my $item (@{$rss->{'items'}}) { |
|---|
| 140 | $result_all = encode('utf-8', $item->{title}); |
|---|
| 141 | |
|---|
| 142 | my ($result_id,$result_text) = split(/: /, $result_all); |
|---|
| 143 | |
|---|
| 144 | my $result = _parse_mecab($result_text); |
|---|
| 145 | ### $result |
|---|
| 146 | } |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | |
|---|
| 150 | === |
|---|
| 151 | title: MeCab (和布蕪) |
|---|
| 152 | list: |
|---|
| 153 | - Yet Another Part-of-Speech and Morphological Analyzer |
|---|
| 154 | - 形態素解析をしてくれるモジュール |
|---|
| 155 | - 奈良先端科学技術大学院大学の工藤拓氏が研究開発されている |
|---|
| 156 | - 例:ルー語変、夙川アトムなど |
|---|
| 157 | |
|---|
| 158 | === |
|---|
| 159 | title: MeCab using parse to textnode Code |
|---|
| 160 | code: | |
|---|
| 161 | |
|---|
| 162 | sub _parse_mecab{ |
|---|
| 163 | my ($txt) = @_; |
|---|
| 164 | my $mecab = new MeCab::Tagger(""); |
|---|
| 165 | my @result; |
|---|
| 166 | |
|---|
| 167 | for(my $node = $mecab->parseToNode($txt); $node; $node = $node->{next}){ |
|---|
| 168 | next if $node->{surface} eq ""; |
|---|
| 169 | |
|---|
| 170 | my @feature = split ",", $node->{feature}; |
|---|
| 171 | my $type = $feature[0]; |
|---|
| 172 | $type = Encode::decode("utf-8", $type) unless utf8::is_utf8($type); |
|---|
| 173 | my @TYPE_OK = qw/名詞 動詞 形容詞/; |
|---|
| 174 | |
|---|
| 175 | if(any { $_ eq $type } @TYPE_OK){ |
|---|
| 176 | push(@result, $node->{surface}); |
|---|
| 177 | }else{ |
|---|
| 178 | ## NG |
|---|
| 179 | #say STDERR $node->{surface}; |
|---|
| 180 | } |
|---|
| 181 | } |
|---|
| 182 | return \@result; |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | === |
|---|
| 186 | title: 実際に名詞、動詞、形容詞の単語が返ってきます |
|---|
| 187 | |
|---|
| 188 | === |
|---|
| 189 | title: ただ解析しただけではおもしろくないので |
|---|
| 190 | |
|---|
| 191 | === |
|---|
| 192 | title: 利用頻度を調べてみます |
|---|
| 193 | |
|---|
| 194 | === |
|---|
| 195 | title: 余計な単語も含まれているので、フィルタリングします |
|---|
| 196 | |
|---|
| 197 | === |
|---|
| 198 | title: Tokenized Keyword count Code |
|---|
| 199 | code: | |
|---|
| 200 | sub _process_word{ |
|---|
| 201 | my($array_ref) = @_; |
|---|
| 202 | my $hash = {}; |
|---|
| 203 | for my $word (@{ $array_ref }) { |
|---|
| 204 | |
|---|
| 205 | my $invalid_prepost = '[_\\\)\(\)"\'@:;\.\[\]/\*<>\-\!=&,\{\}\+\| 。\$\?`、「」#\^]'; |
|---|
| 206 | $word =~ s{^$invalid_prepost+}{}o; |
|---|
| 207 | $word =~ s{$invalid_prepost+$}{}o; |
|---|
| 208 | $word =~ s{^[0-9]+}{}o; |
|---|
| 209 | $word =~ s{[0-9]+$}{}o; |
|---|
| 210 | $hash->{$word}++; |
|---|
| 211 | |
|---|
| 212 | } |
|---|
| 213 | return $hash; |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | === |
|---|
| 217 | title: これで解析と集計が終わりました |
|---|
| 218 | |
|---|
| 219 | === |
|---|
| 220 | title: あとはGoogle::Chartを使ってグラフ化するだけです |
|---|
| 221 | |
|---|
| 222 | === |
|---|
| 223 | title: ちょっと時間が間に合わなくて |
|---|
| 224 | |
|---|
| 225 | === |
|---|
| 226 | title: ここの解析までできました…。すいません>< |
|---|
| 227 | |
|---|
| 228 | === |
|---|
| 229 | title: 素敵なCPANモジュールを有効活用して |
|---|
| 230 | |
|---|
| 231 | === |
|---|
| 232 | title: 人間はもっと幸せになりましょう |
|---|
| 233 | |
|---|
| 234 | === |
|---|
| 235 | title: おまけ |
|---|
| 236 | |
|---|
| 237 | === |
|---|
| 238 | title: 個人的なWish List |
|---|
| 239 | list: |
|---|
| 240 | - 仕事で早くPerlができるようにすること |
|---|
| 241 | - Plusenのシンタックスハイライト対応 |
|---|
| 242 | - 早くCPAN Authorになること |
|---|
| 243 | |
|---|
| 244 | === |
|---|
| 245 | title: no strict, no life!!(by Clouderさん) |
|---|
| 246 | |
|---|
| 247 | === |
|---|
| 248 | title: 以上。ご清聴ありがとうございました。 |
|---|
| 249 | |
|---|
| 250 | |
|---|