2006-07-02 [長年日記]
_ bookmarkletの受付口が動いていませんでした
1470.netリニューアル版のbookmarklet受付口でエラーが出て、bookmarklet経由の登録がうまく動いていませんでした。
というのは、PHP5でもそろそろ実用で使えるアクセラレータがあるかと探してみたところ、peclに入っているAPCが一応PHP 5.1系に対応していると書かれていたので試しに入れたところ、一見ちゃんと動いているように見えたので、そのまま本番環境に導入してしまいました。が、先ほど試してみたところ、上記ページでAPCなしでは発生しないエラーが発生しているのに気づいたというわけです。
ちなみにエラーが発生したコードは、instanceofで変数の内容を振り分けて処理を切り替えている部分で、APCなしでは正しく継承元クラスのオブジェクトと認識できるのに対し、APCありだとその部分で正しい判断ができていないようでした。検証コードレベルを書けるレベルまで追ってませんけど。
2006-07-04 [長年日記]
_ URIデータベースの不整合障害から復旧しました
設計ミスでURIデータベースに不整合が起こり、その修復の際に各種不具合が発生していましたが、先ほど一通り復旧しました。長々トラブっていてごめんなさい。
_ マイblogmap
で、メモツール以外の新しい機能として、リニューアル版blogmapを稼働させました。ただし、従来のblogmapとはずいぶん違ったものになっています。
従来のblogmapでは、システムがpingサーバー等からblogのフィード情報を収集し、それを解析してランキング等生成していました。しかし、その方法ではspam系blog情報の混入率があまりに高すぎて、頻繁にゴミ掃除をしないとまともな情報が得られないようになっていました。
そこで、今回はユーザーが情報収集先のフィードを自由に登録し、ユーザーが登録したフィード群における被リンク情報等を解析表示できる、ユーザーカスタマイズ可能なblogmapとして作成しました。
この方法ならば、情報収集先をユーザー個々人が管理することでspamを排除できますし、また情報収集の傾向もユーザーが自由に管理することができるでしょう。実際に登録した例は以下のようになります。
表示件数やレイアウトなどは多分いろいろいじると思いますが、機能のイメージはだいたい分かると思います。自分のblogmapにフィードを登録するためのbookmarkletも用意しています。
ちなみに、情報を収集するのはあくまでもフィード内に含まれる情報のみですので、全文を掲載しているフィード以外を登録しても、あまり面白い結果は得られません。また、いわゆるフィードリーダー的な機能も一部持っていますが、フィードリーダーとしての機能はあまり充実させるつもりはありません(他に良くできたフィードリーダーがあるので)。
また、各ユーザーによって登録された特定のフィードに関しては、以下のようなページが用意されます。
- フィード『いしなお!』
- フィード『ただのにっき』(うちには最近MONO系情報を載せていないんで、MONO系情報が載っている例としてたださんのところも)
従来から要望が多かった、アフィリエイト系リンクで情報収集元サイトのIDを残す機能を搭載しているので、Amazon商品系リンクについては、元サイトのアソシエイトIDが生きます(和書についてはbk1へのリンクも生成し、bk1のpartner-idが見つかった場合はそれも利用します)。
2006-07-05 [長年日記]
_ URI関連のフィードを用意しました
ひとまずURIおよびメモに関するフィードをRSS 1.0形式(従来のMM/Memoと同じような形式)で用意しました。
- 新着メモ - http://1470.net/list/memo/recent/feed
- 新着メモに関連するURI - http://1470.net/list/memo/recent/feed/uri
- ユーザー新着メモ - http://1470.net/user/[userName]/feed
- ユーザー新着メモに関連するURI - http://1470.net/user/[userName]/feed/uri
- ユーザー日付別メモ - http://1470.net/user/[userName]/[year]/[month]/[day]/feed
- ユーザー日付別メモに関連するURI - http://1470.net/user/[userName]/[year]/[month]/[day]/feed/uri
URI以外のデータをどう扱うかはいまだに検討中です。一応Atom方向を考えてはいるんですが、調べなければならないことが盛りだくさんなので、ひとまずは慣れているRSS 1.0でお茶を濁しておきます。
_ やっつけ1470footer
RSSを配信したついでにmm_footerをやっつけで改造したけど、CSS周りとかいろいろ調整が必要なんで、自分で改造して使う根性がある人だけどうぞ。
add_body_leave_proc(Proc.new do |date|
oldest_date = Time.local(2005, 1, 11)
if date > oldest_date
if @mode == 'day' or @mode == 'latest'
userName = 'ishinao' # your 1470.net id
url = "http://1470.net/user/#{userName}/#{date.strftime('%Y/%m/%d')}"
rssurl = "http://1470.net/user/#{userName}/#{date.strftime('%Y/%m/%d')}/feed"
template_head = %Q[<div class="section mm_footer">\n<h3><a href="#{CGI.escapeHTML(url)}">今日のメモ</a> powered by <a href="http://1470.net/">1470.net</a></h3>\n<ul class="mm_footer">\n]
template_list = '<li>#{content.gsub(/href="\//, "href=\"http://1470.net\/")}</li>'
template_foot = "</ul>\n</div>\n"
cache_time = 3600;
if date.strftime('%Y-%m-%d') != Time.now.strftime('%Y-%m-%d')
cache_time = 3600 * 12;
end
rss_recent(rssurl, 50, cache_time, template_head, template_list, template_foot)
else
''
end
end
end)
2006-07-06 [長年日記]
_ ようやくMM/Memoでの503頻発が改善できたっぽい
新1470.netと同程度にバランスされるはずなのに、なぜかMM/Memoばかり503エラーになっていたのを改善しようといろいろいじっていたんだけど、ようやく改善できたっぽい。
結局問題は、旧1470.netで受け付けていたpingサーバーへの、世界中からの(ほとんどがspamの)アクセスで、PoundからMM/Memoへのコネクションがあふれてしまっていたらしい。pingサーバーへのアクセスをMM/Memo側のサーバーに振らないように変えたところ、503の頻発はようやく解消された模様。
というわけで、今週頭あたりからご迷惑をおかけしてきましたが、ようやく従来通りアクセスできるように戻ったと思います。
2006-07-07 [長年日記]
_ URLのパーツごとの統計
旧1470.netではURLをvarchar(255)で格納していたんだけど、新1470.netではprotocol、hostname、port、path、querystring、fragmentというパーツに分割し、URL自体はそれらへのIDへのリンクとして持つようにした。
URL情報をハンドリングするには、必ず6つのテーブルへの参照が必要と、処理的には冗長なんだけど、従来のやり方だと無限に増え続けるURL情報がDBサイズを圧迫するんで、とにかくDB上のURL関連データのサイズを圧縮する方が、スケールを考えたときには圧倒的に有利だったので。
で、しばらく走らせてみて、いろいろなURL関連の情報がたまってきたところで、URL数に対しての各パーツの数ってのは、結構面白い情報だなーと思ったので、現在の値を晒してみる。こういうのって研究している人いるのかなー。
| URL | 112,679 |
| プロトコル*1 | 2 |
| ホスト名*2 | 21,378 |
| パス | 78,979 |
| QUERY_STRING | 8,214 |
| フラグメント | 23,510 |
ちなみに、URL情報は形式的にvalidであれば、実体がなくても(404とか返ってきても)登録はされるようになっているんで、すべてが有効なURLであるとは限らない。
あと、うちのDBに登録されるURLってのは、基本的に
- 誰かが興味を持ったURL
- RSSなどで配信されているURL
なので、そういう偏りがあることにも注意が必要だろう。
_ メモのパーマリンク情報の不整合を修正中です
メモのパーマリンク生成処理にバグがあったため、メモに関連するURIデータベースに重複(同じメモに関するURI表現が複数存在する)等が発生しています。現在修正スクリプトを走らせているので、しばらくしたら正しいパーマリンク表現一つに収束すると思います。
_ 1台外れのサーバーがありました
1台deployに失敗してエラーを返すサーバーがあり、先ほどまで1/3の確率でエラーを返す状態になっていました。
ちなみに現在の構成では、フロントのpoundでバックエンドのWebサーバー×3に分散させていて、
Session
Type IP
TTL 300
End
といった感じでIPアドレスベースで接続サーバーを固定しているんで、IPアドレスが変わらない限りは、基本的に同じサーバーに接続するようになっています。
ので、外れのサーバーをひいた場合はずっとエラーが出っぱなし、あたりのサーバーをひいた場合は特に問題がない、みたいな感じの挙動になっていました。
2006-07-10 [長年日記]
_ スケーラビリティとミニマムの負荷
旧バージョンはDBのselectクエリーは分散できるものの、それ以外は分散がほとんど効かないような設計だった。今回はアプリケーションサーバーもDBサーバーも単純に追加できるような設計にしてみたんだけど、そういう設計だとミニマムでの負荷はどうやってもある程度ベタに書いた設計よりも高くなってしまうなー。
すでに現段階で結構な手数を高速化(大量に呼び出されるurlForをベタに書き直したり、エスケープ処理の呼び出しにかかるコストを下げたりとか、とか)に費やしているんだけど、それでも1台増やしたサーバーがぱんぱんだ。DB負荷対策のためにメモリを増やしておいたんだけど、ロジックに費やすCPUパワーの方が先に頭打ちになってしまった。
商売でやってるんだったら、素直にサーバーを増やせばいいんだろうけど、個人でやっていると金だけじゃなく運用にかかる人的コストもばかにならない(俺は開発にかけるコストは趣味だから気にならないけど、運用は趣味じゃないから、その分のコストが増えるとうんざりしてくる)から、サーバーを増やす敷居が高い。
というわけで、単純にサーバーを追加するだけでスケールするような設計は、商売でやるにはいいんだろうけど、個人では実はあまり使えず、それよりも小技で高速化しやすいような設計(キャッシュをメソッド単位できめ細かくかましたり、フレームワーク依存のロジックを高速バージョンに差し替えやすかったり)の方がメリットが大きいかもなー。ひとまずメモリはまだ余っているんで、CPUパワーをメモリ使用量とトレードするような高速化を補助する仕組みをいろいろ追加していこう。っつーのはまあ、一般的には大して需要が大きくはないだろうけど。
_ はてな認証APIに対応しました
リニューアル版1470.netで、はてな認証APIによるはてなアカウントでのログインに対応しました。使い方としては、
- すでにTypeKeyを使って登録した1470.net上のアカウントに、新しくはてなアカウントを結びつけ、TypeKeyとはてなのどちらを使っても、1470.net上の一つのアカウントにログインできるようにする(TypeKeyサービスが落ちている時などの代替手段)
- TypeKeyではなくはてなアカウントを使って、1470.net上のアカウントを作成し、以降はてなアカウントを使って1470.netにログインする。
があります。従来の、
- TypeKeyアカウントを使って1470.net上のアカウントを作成し、以降TypeKeyアカウントを使って1470.netにログインする
とあわせると3パターンの使い方があることになります。
ただ、現在セッション周りの挙動がちょっと怪しいです。特にIEコンポーネントブラウザを使ったときに、セッションがうまく保存されず、ログインページを延々とリダイレクトし続けることがあります。
現在使用しているセッションハンドラが、諸事情により、あわててでっち上げたやつなんで、何かおかしい部分があるのかもしれませんが、再現率が低く、いまいち状況がつかめていません。挙動がおかしい場合は、IEコンポーネントブラウザ以外を利用するとうまくいくかと思います(って、1470.netを使うためにブラウザを変えろってのもひどい話ですが)。原因が分かり次第なおしますんで。
_ ユーザーページでの各種アフィリエイト利用が可能になりました
ユーザー設定から、
- Amazonアソシエイト
- bk1ブリーダー
- Google AdSense
の各アフィリエイトのIDを登録しておくことで、1470.netのユーザーページ(http://1470.net/user/[ユーザー名]/以下)で、自分のアフィリエイトIDを利用することができるようにしました。
キャッシュの関係で、しばらく設定が反映されないことがありますが、数分程度で設定したIDを利用して表示されるようになります。
なお、この設定を利用してアフィリエイトを行う場合は、各アフィリエイトの規約等を確認した上で、自らの責任で設定を行ってください。何らかの不都合が起きても、1470.netサービス提供者は一切の責任を負いかねます。
あと、各アフィリエイトIDの入力チェックが結構いい加減なので、もしかしたら正規のIDなのに不正なIDだとエラーが出て、入力が弾かれる場合があるかもしれません。その場合はコメント等で教えてもらえれば、チェックロジックを修正します。
バグってました
設定を保存しないバグがありました。修正したのでもう一度設定をやり直してみてください。今度はちゃんと設定できると思います。
_ バックエンドサーバーが2台止まっていました
3台中2台のアプリケーションサーバー(lighttpdが起動したfastcgi-php)が応答を返さない状態になっており、500エラーを返す状態になっていました。先ほど復旧させましたが、今のところ原因は不明です。高負荷が原因かなー。でも特筆するほど高負荷になっていたとは思えないんだけどなー。
2006-07-11 [長年日記]
_ セッションの怪しい挙動が直った気がする
カスタムセッションハンドラを使うといまいち再現性がない怪しい挙動をしていた件だけど、もしかしたらこれで直ったのかな? 例外ログに残ってないからエラーは出ていないのかと思ったら、httpdのエラーログの方にエラーが残っていた*1。
Failed to initialize storage module: user (path: )
よく分からないけど、セッションハンドラの登録の仕方がおかしいのか? で、PEARのHTTP_Sessionのセッションコンテナ周りを見ていたら、
session_module_name('user');
というコードがあった。session_set_save_handler()するだけじゃなくて、session_module_name()を使って明示的にカスタムハンドラを使っていることを指定しなければならないんだっけ?
上記コードを追加+セッションID再発行周りの処理をちょっと書き換えてみたところ、俺の手元ではIEコンポーネントブラウザでもおかしな挙動を起こすことがなくなった模様。後者の方も結構重要な変更(セッションID付け替え後のセッション再スタートのタイミングを変えた)なんで、どっちの修正で直ったのか不明*2。でもエラーメッセージ自体は前者の関係っぽいよなー。
_ いろいろ追加しました
各所にRSSを仕込み、ランキングとか新着系の情報も増やし、携帯用のページも追加しました(ページ送りは4、6。トップに戻るは0)。あと表側には関係ないけど、deployスクリプトを作ってちゃんと自動でdeployされるようにしました。
_ 携帯はやっぱり面倒そうだなー
フレームワークの携帯対応の実験として、携帯用のレイアウトファイルを作り、Viewに携帯用変換フィルターをかましたところ、なぜか正しく文字コードが変換されなくてしばらくはまった。
結局、コンテンツ出力前に携帯用変換フィルターをかましてしまうと、レイアウト出力時にもう一度フィルターが走ってしまう(コンテンツ部分に2回文字コード変換がかかる)というのが原因だった。コンテンツ出力前ではなく、携帯レイアウトファイルのコードビハインドでフィルターを適用したところ、正常に動作した。
携帯対応はあまり考えたくなかったんで、何となくこうやったら動くかなー程度しか考えないできたんだけど、やっぱり実際にやり始めると面倒なことが多そうだなー。
2006-07-12 [長年日記]
_ ToDoを追加しました
メモにToDo機能を追加しました。ToDo機能というのは、「(やることの)内容」「予定日(省略可)」をメモに付加することによって、そのメモをToDo項目として扱うことができる機能です。
「イベント」機能とかぶる部分もありますが、他人と共有したい日時情報は「イベント」を、個人的な日時 or 作業を管理したい場合は「ToDo」を使うイメージになります。
見せ方等まだ練れていない部分も多いのですが、試しに使ってみてください。
_ 1470.net関連ライブラリもろもろ
1470.net本体の方で手一杯で、関連して作ったライブラリをちゃんとまとめることができずにいるんだけど、公開Subversionレポジトリ上には載せてあるんで、ソース読んで使う根性がある方はどうぞ。基本的にPHP5+Zend Frameworkベースで書いてあり、修正BSDライセンスにしてあります。
- HyperEstraier - 主にノードAPIクライアント。それ以外のところは構想途中。
- Service_TypeKey - PHP5で書き直したAuth_TypeKey。ひらたさんからは修正BSDライセンスでの公開許可をもらってある。Auth_TypeKeyの細かいバグ(ときどきDSAのverifyに失敗したりとか→コアロジックじゃなくurldecode周りの不具合)を修正してある。
- Service_Hatena_Auth - はてな認証APIクライアント。
Subversionへの直接アクセス(checkoutとか)は、http://svn.ishinao.net/webxp/からいけると思う。
WEBXPフレームワーク本体(Zend Frameworkをラッピングするフレームワーク)は、まだまだ仕様策定中(1470.netリニューアル版に適用しながら、実用レベルでの仕様の問題点を洗い出し中)につき、触らない方が無難。
2006-07-13 [長年日記]
_ はてなアカウントの結び付けを行いたい方
現在TypeKeyサービスが死んでいて、TypeKeyアカウントを使ってのログインができません。はてなアカウントを登録済みの方は、そちらを利用してのログインが可能ですが、すでにTypeKeyアカウントで利用している方で、まだはてなアカウントとの結びつけを行っていない方は、TypeKeyサービスが復旧しないと、結びつけ作業も行えない状況です。
思ったよりもTypeKeyサービスのメンテナンスが長引いているので、暫定処置として、
- 1470.net上のアカウント名
- 登録済みのTypeKeyアカウント名
- 結びつけたいはてなアカウント名
をコメントしてもらえれば、こちらで上記結びつけ処理を行います。ただし、はてなアカウント上のコンテンツをチェックして、アカウント所持者本人であるとの確認が難しい場合は、手動での登録は見合わせることもありますのでご了承ください(他の人のアカウントと結びつけてしまうと困るんで)。
2006-07-14 [長年日記]
_ すみません、ここ数ヶ月古い日記に対してのツッコミ、trackbackに気づいていませんでした
tDiaryのspamフィルタの設定で、10日以上前に対するツッコミ、trackbackをspamとして非表示受信(通知メールもなし)にする、という設定をしていたのをすっかり忘れていて、ここ数ヶ月10日以上古い日記に対してのツッコミ、trackbackがあっても全然気づいていませんでした。
今古い日のデータを見直してチェックしていますが、今まで古い日記にツッコミ、trackbackをくれた方々、反応できなくてごめんなさい。
_ blogmapでのフィード配信をはじめました
blogmapの注目URI、注目MONO、新着URI、新着MONOのフィード配信をはじめました。ちなみにリニューアル版のblogmapってのは、いったいどういうものなのかというと、複数のフィードを解析した結果をフィード配信する(HTMLでも見れますけど)ための、フィード解析&フィルタリングツールになります。
「ITmedia Biz.ID:“情報を読まない”情報収集術――「未読RSS恐怖症」対策」みたいな話もありましたけど、RSS/Atomフィードリーダー等の発達とフィード配信を行うサイトが増えることによって、情報を素早く大量に収集することが可能になっていますが、そうやって収集された大量の情報を人間が吸収する段階がボトルネックになりつつあります。
そこで、単に情報を素早く大量に集めるだけでなく、その情報をうまく吸収する仕組み(良くできたRSSリーダーだとか、あるいはソーシャルブックマークの注目リストやお気に入り機能など)がいろいろ用意されはじめているわけです。そういう情報の吸収方法を効率化する仕組みの一つが、blogmapになります。
blogmapではフィードリーダーと同様に、ユーザーが自分のお気に入りのRSS/Atomフィードを登録していきます。しかし、ふつうのフィードリーダーと違って、フィード情報をそのまま(たとえば新着順などで)表示すると言うことはありません。
blogmapでは、フィードに含まれるエントリー情報から、
- リンクしたURL(Webページ)に関する情報
- リンクしたMONO(Amazon商品ページ)に関する情報
を解析し、その二つの情報をキーとして、
- 新しくリンクされたURL、MONOに関する情報
- 最近よくリンクされているURL、MONOに関する情報
というリストを作ります。つまり、いちいち実際のエントリーの内容を読まなくても、URL、MONOに関する情報のみを自動的に抽出してくれるわけです(参考 :私のblogmap)。
いわゆる読み物系サイトなどの場合は、エントリー本文を読まないと意味がありませんが、情報中心のサイトの場合は、まずURLおよびMONO系情報のみをチェックするだけで、十分に有用な情報が手に入ります。そこで何か気になる情報が見つかった場合は、そのURL、MONOに関する情報を扱っているエントリー本文を読んで、さらに詳しい情報を得ればいいのです。
このような処理は、技術力のある人ならばPlaggerなんかを使って、独自のフィルターを作ることによって対応していることでしょう。しかし、Plaggerは誰でも使えるツールというわけではありません。
リニューアル版1470.netに搭載したblogmapは、そういった高度なフィルタリング処理を、誰でも簡単に実現できるようにしたツールなのです。
という理想の元に設計したわけですけど、実際にそういう風に使えるのかどうかはまだ分かりません。まあぼちぼち使ってみて、不満や改善案などがあったらコメントください。
MM/Memoのお気に入り相当の機能は
リニューアル版1470.netの各ユーザーのフィードをblogmapに登録することで、それらのユーザーのフィードをミックスした新着情報、注目情報が抽出されるようになります。
他のSBMのフィードの場合
blogmapでは、基本的にblog等のエントリー情報を含むフィードを解析し、そのフィードの本文(description、content:encoded、contentなど)内に含まれるURLを解析します。
一般的なSBMの場合は、そのフィードのアイテム要素としてURL情報を持ち、本文等にそれらURLへのリンクを持たないため、同じロジックでは解析対象となりません。1470.netのように、本文要素にURL情報を含むフィードを配信するSBMの場合(あるのか知りませんけど)は対応できます。
アドホックに有名SBMを別扱いに処理することも不可能ではありませんが、できればそういう汚い実装は避けたいので、現時点では他のSBMで提供されるフィードをblogmapに登録しても、そのURL等は解析対象にはなりません(/uri/*系の情報には、どのフィードに登録されたかなどの情報が表示されるようになるので、登録しても意味がないわけではないですけど)。
このあたりは何かいい方法(統一的な扱いで、なおかつ有意な情報を得る方法)が見つかるまでは、ペンディング状態です。
具体的な利用イメージとしては
主に情報提供系サイトで、
- その主たる内容が、URL抽出によっておおむね表現される
- RSS/Atomフィードで全文(もしくはそれに近い)コンテンツを配信している
- 日々更新される情報量が多くて、すべてのエントリーを読み切れない
ようなサイトに関しては、RSS/Atomフィードリーダーに直接登録するのはやめてしまいます。代わりにそのようなサイトはblogmapに登録し、blogmapの新着もしくは注目URIのフィードをチェックするようにします。
そうすることで、エントリー本文を毎回チェックするサイトと、情報の中の一部のみをチェックするサイトを区分し、日々の情報の整理を効率化させよう、といった感じになります。
ただまあ私の場合は、普段フィードリーダーでエントリーを全部読むサイトもそうでないサイトも、コンテンツ本文が配信されているサイトはほとんど登録しちゃってますけど。
2006-07-15 [長年日記]
_ 対応方法が思いつかないspam
そのページに書かれている文章から抜き取ったテキストの最後に1行(宣伝)URLを追加したツッコミspamがさっき来たんだけど、これって機械的な識別がえらく難しそうだな。日本語利用チェックとか、URL文字列割合チェックとか、その手の対応はすべて無効で、ほぼURL・ドメインベースのblacklistで対応するしか手はないんじゃなかろうか。
_ タグ入力支援機能の改善
リニューアル版1470.netのタグ入力支援機能を、使いにくいまま放置している。この辺は結局Ajaxを使わなければならず*1、Ajaxを使う場合はちゃんと設計してから作らないとぐだぐだになりがち*2なんで、隙間でちょっと機能追加するといった感じで作れない。
ひとまずタグ入力支援機能として、どういう機能があれば使いやすいのか自分の中でまとめ切れてないんで、具体的にどういう支援機能があればうれしいみたいなご意見募集中です。
_ データフォーマットはJSONでもいいでしょうか?
メモのバックアップ向けのAPIを作りかけている。インターフェースは基本RESTで行こうと思っているんだけど、データフォーマットをどうしようか悩み中。XMLが無難ではあるんだけど、やっぱりうざいなー。特にTSVとかCSVでも十分に表現できるようなデータを、わざわざXMLにするのがだるい。ただ、そういうときにTSVとかCSVとか使うってのも、扱うデータフォーマットの統一感とか、データが途中でぶち切れたとき対策とかの点でいまいちだ。で、今のところJSONにしちゃおうと思っていたりするんだけど、それだと困るって人はいますかねー。まあ最悪クライアント側のサンプル実装もこっちで作れば問題ないか。
2006-07-16 [長年日記]
_ 6時頃から8時半頃までサーバーが死んでました
今朝6時頃から8時半頃まで、フロントサーバーが刺さっていて、応答しない状態になっていました。
CRONDプロセスがやたらと増殖して、プロセス数を食いつぶして、shutdownすら効かない状態になっていた(ハードリセットした)んだけど、これはいったい何だったんだろう?
_ タグ入力補助機能追加中
しばたさんの要望を中心に、タグ入力補助機能を追加していっています。
で、まずタグの「インクリメンタル・タグ補完」を追加しました。タグ欄に文字を入力すると、過去に自分が使用した、その文字から始まるタグを候補として表示されます。ただし、migemo風のローマ字入力→日本語推測→タグ補完まではできていません。これはmigemoを内部で使うよりも、自前で辞書を持った方がいいかもなー。
あと、同じURI、MONOを扱った他のメモに使われたタグを「おすすめ」として表示する機能もつけておきました。MONOの場合は、作者名なども「おすすめ」として表示します。
「関連語のsuggestion」(タグ自体の関連性をたどる)も難しくなさそうなんで、そのうち対応すると思います。
関連語のsuggestionもつけてみました
インターフェース的にはちょっと微妙だけど、使い物にはなるかな。
_ lighttpd+fastcgi+PHP 5って安定しない?
なんかしばらく動かしておくと、CPUパワーを消費し続けるPHPプロセスが生まれて、そいつらのせいでじわじわとload averageがあがっていく。lighttpdを再起動すると直るんだけど、場合によってはlighttpdを再起動しても上記のようなPHPプロセスが居座り続けて、強制的に殺さないといなくなってくれない。どこかに無限ループになるような処理があったりして、そいつがPHP/fastcgiプロセスとしてずっと動き続けてたりするんだろうか? ひとまず定期的にlighttpdは再起動しておくのが無難か?
2006-07-17 [長年日記]
_ メモ情報取得API
主にメモデータバックアップ目的のためのメモ情報取得APIを用意しました。すみません。API仕様を変更してます。戻り値を直接ルートノードから返すのではなく、必ず"result"ノード下に収納することにしました。
リスト取得
- URL - http://1470.net/api/memo/list
- パラメータ(QUERY_STRING)
- userName - 1470.netユーザーID(省略可)。指定すると、そのユーザーのメモ情報のみが対象となる。
- updt - 更新日時(省略可)。指定するとその更新日時以降に更新されたメモのみが対象となる。
- リクエストメソッド - GET
- 戻り値
- データ形式 - JSON
- 例 {"info": {"totalCount": 1234}, "result": [{"id" : 998, "updt" : "2006-06-30 02:16:20"}, {"id" : 999, "updt" : "2006-06-30 02:16:21"}, ...]}
- info.totalCount - 該当した総項目数(2000を超えている場合、各項目として返るのは最初の2000件)
- result.* - 各項目
- id - メモID。メモにつけられたユニークなID。
- updt - メモの更新日時(JST)
- ソートオーダー
- updt asc。
- 制約
- 結果が2000件を超える場合は、最初の2000件のみを返す。その場合updtパラメータ指定などを使って、続きの情報を取得し直す必要がある。
メモ情報取得
- URL - http://1470.net/api/memo/[メモID]
- パラメータ - なし
- リクエストメソッド - GET
- 戻り値
- データ形式 - JSON
- 例 {"result": {"id" : 34553, "url" : "http://1470.net/user/ishinao/2006/07/01#m_34553", "title" : "集英社 ハチミツとクローバー 9 (9) 羽海野 チカ", "comment" : null, "eval" : null, "tags" : ["羽海野 チカ", "ハチクロ", "マンガ"], "groups" : {}, "uri" : {}, "mono" : [{"asin" : 4088653521, "uri" : "http://www.amazon.co.jp/exec/obidos/ASIN/4088653521/ref=nosim/ishinao-22", "title" : "集英社 ハチミツとクローバー 9 (9) 羽海野 チカ"}], "map" : {}, "event" : [{"name" : "集英社 ハチミツとクローバー 9 (9) 羽海野 チカ 発売日", "stdt" : "2006-07-14 00:00:00", "eddt" : null}], "todo" : null, "rgdt" : "2006-07-01 14:04:38", "updt" : "2006-07-16 20:55:51"}}
- 項目
- id - メモID
- userName - ユーザーID
- url - メモURL
- title - メモタイトル
- comment - コメント
- eval - 評価
- tags - タグ(配列)
- groups - グループ(配列)
- uri - メモに添付されたURI情報(配列)
- url - URL文字列。
- title - URIで示されたドキュメントのタイトル。
- mono - メモに添付されたMONO情報(配列)
- asin - ASINコード。
- url - Amazon個別商品ページURL。
- title - 商品情報(タイトル+著作者情報)。
- map - メモに添付された位置情報(配列)
- name - 位置情報名。
- latitude - 緯度。
- longitude - 経度。
- zoom - Google Maps APIにおけるズーム情報。
- event - メモに添付されたイベント情報(配列)
- name - イベント名。
- stdt - イベント開始日
- use_sttime - イベント開始日で時間要素も有効かどうか
- eddt - イベント終了日
- use_edtime - イベント終了日で時間要素も有効かどうか
- todo - メモに添付されたToDo情報
- name - 次に行うToDo名。
- tododt - その予定日。
- rgdt - メモ登録日
- updt - メモ更新日
バックアップクライアントサンプル実装
require_once 'Zend/Json.php';
$userName = 'ishinao';
$dataDir = '/tmp/backup';
$listUrl = 'http://1470.net/api/memo/list';
$itemUrl = 'http://1470.net/api/memo/';
$touchFile = $dataDir . '/touch';
$updt = filemtime($touchFile);
$rawListData = file_get_contents($listUrl . '?userName=' . urlencode($userName) . '&updt=' . urlencode(date('Y-m-d H:i:s', $updt)));
$decodedListData = Zend_Json::decode($rawListData);
$list = $decodedListData['result'];
foreach ($list as $row) {
$memoId = intval($row['id']);
if (!$memoId) {continue;}
$dataFile = $dataDir . '/' . $memoId . '.txt';
if (file_exists($dataFile) && (filemtime($dataFile) == strtotime($row['updt']))) {continue;}
$rawItemData = file_get_contents($itemUrl . $memoId);
$decodedItemData = Zend_Json::decode($rawItemData);
$item = $decodedItemData['result'];
if ($item['id'] != $memoId) {
throw new Exception('memo cannot read: ' . $memoId);
}
file_put_contents($dataFile, $rawItemData);
touch($dataFile, strtotime($row['updt']));
touch($touchFile, strtotime($row['updt']));
}
_ 携帯用ユーザーページを追加しました
携帯ページにユーザーページ(ユーザーごとの新着/ToDo表示)を追加しました。これで出先でToDo(っつーか買物リスト)をチェックしやすくなったな。
携帯(フルブラウザ以外)でもツール系の機能を使えるようにするべきかなー。携帯は閲覧さえできればそれで十分かなー。と迷いつつちょろっと試してみたところ、TypeKeyやはてな認証APIはEZWebから接続できない(SSL証明書が携帯非対応)ことが判明。ひとまず無理か。俺自身はW-ZERO3+Operaでフル機能使えるしなー。
2006-07-18 [長年日記]
_ メモ情報取得APIの仕様を変更しました
戻り値を直接ルートノードに返すのは今後の拡張性に問題があるため、結果を"result"というノード以下に返すようにしました。
今後は互換性のない仕様変更はないように気をつけますので。
_ lighttpd+fastcgi+PHP 5って安定しない?の続報
TutorialLighttpdAndPHP - lighttpd - Tracの情報を参考に、"max-procs" => 2に設定してみたところ、連続稼働2、3日経っても以前みたいにCPUパワーを食い続けるプロセスが生まれたりはせず、安定して動いている。eacceleratorのsnapshotを入れている(ちなみにときどき特定のコード*1でエラーを吐くけど、基本的には高速化の恩恵の方が大きいんで、目をつぶって動かしている)んで「If you're using any php opcode cacher」には当てはまるんだけど、「unless you want to eat up so much memory」じゃなくて、CPUパワーだけを食っていたんだけどなー。
*1 array('' => '-')みたいな空文字列をキーにした配列とか
2006-07-19 [長年日記]
_ 0.1.3+αから0.1.5への移行
1470.netで使っているZend Frameworkを、0.1.3をベースにいくつかの自前の修正とincubatorの取り込みを行ったバージョンから、0.1.5(というか最新のtrunk)に移行中。以下作業メモ。
- Zend_Db_Adapterのtype表記が、pdoMysql形式からPDO_MYSQL形式に変わったらしい。
- Zend_Service_Amazon周りのバグはいつまで経ってもなおんねーなー。報告はしてあるんだけど。それともjpでしか再現しないんだろうか? んなことないはずなんだけど。まあいいや。自分でなおしたバージョンを使おう。
- Zend_Db_Table::find()の挙動は相変わらず気に入らないんで、これも自分でなおしたバージョンに差し替え。っつーか、引数を配列にキャストして、要素が1個の場合はRowを返し、複数の場合はRowsetを返すって、すごい使いにくくないかなー。キーの配列を引数で渡すとき、たまたま要素数が1個になっちゃったときにRowで返される(受け取った側の扱いが変わる)のはすごく迷惑なんだけど。引数の型で戻り値の型を決めて欲しいなー。要望は出してあるんだけど。
- Zend_Http_Clientはincubatorバージョンにある、Cookieやchunkedエンコーディング、gzipエンコーディング等に対応したものに差し替え。俺が使う範囲ではほとんどバグがなくなった。
- Zend_Filter::isHostname()はまだ一文字要素があるホスト名(d.hatena.ne.jpとか)でtrueを返してくれないんで、その部分を差し替え。でもこれはバグトラックの方で進展があったんで、そのうち直ると思う。
- Zend_Json_Decoder::_eatWhitespace()は、相変わらずパイプを使った正規表現だとはてな認証APIのJSONがデコードできないんで、ここも自前で修正。
- そういやZend_Cacheはincubatorから標準添付に格上げされたんだね。incubatorの頃から使っているけど、memcachedバックエンドもちゃんと動いている。
- 本当だったらZend_Controller_RewriteRouterに移行したいところだけど、全然互換性がない自前のルーターで来ちゃってるんで、今更乗り換えられない。失敗したかなー。そういやincubatorの方にUrlヘルパー(Railsでいうurlfor。tokenからurlへの逆解決)が置いてあるね。
ってところまで直したところ、手元では一通り問題なく動いているんだけど、いつサーバーに適用しようかなー。
あぶないあぶない
Zend_FeedをRSS 1.0に対応させる修正を忘れていた。これをやらないと日本のRSSのかなりの数に対応できなくなってしまう。ちなみにこれは自前パッチじゃなくて、昔Zend Frameworkのtracに報告されていたパッチ。
アップデートした
本サーバーの方もアップデートした。特に問題なさそうに見えるけれども、何か怪しげな挙動があったら教えてください。
_ 配列生成のショートカットがあるといいなー
PHPでは配列が便利なので多用するわけだけど、配列を生成するのにarray()関数を使う必要があり、ちょっとしたオプション指定なんかでいちいちarray()と書くのはとてもうざい。これって何かショートカット表現が用意されているとうれしいんじゃなかろうか。配列生成くらい関数を通さずに、文法の範囲で(短く)書けてもいいのになー。
2006-07-20 [長年日記]
_ フィード情報におかしな情報が混ざっているものがあります
blogmapのOPMLインポートのテストをしていたんだけど、なぜかその機能を使って追加したフィード情報に、おかしな情報が混ざっていることがあります。まだ原因は調査中(ライブラリのアップデートが影響しているかも?)ですが、妙な情報が登録されている(同一タイトルのフィードが重複していたり)フィードを見かけたら、教えていただければ修正します。
_ 内部APIいろいろ
日本で公開されているAPI一覧(下書き)とかからリンクされてたんで、どうせなら1470.netリニューアル版内部で使っているAPIも一応書いておこう。内部用なんでいつまで使えるかは未保証だけど。
個人で使う分には外部から適当に呼び出して使ってもいいけど、ばりばり使う場合は、タグ系API以外はどうせ元ネタを公開(位置情報+郵便番号データベース、鉄道路線+駅位置情報データベース)しているんで、自前でサーバー立てて使ってください。あと鉄道系DBをアップデートしてくれる人募集中。
都道府県一覧
- URL - http://1470.net/api/prefectures
- パラメータ - なし
- 戻り値
- 形式 - JSON(配列)
- 各要素 - キー「都道府県ID」、値「都道府県名」
市区町村一覧
- URL - http://1470.net/api/cities/[都道府県ID]
- パラメータ
- 都道府県ID - 都道府県一覧で取得したID
- 戻り値
- 形式 - JSON(配列)
- 各要素 - キー「市区町村ID」、値「市区町村名」
町域一覧
- URL - http://1470.net/api/cityareas/[市区町村ID]
- パラメータ
- 市区町村ID - 市区町村一覧で取得したID
- 戻り値
- 形式 - JSON(配列)
- 各要素 - キー「町域ID」、値「町域名」
郵便番号→住所推測
- URL - http://1470.net/api/zip/[郵便番号]
- パラメータ
- 郵便番号 - 半角数値7桁(ハイフンはなし)
- 戻り値
- 形式 - JSON(連想配列)
- 各要素
- address - 住所ID
- prefecture - 都道府県ID
- city - 市区町村ID
- cityarea - 町域ID
- title - 表示名
- 注意
- 郵便番号が市区町村レベルで定義されている場合でも、必ず町域レベルまで推測しようと試みるため、いわゆる郵便番号→住所変換データベースとは異なる結果になる
- 例
- 呼び出し: http://1470.net/api/zip/1500002
- 戻り値: {"address" : 59209, "prefecture" : 13, "city" : 615, "cityarea" : 59200, "title" : "東京都渋谷区渋谷一丁目"}
住所→位置情報変換
- URL - http://1470.net/api/location/[都道府県ID]/[市区町村ID]/[町域ID]
- パラメータ
- 都道府県ID
- 市区町村ID
- 町域ID
- 戻り値
- 形式 - JSON(連想配列)
- 各要素
- prefecture - 都道府県ID(エコー)
- city - 市区町村ID(エコー)
- cityarea - 町域ID(エコー)
- latitude - 緯度(世界測地系)
- longitude - 経度(世界測地系)
- 例
- 呼び出し: http://1470.net/api/location/13/615/59200
- 戻り値: {"prefectureId" : 13, "cityId" : 615, "cityareaId" : 59200, "latitude" : 35.66129, "longitude" : 139.70698}
位置情報から最寄りの住所推測
- URL - http://1470.net/api/nearAddress/[緯度]/[経度]
- パラメータ
- 経度 - 世界測地系。小数表現。
- 緯度 - 世界測地系・小数表現。
- 戻り値
- 形式 - JSON(連想配列)
- 各要素
- address - 住所ID
- prefecture - 都道府県ID
- city - 市区町村ID
- cityarea - 町域ID
- title - 住所表示名
- latitude - 住所を代表する緯度(世界測地系)
- longitude - 住所を代表する経度(世界測地系)
- zipcode - 住所で使われる郵便番号(推定)
- 例
- 呼び出し: http://1470.net/api/nearAddress/35.12355/139.23423
- 戻り値: {"address" : 67266, "prefecture" : 14, "city" : 712, "cityarea" : 67255, "title" : "神奈川県足柄下郡真鶴町真鶴", "latitude" : 35.15503, "longitude" : 139.14351, "zipcode" : 2590200}
鉄道路線一覧
- URL - http://1470.net/api/railways
- パラメータ - なし
- 戻り値
- 形式 - JSON(配列)
- 各要素 - キー「路線ID」、値「路線名」
- 注意
駅一覧
- URL - http://1470.net/api/stations/[路線ID]
- パラメータ
- 路線ID - 鉄道路線一覧で取得したID。
- 戻り値
- 形式 - JSON(配列)
- 各要素 - キー「駅ID」、値「駅表示名」
- 例
- 呼び出し: http://1470.net/api/stations/1
- 戻り値: {"8874" : "小沢", "8975" : "大麻", "8981" : "張碓", "8982" : "手稲", "8983" : "銭函", "8984" : "星置", "8985" : "稲穂", "8987" : "穂積公園", "8988" : "発寒中央", "8989" : "発寒", "8957" : "森林公園", "8956" : "厚別", "8875" : "銀山", "8876" : "然別", "8878" : "余市", "8880" : "小樽", "8881" : "塩谷", "8904" : "札幌", "8905" : "琴似", "8954" : "苗穂", "8955" : "白石", "9005" : "野幌", "9006" : "江別", "9124" : "奈井江", "9125" : "豊沼", "9128" : "滝川", "9131" : "江部乙", "9132" : "妹背牛", "9169" : "深川", "9171" : "納内", "9177" : "旭川", "9178" : "伊納", "9117" : "茶志内", "9027" : "峰延", "9008" : "豊幌", "9009" : "幌向", "9012" : "南小樽", "9013" : "小樽築港", "9014" : "朝里", "9019" : "上幌向", "9020" : "岩見沢", "9025" : "美唄", "9026" : "光珠内", "9179" : "近文", "8729" : "函館", "8777" : "駒ケ岳", "8778" : "赤井川", "8780" : "鹿部", "8781" : "本石倉", "8782" : "石谷", "8783" : "桂川", "8784" : "森", "8785" : "尾白内", "8786" : "東森", "8776" : "東山", "8775" : "姫川", "8730" : "五稜郭", "8763" : "結梗", "8764" : "七飯", "8765" : "大中山", "8766" : "渡島大野", "8767" : "大沼公園", "8768" : "大沼", "8769" : "仁山", "8770" : "池田園", "8787" : "掛", "8788" : "渡島砂原", "8812" : "長万部", "8819" : "蕨岱", "8866" : "黒松内", "8867" : "熱郛", "8868" : "目名", "8869" : "蘭越", "8870" : "昆布", "8871" : "ニセコ", "8872" : "比羅夫", "8811" : "二股", "8806" : "中ノ沢", "8789" : "渡島沼尻", "8791" : "野田生", "8792" : "石倉", "8793" : "落部", "8794" : "八雲", "8795" : "鷲ノ巣", "8800" : "黒岩", "8801" : "北豊津", "8805" : "国縫", "8873" : "倶知安"}
- 注意
駅位置情報
- URL - http://1470.net/api/station/[駅ID]
- パラメータ
- 駅ID - 駅一覧で取得したID。
- 戻り値
- 形式 - JSON(連想配列)
- 各要素
- id - 駅ID(エコー)
- name - 駅名
- latitude - 緯度(世界測地系)。小数表記。
- longitude - 経度(世界測地系)。小数表記。
- 例
- 呼び出し: http://1470.net/api/station/8874
- 戻り値: {"id" : 8874, "name" : "小沢", "latitude" : 42.97158, "longitude" : 140.67775}
- 注意
最寄り駅推測
- URL - http://1470.net/api/nearStation/[緯度]/[経度]
- パラメータ
- 緯度 - 世界測地系。小数表記。
- 経度 - 世界測地系。小数表記。
- 戻り値
- 形式 - JSON(連想配列)
- 各要素
- station - 駅ID
- latitude - 緯度。世界測地系。小数表記。
- longitude - 経度。世界測地系。小数表記。
- 例
- 呼び出し: http://1470.net/api/nearStation/35.66129/139.70698
- 戻り値: {"station" : 5581, "name" : "渋谷", "latitude" : 35.65767, "longitude" : 139.70342}
タグ推測(ユーザー、利用頻度、タグ名前方一致)
- 概要
- タグの利用頻度順に10件のタグを返す。
- ユーザー名を指定した場合、そのユーザーに関する情報。
- タグ名を指定した場合は、そのタグ名と前方一致でマッチするタグを返す。
- URL - http://1470.net/api/tag/list
- パラメータ(QUERY_STRING)
- userName - 1470.netユーザー名。省略可(省略時は全ユーザーが対象)
- tagName - タグ名(最初の部分だけでOK)。前方一致で検索する。省略可。
- 戻り値
- 形式 - JSON(連想配列)。resultノード以下。
- 各要素
- name - タグ名
- cnt - タグ利用回数
- 例
- 呼び出し: http://1470.net/api/tag/list?userName=ishinao&tagName=a
- 戻り値: {"result" : [{"name" : "AJAX", "cnt" : 26}, {"name" : "API", "cnt" : 11}, {"name" : "Amazon", "cnt" : 11}, {"name" : "Apache", "cnt" : 9}, {"name" : "ACCS", "cnt" : 6}, {"name" : "au", "cnt" : 5}, {"name" : "Apple", "cnt" : 4}, {"name" : "AV", "cnt" : 4}, {"name" : "AA", "cnt" : 2}, {"name" : "adsense", "cnt" : 2}]}
タグ推測(タグの相関)
- 概要
- あるタグと同時に使われることが多いタグ群を20件を返す。
- 元となるタグを複数渡すと、各タグごとの結果を加算し、多い順に20件返す。
- URL - http://1470.net/api/tag/related
- パラメータ(QUERY_STRING)
- query - タグ名。複数渡すときには半角スペース区切りで。
- 戻り値
- 形式 - JSON(連想配列)。resultノード以下。
- 各要素
- name - タグ名
- cnt - 利用回数
- 例
- 呼び出し - http://1470.net/api/tag/related?query=ajax%20php
- 戻り値 - {"result" : [{"name" : "javascript", "cnt" : 134}, {"name" : "JavaScript", "cnt" : 57}, {"name" : "Web", "cnt" : 29}, {"name" : "Programming", "cnt" : 24}, {"name" : "PHP", "cnt" : 22}, {"name" : "Internet", "cnt" : 19}, {"name" : "Ajax", "cnt" : 18}, {"name" : "computer", "cnt" : 18}, {"name" : "PEAR", "cnt" : 15}, {"name" : "フレームワーク", "cnt" : 15}, {"name" : "Ruby", "cnt" : 14}, {"name" : "Rails", "cnt" : 12}, {"name" : "セキュリティ", "cnt" : 12}, {"name" : "prog", "cnt" : 11}, {"name" : "Web2.0", "cnt" : 11}, {"name" : "Javascript", "cnt" : 10}, {"name" : "XML", "cnt" : 10}, {"name" : "Google", "cnt" : 10}, {"name" : "技術", "cnt" : 9}, {"name" : "JAVA", "cnt" : 8}]}
_ blogmapにOPMLでインポート
blogmapで情報を収集するフィードを、OPMLファイルを使って登録する機能を追加しました。
まだ挙動が怪しい部分があるんですが、その後のテストではどうしても再現できないんで、実稼働させてトラブルが出たら対処することにします。
一度のインポート処理に60秒間のタイムアウトを設定しているので、大量のフィードが記載されたOPMLファイルをインポートすると、いったんタイムアウトになることがあります。が、基本的に放っておく(あるいは明示的に「次に進みます」をクリックする)ことで、残りのフィードを取り込み続けますので。
2006-07-21 [長年日記]
_ どうもキャッシュの更新状況がおかしいなーと思ったら
Zend_Cacheのmemcachedバックエンドってタグ機能サポートしてないのか……。どうしたもんかなー。
Mysqlバックエンドをでっちあげてそっちに移行した
厳密さよりも速度を取っているんで、その点注意。あとZend_Cache::$availableBackendsにMysqlを追加しておく必要がある。
2006-07-24 [長年日記]
_ xdebugのプロファイラーの誤動作
PHP 5.1.4(Windows XP)+xdebug(5.1.2-2.0.0beta6)でプロファイルを取ったところ、途中でプロファイルデータがリセットされ、ほとんど内容のないプロファイルデータが生成された。この前まではふつうにプロファイルが取れていたのになんでだろうなーと、どこでリセットされるのか探していたところ、
<link rel="SHORTCUT ICON" href="/favicon.ico" />
を出力している行を削除したら、途中でリセットされず、ちゃんとプロファイルが取れるようになった。けど、上記行を別のPHPファイルに切り出して実行しても、特におかしいことにはならないから、何か複合的な原因があるんだろうなー。ちなみに
<link rel="SHORTCUT" href="/favicon.ico" />
とやったら、正しくプロファイルが出力されるんだけど、
<link rel="ICON" href="/favicon.ico" />
だとやっぱりおかしくなる。あと、
<!--link rel="SHORTCUT ICON" href="/favicon.ico" /-->
ならば、問題は出ない。
link relとiconの組み合わせに何かある? どちらにしろPHPコードとしては正常に動作していて、xdebugのプロファイラーの動作だけがおかしくなるんだよなー。わけわからん。
_ おすすめURIを追加しました
好みのニュースをおすすめしてくれる『Kikker』がいいらしいという話を聞いて、うちにもおすすめURIページを追加してみました。といっても、うちの場合はKikkerみたいに真面目に(ドキュメントの類似度等)計算しておらず、単に「今まで自分がつけたタグと同じタグが付いているけれども、まだ自分はメモしていないURI」を表示しているだけですけど。
もうちょっといろいろ計算しようかと思ったんですが、この程度でも結構いい感じの情報が出てくるみたいなんで、ひとまずこれでしばらく動かしてみます。多分、似たようなタグの付け方をする人=同じような話題に同じような方向で興味を持っている人、ってことで、この程度のロジックでもそれなりの結果が出るんだろうなー。
この方向性は結構面白そうなんで、サーバーに余力がありそうならもうちょっといろいろ試してみよう。ドキュメントごとの特徴語インデックスとタグの類似度インデックスを作っておけば、もっと汎用的な抽出ができるんだろうなー。
2006-07-25 [長年日記]
_ うげ、ばけばけだ
フィードのクロール処理を別マシンに移動したところ、なんか文字化けしまくっています。次回フィード更新時にフィード系の情報は修正されます。フィード以外で文字化けしている分については、修正クローラーを走らせますんで、しばらくしたらだいたい直ると思います。
それにしても、まったく同じphp.iniを使っているのになんで化けたんだろう? 使っているMySQLのライブラリの問題かなー。
_ タグ検索時には半角空白を無視するようにしました
半角空白を含むタグを検索(同じタグを付けたメモを見る、など)する際に、半角空白を無視して検索するようにしました。
っつーかまあ、限りなくAmazonの著者データベースの姓と名の間の半角空白の扱いがいい加減な状況に対しての対策です。これで、Amazonに登録されている著者名をそのままタグに利用した場合でも、半角空白の揺らぎは無視して検索できるようになります。
_ フィードから取得したURIも対象に加えました
今までは1470.net上のメモにつけられたタグのみを利用して、おすすめURIを抽出していましたが、新しくフィードに付けられたタグ(あるいはカテゴリ)がマッチする場合も、おすすめURIとして抽出するようにしました。
カテゴリ対応のblogやSBM経由で取得したフィードなんかには、タグが付加されてますんで、それら経由での情報も掲載されるようになると思います。要するに、まだ1470.net上で誰もメモしていないURIでも、外部のタグに類似した情報を使うことによって、おすすめURIに抽出&掲載できるようになるはずです。
あと、従来はタグの完全一致で検索をかけていましたが、他のタグ検索時と同様に「大文字小文字は無視」「半角スペースは無視」して検索するようにしました。
_ 被ブックマーク/被リンクURI一覧
特定のサイト(ホスト)内のページの、被ブックマーク/被リンクURIを表示する機能を追加しました。URLは、
- http://1470.net/site/[ホスト名](/[パス])
- ここの場合: http://1470.net/site/tdiary.ishinao.net/
になります。
また、以前からあるフィード情報のページ、
からも[SITE]というリンクを張っているので、[URI]→[FEED]→[SITE]とアイコンをたどることで、URIが所属するフィード(サイト)→そのサイトの他の人気URIへとたどることができるようになります。
たとえば今たまたま一番新しいメモの、
から、[URI]アイコンをたどって、
にいき、その[FEED]アイコンをたどって、
にいき、その[SITE]アイコンをたどって、
にいく。といった感じの利用イメージになります。
いやーそれにしても、もともとのblogmap構想(Web日記の被リンク情報を解析して、関連情報をたどりやすくする仕組みを作る)がずいぶん実現できてきたなー。
2006-07-26 [長年日記]
_ colinuxへの移行、苦戦中
今まで何度もcolinuxやらVirtualPCやらcygwinやら、ローカルのPHP開発環境をLinux on Windows系に移行しようと思ったんだけど、なんだかどうしてもなじめないままに、Win32バイナリ環境に戻ってきていた。けど、やっぱりどうしてもWindows(開発)環境とLinux(運用)環境の差異を吸収するのが面倒くさくなってきたんで、今度こそ完全に移行することを決意。
で、もう何度目かになるcolinuxをできるだけ再セットアップが簡単そうなdebianを使って環境構築しているんだけど、いつまで経ってもまともな環境ができあがらない。まずdebianがよく分からない。Redhat/Fedora系でaptは使ってきたから、似たようなもんかと思っていたんだけど、内部的な管理の仕方が全然違うんだね。開発環境でライブラリのバージョン等を細かくいじりたい場合、debianでは何をどうやっていいのかよくわからん。
さらに、hyperestraier-1.3.3がどうしてもインストールできずにしばらくはまった*1。結局他の環境でインストール実績のあるqdbm-1.8.59+hyperestraier-1.2.8まで戻したらインストールできた。
さらに、PHP 5.1.4をインストールしようとしたら、apt-get install php-5.1.4できたもんだから、楽でいいやと使おうとしたんだけど、どうしてもmysql拡張を使う方法がわからなかったんで、結局Apache 2もPHP 5.1.4もアンインストールして、ソースからインストールし直した。
また、MySQL 4.1系については、apt-get install mysql-server-4.1とかでインストールできてラッキーと思っていたんだけど、PHPをソースインストールするときに使うヘッダ類が見つからずに(mysql-headers-4.1とかあるかと思ったら見あたらない)あきらめて一度アンインストールした。がその際のメッセージを見て、mysqlclinent14-devというのがあるのを発見し、それを使ってようやくPHP 5.1.4を--with-mysql付きでインストールすることができた。
ということで、ようやくApache 2+PHP 5.1.4+MySQL 4.1な環境を構築できたんだけど、まだテスト環境ができたってだけで、開発環境はこれから作らなきゃならないんだよなー。今度こそ挫折せずに最後までたどり着けるだろうか?
そういやcolinuxとWindows間のファイル共有はsambaを使うのが基本なのかな? あと、ネットワークはTAP(ネットワーク共有)にした。ノートとかで移動しながら使うのには、これが一番扱いやすいっぽい?
ファイル共有は
cofsでWindowsのファイルシステムを直接マウントして、作業ドライブとしてはそこを使うのがよさそう。
だめだ
cofsでマウントしたドライブは、読み込みには使えるけど、書き込みにはまともに使えないっぽい。
*1 qdbm-1.8.62は入ったんだけど、hyperestraier-1.3.3の方のmakeがCB_LIST_〜がどうとかいうエラーで止まる。って正確なメッセージをメモるの忘れた
2006-07-27 [長年日記]
_ メモ、URI検索結果のフィードを用意しました
この間追加した「おすすめURI」の進化の方向をいろいろ考えていて、タグの好みを学習させていって(関連タグを並べて[好き][嫌い]をクリックさせていくとか)それを検索キーにすればいいんじゃね、とかいろいろ試していたんだけど、なんかごちゃごちゃやっているうちに、そんなんだったらふつうにエゴサーチをやりやすくした方が話が早い気がしてきた。
というわけで、メモ検索およびURI検索にフィードを追加しました。右上に[FEED]アイコンがあるんでそちらからどうぞ。
ちなみにメモ検索は、1470.netに登録されたすべてのメモに対する全文検索で、URI検索は、メモやblogmapで収集しているフィードからリンクされたURIに対しての全文検索ね。
このサイト/サイトがリンクする先も検索対象に入れたいって場合は、自分のblogmapにそのサイトのフィードを登録しておけば、そのうち検索対象に含まれるようになります。
検索条件の指定方法は、HyperEstraierの簡便書式に準じます。ふつうに半角スペース区切りでキーワードを追加していくとアンド条件。ノット条件はキーワードの頭に「!」。オア条件は「|」で、アンド条件よりも優先順位が高くなります。ソートオーダーは新着順固定です。
2006-07-31 [長年日記]
_ 登録日を指定したメモ一覧取得API
メモ情報取得APIに、ユーザーと登録日を指定し、特定のユーザーが特定の日に登録したメモ一覧を取得するAPIを追加しました。
登録日指定メモ一覧取得
- URL - http://1470.net/api/memo/daily
- パラメータ(QUERY_STRING)
- userName - 1470.netユーザーID(省略可)。指定すると、そのユーザーのメモ情報のみが対象となる。
- day - 登録日(YYYY/mm/dd形式推奨。省略可)。省略すると当日(APIを呼び出した日)となる。
- リクエストメソッド - GET
- 戻り値
- データ形式 - JSON
- 例 {"result": [{"id" : 998, "updt" : "2006-06-30 02:16:20"}, {"id" : 999, "updt" : "2006-06-30 02:16:21"}, ...]}
- result.* - 各項目
- id - メモID。メモにつけられたユニークなID。
- updt - メモの更新日時(JST)
- ソートオーダー
- rgdt asc, id asc。
- 例
- 呼び出し: http://1470.net/api/memo/daily?userName=ishinao&day=2006/7/30
- 結果: {"result" : [{"id" : 67803, "updt" : "2006-07-30 08:29:57"}, {"id" : 67804, "updt" : "2006-07-30 08:31:41"}, {"id" : 67862, "updt" : "2006-07-30 22:46:56"}]}
_ W-ZERO3[es]買った
ビックカメラに行ってみたら機種変で黒の在庫があるというんで、W-ZERO3初代から機種変更。まだ最低限のセットアップをしただけで、全然使ってないけど、ひとまず持ちやすくなったってだけでも、初代よりずいぶんましな感じ。ただ、持ちやすくなった反面、サイドのボタンの誤爆が増えそう。
契約を変更してみた
今まではつなぎ放題+A/B割+年間契約(3年超)だったんだけど、今度はウィルコム定額+データ定額にしてみた。これでひとまずどのくらいパケット通信を使っているのか数字を見てみることにしよう。つなぎ放題契約だと、結局月にどのくらいパケット通信(W-ZERO3単体+PCとつないで)しているのかの数字がよく分からないから、ベンチマーク用の契約として。
_ 文字コード自動判別がなかなか安定しない
URI情報を取得する際に、そのURIで示されるドキュメントの文字コードを判別して処理を行いたいわけだ。ほとんどはHTMLかXHTMLなんで、
- HTTPレスポンスヘッダのcontent-type: text/???; charset=****の部分から取得する
- HTMLヘッダ中の<meta http-equiv="content-type" content="text/html; charset=****">から取得する
- XMLドキュメント先頭の<?xml version="1.0" encoding="*****" ?>から取得する
- 上記すべてが取得できず、なおかつcontent-typeがtext系だった場合は、mb_detect_encodingで文字コード自動判別を試みる
といった感じの処理をしているんだけど、
- content-typeに本来の文字コードとは異なる適当な(たぶんhttpdデフォルト設定のまま)charsetをつけてくる場合は結構ある
- 実際の文字コードと、HTMLヘッダやXMLヘッダの文字コード宣言とが違っている場合が結構ある(文字コードの設定を変えたけど、テンプレートは直してない、とかかなー)
- 文字コードとして無効な内容(各種typo、SHIFT_JISじゃなくてSHIFT-JISになっている、無指定のつもりでnoneという文字列が指定されている、など)がセットされている
なんて場合があって、なかなか文字化けを根絶することができない。最初のうちはできるだけまっとうなロジックの範囲で、そういう場合にもそれなりの結果が得られるような対応をしていたんだけど、限界を感じてきたんで、微妙にアドホックな手段が混ざりはじめてきた。
というわけで、そのあたりを自分で設定可能なみなさま、設定が正しいかどうかを見直していただけるといろいろと助かります。
そういや、おそらく複数のhttpdで分散処理をしていて、リクエストを投げるたびに違ったヘッダが返される(外れを引くと文字化けする)という例もあったなー。


Before...
_ ishinao [>nijimuさん 追加しておきましたので、試してみてください。]
_ ishinao [と、手動登録したら、とたんにTypeKeyが復活した模様。]
_ nijimu [ありがとうございます。無事ログイン成功しました。その途端にTypeKey復活しなくても……。]