エンジニアtypeさんの連載:ギークな女子会 acotie編の原稿について補足と私信
http://engineer.typemag.jp/brightw/2011/07/-acotie.php の補足と私信です。
思いのほか長くなってしまったので、一部の方以外はスルーしてください><
今回のエントリーを書くに至った経緯、ごく一部の方に誤解を招くような表現
エンジニアtypeさんで座談会企画をさせて頂いた内容ですが、実際に私がドワンゴで働いていなかったような表現になっているのは事実です。
時間の制約がある中で、私が元ドワンゴ社員ということは自己紹介の際にも、取材中にも編集部の方にも何度もお伝えしましたし
実際には全面的にドワンゴの開発部の内情を知った上でつっ込んだ内容の話や質問もしていました。*1
しかし編集の方が必要ないと判断されたのか内容がバッサリ消されていたり、編集部の方が質問した内容が私が言ったようにすり変えられていました。
結果的にできあがった原稿全体の流れとして、非常によそよそしい内容となってしまいました。
あとはコンテンツの強調するポイントにもすこし疑問を感じる部分もありますが、編集部の方もお仕事でPVを稼ぐコンテンツとして必要な要素であり
多少の文章の改変や誇張は必要なのがメディアというものなのかなと思い、表向きには今まで特になにも言及せずにいました*2。
そして先日お会いした方々に「エンジニアtypeの記事に対して、あたかもacotieがドワンゴで働いていなかったことになっているので、元上司が心を痛めていた」という旨を伝えられ、なんだか複雑な心境になりました。
すぐに今回の経緯と感謝の気持ちを改めて伝えようと、このエントリーを書くことを決意しました。
ドワンゴ在籍時の振り返り
わたしは2008年の初旬に元上司とネット上で知り合い、偶然にもnipotan niteの二次会で初めてお会いし
2008年5月にいろいろあって気持ちがどん底になりながら転職を探している際にTwitter経由でドワンゴに誘って頂きました。
在籍中は本当にずっとお世話になりっぱなしでしたし、今では考えられないほど自己中心的とも言えるような行動を会社でしていました。
非常識極まりない行動に対しても特に怒られなかったですし、むしろ気持ちを理解しようと一生懸命努力し、いつも笑顔と寛大な心で受け入れてくれました。
当時はきっと上司の優しさにどこまでも甘えていたのだと思います。思いますというより周囲にも自分にも甘えていました。
退職後、迷惑ばかりかけた上にろくに成果も出さずに辞めたことを後悔することが多々ありました。
今でも元上司には顔向けできないですし、申し訳ない気持ちでいっぱいです。
1年と数ヶ月間という短い間でしたが、たくさんの方々にお世話になり、私にとって本当にかけがえのない時間です。
特に今でも元上司のことは尊敬していますし、優秀な方々と一緒に働けて本当に光栄でした。
すこしだけ成長できたのもドワンゴという会社、上司や同僚のおかげですし、本当にすごく感謝しています。
これは後からとってつけたフォローではなく、今までずっと言葉にしてこなかった本心です。
あくまでも私信
ぜんぜん知らない第三者が記事を見る上では、全くドワンゴを知らないふりをして質問している形にして頂いても構わないのですが
一部のお世話になった方々に対して誤解を招くような結果となってしまいましたので、このような拙い文章を書きました。
けっして企画のあり方や編集の仕方についての提言をしているわけではありません。事前に原稿も確認した上で了承しています。
重ねて言いますが、今回の記事の内容が全体的によそよそしい内容になってしまったということに関して、誤解を解きたいと考えています。
不特定多数の方が閲覧ができるウェブの媒体で、特定の方・お世話になった方が心を痛めることは不本意であり残念で悲しいです。
今回の件は、私がもうすこし原稿確認の段階で配慮するべきであったと反省しております。
今後の活動を通してなにか還元できるように、前向きに行動し、地に足をつけながら毎日楽しくプログラミングをして過ごしています。
すこし過去を振り返ってみても、現在まわりを見回しても、やはり人とのご縁にだけは本当に恵まれでいるとしか言いようがありません。
このようなオープンな形式でしか伝えられませんでしたが、もしいつか謝罪と感謝の気持ちを直接述べる機会を頂けるようであれば、私は非常に嬉しく思います。
エンジニアtypeさんで連載:ギークな女子会が公開になりました(すこし裏話
本日付けでエンジニアtypeさんでの連載記事が公開になりました。
先日、開発者としてエンジョイされている@shokosこと佐々木 抄子(ささき しょうこ)さんと@purewishこと韓 松熙(はん そんひ)さんと一緒にお話しさせて頂く機会がありました。
担当の1回目というのもあり、面識があるお二人しかいない!*1と思って、ドキドキしながら声をかけさせて頂きました。(元同僚・Perlつながりメソッド)
佐々木さん、韓さんの印象
間違いなくお二人とも意識的なレベルも高く、問題をいかにクリアするか、いかに学習できるかということを常に考え、楽しくお仕事をされているといった印象を受けました。
現在の会社の働く環境(まわりの人達、開発環境、社風など)がいかに恵まれているか、といえばそれに集約されるのかもしれませんが
その言葉だけでは片付けられないような上手くいく発想、取り組み方といった秘訣も多々あり、すごく勉強になりました。*2
モチベーションとなっているもの
こういう取材的なものが得意ではないのですが、もっとがんばってる人が前に出て評価される業界であってほしいということと
わりとストイックな感じのエンジニアもいるんだねーという印象づけをすることによって
もっともっとネット上のおもしろい人達がカジュアルに前に出やすくなるようなきっかけになれば幸いです。
どうでもいいですが、カップルでエンジニアというのもちょっとだけうらやましいですね。
それから、みんな白い服なのはドレスコードだからです(ウソ
今後も「ギークなお姉さん」こと、べにぢょさん(@lovecallさん)と交互に公開されていきますので、楽しみにしてくださいね!
下記のリンクから過去のアーカイブが見れます。
べにぢょ&acotieとギークな女子会❤ | 輝け!女子部 | エンジニアtype - エンジニアのシゴト人生を考えるWebマガジン
Smiley Hackathon#10のお知らせ
またしても告知です。苦手な方はスルーしてください!
おかげさまで日本で一番ゆるいイベントとなりつつある Smiley Hackathonも10回目になりました!
エンジニアの為のスキル向上の為の不定期もくもくイベントです。
ハッカソンというと非常にとっつきにくいイメージですが、ルールや言語のしばりは一切ありません。
プログラミングが好きな方、これから勉強しようと思っている方、興味があれば全然OKです。
今回も株式会社ガイアックス様に会場を提供して頂ける事になりました。心からお礼を申し上げます。
2011/7/2(土) 13:00〜20:00 @ガイアックスさん
↓ ご応募はatndにて受け付けています! ↓
過去の実績や振り返り
もとはといえば私がガリガリとコードを書きたい!という自己中的な発想のもと始めたイベントですが、
それなりに過去にちゃんとアウトプットされていらっしゃる参加者も多いです。
実際に参加された方の声
これは去年の#9の時にg177564さんがつぶやかれてたpostのようです。
そこまでビックリするくらい、ゆるーーーーーーーくアピールしたつもりはないのですが、たしかに毎回雑な終わり方で反省しています><
http://twitter.com/g177564/statuses/21127146102
今年の4月頃?にid:sugyan氏がつぶやかれていたpostのようです。ぐぐって知りました。
色んな言語好きな方がいらっしゃると勉強になるのは事実です。意図するところが同じでうれしいですw
すぎゃーん💯 on Twitter: "個人的にSmiley Hackathonはすごい良いなーと思っていて、言語やレベル問わずコード書きたいヒトが集まって好き勝手書きながら分からないこととか周りで訊けるヒトいれば訊いて、と。…そういうのがもっと頻繁に色んなところで開催されるようになればいいなと思ってる"
2011/06/25 追記
いつの間にか定員超えていました。どうもありがとうございます!
会場のキャパ的には全然オーバーしても大丈夫ですので、興味のある方はぜひ参加してみてくださいね^^;
IBM DB2の記事が公開になりました
こんにちは!やたら多い転職回数を活かして、未経験者にweb系エンジニアへの転職アドバイス的なボランティアもしているacotieです。
実は東日本大震災以前にほぼ完了しておりました、IBM DB2のはてブPR記事が2011年5月23日付けで公開されています。
今回は、個人としても尊敬している株式会社はてなの中の方に声を掛けて頂いたというのも非常に感慨深いです。
Perl好きの女性Webエンジニア二人がIBM DB2を試してみた - はてなブックマークニュース
意外とちがったIBM社の雰囲気
DB2のスペシャリストの方々に直接レクチャーして頂く機会というのは、なかなか経験できない貴重なものです。
もちろん台本もなく、話の内容とマッチするのか非常にドキドキしていましたが
非常に丁寧に進めて頂いたり教えて頂いたおかげで、終始和やかな雰囲気であっという間に時間が過ぎました。
事前にDB2 Express-CをMacにインストールし、DB2 9.7 エバリュエーション・ガイドブックを献本頂き、勉強する期間がありました。
DB2 9.7 エバリュエーション・ガイドブックには概念的からDB2 Express-Cのインストール、pureXMLとよばれるXMLデータを取り扱う機能についてや
ハイブリッド・データベースと呼ばれる事柄について詳しく説明があり、すんなりと理解することができました。
- 作者: 日本アイ・ビー・エム
- 出版社/メーカー: 翔泳社
- 発売日: 2009/07/14
- メディア: 大型本
- 購入: 25人 クリック: 247回
- この商品を含むブログ (6件) を見る
レクチャーの内容も無料でDB2がインストールができること、XQueryと呼ばれるXPathを使ったSQL文でアクセスしてみたり、自動チューニングの箇所、個人でのチューニング方法であったり、初めて知ったことが沢山ありました。
DB管理者必見の本が好評発売中
また記事の中で登場される下佐粉昭さんは、著書の「即戦力のDB2管理術 〜仕組みからわかる効率的管理のノウハウ」という本が4月8日に発売されたばかりです!
エキスパートな方から見た実践的なDB2の管理方法や、具体的な方法論やTipsが満載で必見です。
- DBのバックアップの方法
- プロセス/メモリ/ディスク監視方法
- トランザクションなどのパフォーマンス監視
- 実際に起こり得るトラブル解決の為の対処法
- パフォーマンスチューニング
- ベンチマーク
- アクセスプランの確認
- メモリ関連のパラメータの調整方法
- ディスクアクセス自体の高速化など
個人的に第4部 (P.264〜P.409) のパフォーマンスチューニングの章は分かりやすく勉強になりますし、
DB2ではなくてもDB全般の教科書として使えるような内容で感動しました。
即戦力のDB2管理術 ?仕組みからわかる効率的管理のノウハウ
- 作者: 下佐粉昭
- 出版社/メーカー: 技術評論社
- 発売日: 2011/04/08
- メディア: 単行本(ソフトカバー)
- 購入: 3人 クリック: 13回
- この商品を含むブログ (6件) を見る
またIBMの方々も技術者とコミュニケーションを欲していること(全然ツンではない)、定期的にClub DB2という勉強会を開催されていること
有効な広告宣伝として "はてな"という広告媒体を選択されたこと、歴史ある有名な企業もソーシャルな広告の方にシフトされているんだなぁ、と色々と印象的でした。
id:aomushi510さん、はてなのid:mtakanoさん、id:rikoさん、IBMさんの中林紀彦さん、下佐粉昭さん、IBMさんの関連の方々、このような機会を頂きまして本当にありがとうございます。
近況とゆるやかな募集
あと全然関係ないですが、横山と仕事してやってもいいよ!という会社さんをすごくゆるやかに募集しています。
有難いことに複数の会社の方に声を掛けて頂いてはいるものの、諸事情の関係上まだお会いして具体的な話はしていない状況です。
ご挨拶ができていない方も多いのですが、昨年の年明けからフリーランスとしてお仕事させて頂いております。
ここ2年間ほど大きな飲み会やオフ会などに全く参加しなくなった為、疎遠になっていると感じられている方も多いかもしれません。
というのも昔からメールやDM不精かつ自分からメールや連絡をあまりしないタイプで受身な人間な為
反省し言い訳をなくすために色々と行動を変えようとしている最中です。
お世話になった方や挨拶をしたい方も沢山います。
お世話になった方々にひとりひとり何かおいしいゴハンでもご馳走させてほしいです。そして次は奢ってほしいですw
直近ではNDAの関係で言えませんが、Perlを使った大手のwebサービスの開発をしたりしています。
個人では、AIR for Androidで軽くAndroidアプリ作ったり、iPhoneアプリもTitaniumとかUnity3dやcocos2dとか超入門中の身です。
Smiley Hackathonやwebrick cafeについては、近日中にまたよいご報告ができるかと思います。
都内近郊であれば、仕事じゃなくても軽くランチやお茶したい!とかお話ししてみたい!という方も声掛けてくださるとうれしいです^^;
WEB+DB PRESS Vol.61のPerl Hacker Hub 第7回 「新人さんのための仕事で使えるPerl基礎知識」を寄稿しました
2011/2/24より技術評論社さんから発売される、WEB+DB PRESS Vol.61のPerlリレー連載のPerl Hacker Hub第7回、「新人さんのための仕事で使えるPerl基礎知識」を寄稿しました。
ざっくり内容
前半はPerlの世界でデファクトスタンダーとになりつつある最新の環境構築について、cpanm + perlbrewを紹介させて頂きました。
後半はPerlをはじめて今まで、個人的に苦手だった箇所・つまづきやすい部分などを中心に書きました。
どうしてこのテーマだったのか
きっと同じようにつまずいている方や苦手意識を持っている方は本当に沢山いらっしゃると思いますし、実際によく質問されたりする箇所でもあります。
この連載自体が錚々たる顔ぶれの中、恐れ多くも内容について真剣に考えた結果、オリジナリティあふれる独自の内容になったように思います。
ぜひこれからPerlをはじめたいと思われている方や、今も勉強されている方などに読んで頂きたいです!!*1
主な内容は以下の通りです :D
さいごに
編集長をはじめ、編集部の方々、牧さん、大沢さん、アドバイスやご指摘など、ご協力頂きましてありがとうございます。
そして今後ともよろしくお願い致します。
- 作者: 西岡祐弥,濱田章吾,横山彰子,浜本階生,ミック,uupaa,塙与志夫,はまちや2,大沢和宏,中島聡,矢野りん,中島拓,浦嶌啓太,角田直行,佐々木一,倉井龍太郎,深町英太郎,岩永賢明,高橋健一,柴田博志,井上誠一郎,大谷弘喜,荻野淳也,原悠,増井俊之,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2011/02/24
- メディア: 大型本
- 購入: 37人 クリック: 2,058回
- この商品を含むブログ (38件) を見る
AKB48のメンバー情報を取得するスクリプト
WEB::Scraperを使い、各チームのメンバーの一覧の名前、写真、詳細ページURLが取ってみました。
Acme::AKB48みたいに、リンクをたどって常に最新データを動的に作れるようになれるようにしたいなと思います。
2010年の年末から研究生が昇格して56人なんですけどねー。
#!/opt/local/bin/perl use strict; use Web::Scraper; use URI; use yaml; my $uri = URI->new("http://www.dmm.com/akb48/-/akb48member/"); my $scraper = scraper { process '/html/body/table/tr/td[2]/div/div[4]/a', 'TeamA[]' => scraper{ process "img", name => '@alt', image => ['@src', sub{ $_->as_string}]; process "a", link => [ '@href', sub{ $_->as_string}]; }; process '/html/body/table/tr/td[2]/div/div[7]/a', 'TeamK[]' => scraper{ process "img", name => '@alt', image => ['@src', sub{ $_->as_string}]; process "a", link => [ '@href', sub{ $_->as_string}]; }; process '/html/body/table/tr/td[2]/div/div[10]/a', 'TeamB[]' => scraper{ process "img", name => '@alt', image => ['@src', sub{ $_->as_string}]; process "a", link => [ '@href', sub{ $_->as_string}]; }; process '/html/body/table/tr/td[2]/div/div[13]/a', 'Kenkyusei[]' => scraper{ process "img", name => '@alt', image => ['@src', sub{ $_->as_string}]; process "a", link => [ '@href', sub{ $_->as_string}]; }; }; my $result = $scraper->scrape($uri);
output
--- TeamA: - image: http://pics.dmm.com/digital/akb48/list/iwasa_misaki.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=49/ch_navi=akb48member/sort=date/ name: 岩佐美咲 - image: http://pics.dmm.com/digital/akb48/list/oota_aika.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=17/ch_navi=akb48member/sort=date/ name: 多田愛佳 - image: http://pics.dmm.com/digital/akb48/list/ooya_sizuka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=51/ch_navi=akb48member/sort=date/ name: 大家志津香 - image: http://pics.dmm.com/digital/akb48/list/katayama_haruka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=19/ch_navi=akb48member/sort=date/ name: 片山陽加 - image: http://pics.dmm.com/digital/akb48/list/kuramoti_asuka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=38/ch_navi=akb48member/sort=date/ name: 倉持明日香 - image: http://pics.dmm.com/digital/akb48/list/kozima_haruna.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=5/ch_navi=akb48member/sort=date/ name: 小嶋陽菜 - image: http://pics.dmm.com/digital/akb48/list/sasihara_rino.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=22/ch_navi=akb48member/sort=date/ name: 指原莉乃 - image: http://pics.dmm.com/digital/akb48/list/sinoda_mariko.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=8/ch_navi=akb48member/sort=date/ name: 篠田麻里子 - image: http://pics.dmm.com/digital/akb48/list/takazyou_aki.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=9/ch_navi=akb48member/sort=date/ name: 高城亜樹 - image: http://pics.dmm.com/digital/akb48/list/takahasi_minami.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=10/ch_navi=akb48member/sort=date/ name: 高橋みなみ - image: http://pics.dmm.com/digital/akb48/list/nakagawa_haruka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=24/ch_navi=akb48member/sort=date/ name: 仲川遥香 - image: http://pics.dmm.com/digital/akb48/list/nakata_tisato.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=11/ch_navi=akb48member/sort=date/ name: 中田ちさと - image: http://pics.dmm.com/digital/akb48/list/nakaya_sayaka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=26/ch_navi=akb48member/sort=date/ name: 仲谷明香 - image: http://pics.dmm.com/digital/akb48/list/maeda_atuko.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=13/ch_navi=akb48member/sort=date/ name: 前田敦子 - image: http://pics.dmm.com/digital/akb48/list/maeda_ami.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=62/ch_navi=akb48member/sort=date/ name: 前田亜美 - image: http://pics.dmm.com/digital/akb48/list/matubara_natumi.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=45/ch_navi=akb48member/sort=date/ name: 松原夏海 TeamB: - image: http://pics.dmm.com/digital/akb48/list/isida_haruka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=47/ch_navi=akb48member/sort=date/ name: 石田晴香 - image: http://pics.dmm.com/digital/akb48/list/oku_manami.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=35/ch_navi=akb48member/sort=date/ name: 奥真奈美 - image: http://pics.dmm.com/digital/akb48/list/kasai_tomomi.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=37/ch_navi=akb48member/sort=date/ name: 河西智美 - image: http://pics.dmm.com/digital/akb48/list/kasiwagi_yuki.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=18/ch_navi=akb48member/sort=date/ name: 柏木由紀 - image: http://pics.dmm.com/digital/akb48/list/kitahara_rie.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=4/ch_navi=akb48member/sort=date/ name: 北原里英 - image: http://pics.dmm.com/digital/akb48/list/kobayasi_kana.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=39/ch_navi=akb48member/sort=date/ name: 小林香菜 - image: http://pics.dmm.com/digital/akb48/list/komori_mika.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=54/ch_navi=akb48member/sort=date/ name: 小森美果 - image: http://pics.dmm.com/digital/akb48/list/satou_amina.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=6/ch_navi=akb48member/sort=date/ name: 佐藤亜美菜 - image: http://pics.dmm.com/digital/akb48/list/satou_sumire.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=56/ch_navi=akb48member/sort=date/ name: 佐藤すみれ - image: http://pics.dmm.com/digital/akb48/list/satou_natuki.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=40/ch_navi=akb48member/sort=date/ name: 佐藤夏希 - image: http://pics.dmm.com/digital/akb48/list/suzuki_mariya.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=58/ch_navi=akb48member/sort=date/ name: 鈴木まりや - image: http://pics.dmm.com/digital/akb48/list/tikano_rina.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=59/ch_navi=akb48member/sort=date/ name: 近野莉菜 - image: http://pics.dmm.com/digital/akb48/list/hirazima_natumi.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=28/ch_navi=akb48member/sort=date/ name: 平嶋夏海 - image: http://pics.dmm.com/digital/akb48/list/masuda_yuka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=44/ch_navi=akb48member/sort=date/ name: 増田有華 - image: http://pics.dmm.com/digital/akb48/list/miyazaki_miho.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=15/ch_navi=akb48member/sort=date/ name: 宮崎美穂 - image: http://pics.dmm.com/digital/akb48/list/watanabe_mayu.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=30/ch_navi=akb48member/sort=date/ name: 渡辺麻友 TeamK: - image: http://pics.dmm.com/digital/akb48/list/akimoto_sayaka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=31/ch_navi=akb48member/sort=date/ name: 秋元才加 - image: http://pics.dmm.com/digital/akb48/list/itano_tomomi.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=1/ch_navi=akb48member/sort=date/ name: 板野友美 - image: http://pics.dmm.com/digital/akb48/list/utida_mayumi.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=48/ch_navi=akb48member/sort=date/ name: 内田眞由美 - image: http://pics.dmm.com/digital/akb48/list/umeda_ayaka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=32/ch_navi=akb48member/sort=date/ name: 梅田彩佳 - image: http://pics.dmm.com/digital/akb48/list/oosima_yuuko.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=33/ch_navi=akb48member/sort=date/ name: 大島優子 - image: http://pics.dmm.com/digital/akb48/list/kikuti_ayaka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=53/ch_navi=akb48member/sort=date/ name: 菊地あやか - image: http://pics.dmm.com/digital/akb48/list/tanabe_miku.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=23/ch_navi=akb48member/sort=date/ name: 田名部生来 - image: http://pics.dmm.com/digital/akb48/list/nakatuka_tomomi.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=25/ch_navi=akb48member/sort=date/ name: 中塚智実 - image: http://pics.dmm.com/digital/akb48/list/nitou_moeno.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=27/ch_navi=akb48member/sort=date/ name: 仁藤萌乃 - image: http://pics.dmm.com/digital/akb48/list/nonaka_misato.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=60/ch_navi=akb48member/sort=date/ name: 野中美郷 - image: http://pics.dmm.com/digital/akb48/list/huzie_reina.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=12/ch_navi=akb48member/sort=date/ name: 藤江れいな - image: http://pics.dmm.com/digital/akb48/list/matui_sakiko.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=63/ch_navi=akb48member/sort=date/ name: 松井咲子 - image: http://pics.dmm.com/digital/akb48/list/minegisi_minami.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=14/ch_navi=akb48member/sort=date/ name: 峯岸みなみ - image: http://pics.dmm.com/digital/akb48/list/miyazawa_sae.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=46/ch_navi=akb48member/sort=date/ name: 宮澤佐江 - image: http://pics.dmm.com/digital/akb48/list/yokoyama_yui.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=136/ch_navi=akb48member/sort=date/ name: 横山由依 - image: http://pics.dmm.com/digital/akb48/list/yonezawa_rumi.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=29/ch_navi=akb48member/sort=date/ name: 米沢瑠美 Kenkyusei: - image: http://pics.dmm.com/digital/akb48/list/abe_maria.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=150/ch_navi=akb48member/sort=date/ name: 阿部マリア - image: http://pics.dmm.com/digital/akb48/list/izuta_rina.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=151/ch_navi=akb48member/sort=date/ name: 伊豆田莉奈 - image: http://pics.dmm.com/digital/akb48/list/itikawa_miori.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=152/ch_navi=akb48member/sort=date/ name: 市川美織 - image: http://pics.dmm.com/digital/akb48/list/iriyama_anna.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=153/ch_navi=akb48member/sort=date/ name: 入山杏奈 - image: http://pics.dmm.com/digital/akb48/list/usikubo_sara.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=160/ch_navi=akb48member/sort=date/ name: 牛窪紗良 - image: http://pics.dmm.com/digital/akb48/list/ooba_mina.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=126/ch_navi=akb48member/sort=date/ name: 大場美奈 - image: http://pics.dmm.com/digital/akb48/list/katou_rena.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=155/ch_navi=akb48member/sort=date/ name: 加藤玲奈 - image: http://pics.dmm.com/digital/akb48/list/kanazawa_yuuki.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=156/ch_navi=akb48member/sort=date/ name: 金沢有希 - image: http://pics.dmm.com/digital/akb48/list/kawaei_rina.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=161/ch_navi=akb48member/sort=date/ name: 川栄李奈 - image: http://pics.dmm.com/digital/akb48/list/kozima_natuki.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=162/ch_navi=akb48member/sort=date/ name: 小嶋菜月 - image: http://pics.dmm.com/digital/akb48/list/kobayasi_marina.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=157/ch_navi=akb48member/sort=date/ name: 小林茉里奈 - image: http://pics.dmm.com/digital/akb48/list/simazaki_haruka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=128/ch_navi=akb48member/sort=date/ name: 島崎遥香 - image: http://pics.dmm.com/digital/akb48/list/simada_haruka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=137/ch_navi=akb48member/sort=date/ name: 島田晴香 - image: http://pics.dmm.com/digital/akb48/list/suzuki_sihori.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=57/ch_navi=akb48member/sort=date/ name: 鈴木紫帆里 - image: http://pics.dmm.com/digital/akb48/list/takeuti_miyu.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=130/ch_navi=akb48member/sort=date/ name: 竹内美宥 - image: http://pics.dmm.com/digital/akb48/list/nakamata_siori.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=158/ch_navi=akb48member/sort=date/ name: 仲俣汐里 - image: http://pics.dmm.com/digital/akb48/list/nakamura_mariko.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=132/ch_navi=akb48member/sort=date/ name: 中村麻里子 - image: http://pics.dmm.com/digital/akb48/list/nagao_mariya.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=131/ch_navi=akb48member/sort=date/ name: 永尾まりや - image: http://pics.dmm.com/digital/akb48/list/natori_wakana.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=163/ch_navi=akb48member/sort=date/ name: 名取稚菜 - image: http://pics.dmm.com/digital/akb48/list/huzita_nana.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=159/ch_navi=akb48member/sort=date/ name: 藤田奈那 - image: http://pics.dmm.com/digital/akb48/list/mori_anna.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=134/ch_navi=akb48member/sort=date/ name: 森杏奈 - image: http://pics.dmm.com/digital/akb48/list/morikawa_ayaka.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=164/ch_navi=akb48member/sort=date/ name: 森川彩香 - image: http://pics.dmm.com/digital/akb48/list/yamauti_suzuran.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=135/ch_navi=akb48member/sort=date/ name: 山内鈴蘭 - image: http://pics.dmm.com/digital/akb48/list/yamaguti_nau.jpg link: http://www.dmm.com/akb48/-/list/=/article=akb48member/id=165/ch_navi=akb48member/sort=date/ name: 山口菜有
Mashup Award6で小飼弾さんの 404 API Not Found賞を授賞しました
先日作ったPythonのFlask製アプリ、オンラインコード共有ツール codetype.orgが審査員特別賞を授賞しました。
授賞作品の中では一番地味だと言えるサービスです。
TwitterのOAuthを利用してログインをし、プログラミングのコードを貼り付けてオンライン上で実行結果がわかる・共有できるというものです。
もともと9月に女性エンジニアとしてMashup Caravan Girls Talkでプレゼンをさせて頂いたのですが
そのデモアプリとして動く物を1週間くらいでざっくり作ったのがきっかけです。
その当時は弾さんのAPIは提供企業として正式なものではありませんでした。
それがプレゼンから1ヶ月後くらいの10月半ばに、弾さんのAPIが特別審査員として正式に提供することになったようです。
真面目に授賞できるだなんて思っていなくて、私自身でもすごくビックリしていますし、嬉しいのと恥ずかしいのが入り交じっている感覚です。
弾さんから弾さんの著書 & 弾言に弾さんのサインも頂きました。あリがとうございます!!
授賞式の様子。恐縮しすぎて笑顔がおかしい。
source: http://weekly.ascii.jp/elem/000/000/029/29236/
システム的にも雑な部分がたくさんあります。
さくらの500円サーバーでマルチドメインとして動いているため、全然費用がかかっていないです。
弾さんのllevalのAPIから返ってくるレスポンスをごそっとjson形式のままDBに保存しています。
制作/開発時間
今回のサービスは学習込みで全部で30時間くらいかけて作りました。
- ざっくりとしたサンプルベースの雛形5時間
- OAuth対応、lleval対応、ユーザ登録、syntax highlight対応、 10時間
- テンプレート化 10時間
- fork機能、レイアウト微調整、Twitterにpost機能、バナー作成、その他細かいところ 5時間
codetypeの主な機能
- Twitterのアカウントでログインができる
- コードが貼りつけて公開できる
- 実行した結果がオンライン上で確認できる
- http://codetype.org/aNfJJREpTu などオリジナルのURLでシェアできる
- コメントができる
- 既存のコードをベースにフォークできる
- ユーザ名は非公開
あたらしいことにチャレンジしたこと
- Pythonでなにか作りたい
- OAuthの仕組みを利用してなにか作りたい
- 個人ではじめてきちんとサービスとして公開した
- コンテスト的なものに初めて応募
コードも晒します
create_table.sql
CREATE TABLE users ( id integer primary key autoincrement, twitter_id int not null, name string not null, oauth_token string not null, oauth_secret string not null, date string null ); CREATE TABLE entries ( id integer primary key autoincrement, title string null, text string not null, author string not null, hash string not null, tag string null, lang string null, date string null, dan string null ); CREATE TABLE comments ( id integer primary key autoincrement, text string not null, entry_id int null, user_id int null, date string null );
~/src/flaskr/flaskr.py
# -*- coding: utf-8 -*- """ Flaskr ~~~~~~ A microblog example application written as Flask tutorial with Flask and sqlite3. :copyright: (c) 2010 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ from __future__ import with_statement import sqlite3 from contextlib import closing from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash, escape from flaskext.oauth import OAuth from markdown import markdown import random import string import datetime import sys import os from pprint import pprint import urllib from flask import json oauth = OAuth() twitter = oauth.remote_app('twitter', base_url='http://api.twitter.com/1/', request_token_url='http://api.twitter.com/oauth/request_token', access_token_url='http://api.twitter.com/oauth/access_token', authorize_url='http://api.twitter.com/oauth/authorize', consumer_key='[consumer_key]', consumer_secret='[consumer_secret]' ) # configuration DATABASE = '/home/acotie/src/flaskr/flaskr.db' DEBUG = True SECRET_KEY = '[SECRET_KEY]' USERNAME = '' PASSWORD = '' # create our little application :) app = Flask(__name__) app.config.from_object(__name__) app.config.from_envvar('FLASKR_SETTINGS', silent=True) default_lang = { 'perl': 'pl', 'perl6': 'p6', 'awk': 'awk', 'basic': 'bas', 'brainfuck': 'bf', 'c': 'c', 'elisp': 'el', 'lisp': 'lsp', 'scheme': 'scm', 'haskell': 'hs', 'io': 'io', 'javascript': 'js', 'lua': 'lua', 'm4': 'm4', 'ocaml': 'ml', 'php': 'php', 'python': 'py', 'python3': 'py3', 'ruby': 'rb', 'ruby19': 'rb19', 'postscript': 'ps', 'tcl': 'tcl', } def query_db(query, args=(), one=False): cur = g.db.execute(query, args) rv = [dict((cur.description[idx][0], value) for idx, value in enumerate(row)) for row in cur.fetchall()] return (rv[0] if rv else None) if one else rv def random_str(self, length = 10): ret = "" for i in range(length): ret += random.choice(string.ascii_letters) return ret def connect_db(): """Returns a new connection to the database.""" return sqlite3.connect(app.config['DATABASE']) def init_db(): """Creates the database tables.""" with closing(connect_db()) as db: with app.open_resource('schema.sql') as f: db.cursor().executescript(f.read()) db.commit() @app.before_request def before_request(): """Make sure we are connected to the database each request.""" g.db = connect_db() g.user = None if 'user_id' in session: g.user = query_db('select * from users where twitter_id = ?', [session['user_id']], one=True) @app.after_request def after_request(response): """Closes the database again at the end of the request.""" g.db.close() return response @twitter.tokengetter def get_twitter_token(): #return session.get('twitter_token') user = g.user if user is not None: return user.oauth_token, user.oauth_secret @app.route('/') def show_entries(): cur = g.db.execute('select title, text, author, tag, lang, hash, date from entries order by id desc limit 10') entries = [dict(title=row[0], text=row[1], author=row[2], tag=row[3], lang=row[4], hash=row[5], date=row[6]) for row in cur.fetchall()] return render_template('index.html', entries=entries, default_lang=default_lang, ) @app.route('/recent/<int:page>') def show_entries_pager(page): if page is None: page = 1 of_value = 1 of_value = page * 10 print of_value entries = query_db('select title, text, author, tag, lang, hash, date from entries order by id desc LIMIT 10 OFFSET ?', [of_value], one=False) if entries is None: print 'No such entry' abort(404) return render_template('recent.html', entries=entries, default_lang=default_lang, ) @app.route('/<hash>') def entry(hash): dan = '' entry = query_db('select * from entries where hash = ?', [hash], one=True) if entry is None: print 'No such entry' abort(404) comment = query_db('select * from comments where entry_id = ?', [entry['id']], one=False) if comment is None: print 'No such comment' if entry['dan']: dan = json.loads( entry['dan'] ) print dan return render_template('entry.html', entry=entry, comment=comment, dan=dan, default_lang=default_lang, ) @app.route('/<hash>/fork') def entry_fork(hash): dan = '' entry = query_db('select * from entries where hash = ?', [hash], one=True) if entry is None: print 'No such entry' abort(404) comment = query_db('select * from comments where entry_id = ?', [entry['id']], one=False) if comment is None: print 'No such comment' if entry['dan']: dan = json.loads( entry['dan'] ) print dan return render_template('entry_fork.html', entry=entry, comment=comment, dan=dan, default_lang=default_lang) @app.route('/tag/<tag>') def entry_tag(tag): entry = query_db('select * from entries where tag = ?', [tag], one=False) if entry is None: print 'No such entry' abort(404) return render_template('entry_tag.html', entry=entry, tags=tag ) @app.route('/about') def about_entry(): return render_template('about.html') @app.route('/blog') def blog_entry(): return render_template('blog.html') @app.route('/contact') def contact_entry(): return render_template('contact.html') @app.route('/add', methods=['POST']) def add_entry(): if not session.get('logged_in'): abort(401) if not g.user: abort(401) name = session.get('username',None) hash = random_str(20) # dan the api code = request.form['text'] lang = request.form['lang'] url = 'http://api.dan.co.jp/lleval.cgi' params = urllib.urlencode({'c':'', 's':code, 'l':lang}) f = urllib.urlopen(url + '?' + params) # paramsはc=&s=code&l=lang dan = f.read() g.db.execute("insert into entries (title, text, author, tag, lang, hash, date, dan) values (?, ?, ?, ?, ?, ?, ?, ?)", [request.form['title'], request.form['text'], name, request.form['tag'], request.form['lang'], hash, datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"), dan ]) g.db.commit() flash('New entry was successfully posted') return redirect( url_for('entry', hash=hash) ) @app.route('/add_c/<hash>', methods=['POST']) def add_comment(hash): if not session.get('logged_in'): abort(401) if not g.user: abort(401) entry = query_db('select * from entries where hash = ?', [hash], one=True) if entry is None: print 'No such entry' abort(404) g.db.execute("insert into comments (text, entry_id, user_id, date) values (?, ?, ?, ?)", [request.form['comment'], entry['id'], g.user['id'], datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")]) g.db.commit() flash('New entry was successfully posted') return redirect( url_for('entry', hash=hash) ) @app.route('/login', methods=['GET', 'POST']) def login(): if g.user: print "OK" session['logged_in'] = True session['user_id'] = g.user['twitter_id'] session['username'] = g.user['name'] flash('You were logged in') return redirect(url_for('show_entries')) else: print "NO" print g.user print(url_for("oauth_authorized")) return twitter.authorize(callback=url_for("oauth_authorized")) @app.route('/logout') def logout(): session.pop('logged_in', None) session.pop('username', None) flash('You were logged out') return redirect(url_for('show_entries')) @app.route('/oauth-authorized') @twitter.authorized_handler def oauth_authorized(resp): next_url = url_for('show_entries') if resp is None: flash(u'You denied the request to sign in.') return redirect(next_url) else: #success user = g.db.execute('select name from users where twitter_id = ?', [int(resp['user_id'])]).fetchone() if user is None: g.db.execute("insert into users (twitter_id, name, oauth_token, oauth_secret, date) values (?, ?, ?, ?, ?)", [int(resp['user_id']), resp['screen_name'], resp['oauth_token'], resp['oauth_token_secret'], datetime.datetime.now()]) g.db.commit() session['twitter_token'] = ( resp['oauth_token'], resp['oauth_token_secret'] ) session['logged_in'] = True session['username'] = resp['screen_name'] session['user_id'] = int(resp['user_id']) flash(resp['screen_name'] + ' were signed in') return redirect(next_url) if __name__ == '__main__': app.run(host='codetype.org', port=5001)
さくらのマルチドメインの公開ディレクトリの~/www/codetype/以下に.htaccessを置きます。
~/www/codetype/.htaccess
#AddHandler cgi-script-debug .cgi DirectoryIndex index.html .ht RewriteEngine on RewriteBase / RewriteCond %{REQUEST_URI} ^/ RewriteRule ^(.*)$ http://codetype.org:5001/$1 [L,P]
さくらのサーバーは定期的にpythonやperlなど立ち上げっぱなしだとサーバー側のプロセスをkillしてしまう為
プロセスが落ちたら立ち上げるように無限ループさせるスクリプトを書いています。
問題はシェルのプロセス自体やscreenなどもkillされる恐れもあります。必要であれば別途、死活監視用スクリプトが必要かと思います。
~/codetype.sh
#!/usr/local/bin/bash while true do echo 'starting Flaskr server...' python ~/src/flaskr/flaskr.py done
構造やレイアウトなどはこちらにまとめています。
https://gist.github.com/730666
謝辞
今回アプリを作る上で参考にさせて頂いたサイト
以下の4サイトにお世話になりました。本当にありがとうございます!!
MA運営事務局の方々、弾さん、知り合いの方々
今回のきっかけを作っていただいた、プレゼンしませんか?と声を掛けてくださったMashup Award運営事務局の山本さん、山田さん、
仕事終わってからカフェなどで資料thonに付き合ってくださった方々、温かい声を掛けてくださった方々。
本当に感謝の気持ちでいっぱいです。心からお礼を申し上げます。
授賞式でしか味わえないような感動や刺激を沢山受けました。