立ったり歩ったり座ったり
2013年の振り返りエントリ。 id:kitone から指令がとんできたのもあり書き出しました。
昨年の振り返りエントリはこんな感じでした。
http://haseharu.hatenablog.com/entry/2012/12/28/231950
- 相変わらずVim使ってた。少しcoda2を試用期間だけ使ってみる。
- kindle paperwhite購入し、電子版で買える本は優先的にkindleで。
- ゲームはDSのゼルダ(大地の汽笛)やって、クリア後FFタクティクス買って放置中。
- 職場では2回も引っ越し。
- イベントは2回くらい行きました。あとは行ってないかも。
- 書評1本書かせてもらったのと、国家資格的なのを2個取得。
- 半年に渡る職場外研修と10月から兼職で。
- 来年の手帳はほぼ日手帳のweeksで続行。
資格試験をけっこう受けていた一年でした。その他にあった事件的なのは、
- ライブ行けなかった事件
- Li:d tech合宿的なのにひとりぼっち事件*1
- 職場外研修一人で参加することに事件
とかでしょうか。
今年はけっこう仕事も生活も変化があった一年でした。
来年、再来年と変わる一年になります。
タイトルは、以前好きだったブログからお借りしました。
「そうは見えないかもだけど、目の前に座ってる人にはそれなりの理由とか気持ちとか背負ってるものがあるんだよ」みたいな意味の文が書いてあったのをふっと思い出したのでそれをなんとなくタイトルに*2。座ったり、立ったり、歩ったり、息を吸って、仕事をして、生活をして1年間。
気づけば、一年を通して、ほとんどどこにも出かけなくなりました。
来年、もしどこかでお会いしたらよろしくお願いします。
CiNii JSONとはてなブログでできること
はじめに
旧CiNiiがCiNii Articlesというサービスとなり、JSONの返戻データの形式も変わってしまったため、このエントリーのコードは動かなくなっていることに気がつきましたので、コード部分だけでも動くように修正をしました。2017/11/6
CiNii APIがJSONに対応しました。
http://ci.nii.ac.jp/info/ja/index_2013.html#20131011-3
id:otani0083 が書いてますので詳細はこちらを。
http://otani0083.hatenablog.com/entry/2013/10/19/162832
さて、おーたにさんの記事はPythonで処理してます。サーバサイドでの処理もいいのですが、せっかくのJSONでXMLHttpRequest対応なんだからJavascriptでしょうここは、と偉そうにコメントしてしまっていたので年内にやっつけでもいいので記事書いてすっきりしたいと思います*1。あとは「JavaScript使える!」と超盛り上がって*2わいわいとLi:d techで先着何名の招待をもらったはてなブログを使いはじめたのが2011/11/24であれから2年経ったということなので、初心に戻ってはてなブログとJavascriptで遊んでみました。
はてなブログからCiNii検索
はてなブログからCiNiiの検索結果を取得する感じの一番オーソドックスな活用方法みたいなのを作ってみました。下の検索窓に入力するとajaxでCiNiiへ検索しにいき検索結果がサジェストされます。サジェストされたタイトルの中から、選択すると、その下の枠に「やっつけCSV形式」で他の書誌事項とともに表示されます。
ソース
はてなブログやホームページなどに貼付けてもらえれば動くと思います。
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"> <script src="http://code.jquery.com/jquery-1.9.1.js"></script> <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script> <script> $(function() { function log( message ) { $( "<div>" ).text( message ).prependTo( "#log" ); $( "#log" ).scrollTop( 0 ); } $( "#cinii" ).autocomplete({ source: function( request, response ) { $.ajax({ url:"http://ci.nii.ac.jp/opensearch/search?", scriptCharset:"UTF-8", data:{ format : "json", title: request.term }, jsonp:"jsoncallback", success: function( data ) { response( $.map( data['@graph'][0]['items'] , function( item ) { return { label: item['title'], value: item['title'], search_result: '"' + item['title'] + '","' + item['link']['@id'] + '","' + item['dc:publisher'] + '","' + item['prism:publicationName'] + '","' + item['prism:publicationDate'] + '"' } })); } }); }, minLength: 2, select: function( event, ui ) { log( ui.item ? ui.item.search_result : "Nothing selected, input was " + this.value); }, open: function() { $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); }, close: function() { $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); } }); }); </script> <div class="ui-widget"> <label for="cinii">Search CiNii:</label> <input id="cinii" size="60"> </div> Powered by <a href="http://ci.nii.ac.jp/">CiNii</a> <div class="ui-widget" style="margin-top:2em; font-family:Arial"> Result: <div id="log" style="height: 500px; width: 600px; overflow: auto;" class="ui-widget-content"></div> </div>
なんでJavascriptなのか
サーバサイド処理が必要ないので、HPに埋め込んだりとかそういうところで活用できるのはメリットだと思います。
おわりに
2013年もあと少しですね*3。
ダイナミックナレッジベースとしてのOJNavi
はじめに
どこでもリゾルバの機能追加。
http://haseharu.org/labs/d_resolve/about.php
Google Scholarを追加し、OJNaviも追加してみました。Google Scholarは通常の検索対象のサービスとして追加し、OJNaviはCiNii Articles上でどこでもリゾルバを使用した場合のみリンクとして出現します。
OJNavi
上と同じく、Web API的なものはないので、スクレイピング対応です。ただし、タイトルではなくCiNii APIを通じてISSNを取得してISSNでの検索をした結果をスクレイピングしてます。Li:d techメンバーからNDL SearchやCiNii Articlesで書誌情報だけは出てくるけど、そこには書誌だけでフルテキストへのリンクがない、検索エンジンでもヒットしづらい論文がある、という声があったので、それならじゃあ、とOJNaviをみなしダイナミックナレッジベースとして取り入れてみました。
“オープンジャーナルナビゲーター(OJNavi)”、公開:無償電子ジャーナルの検索システム
http://current.ndl.go.jp/node/24369
先に書いた通り、CiNii Article上でどこでもリゾルバを起動させた場合しかOJNaviへのリンクはでません。
ちょっと整理
国内のNII,NDL,JSTをはじめとしたサービスへのタイトルベースでの横断検索と検索エンジンとしてのGoogle Scholarへのタイトルベースでの検索、に加えてOJNavi収録の有無をCiNii Articlesからチェックし、OJNaviの示すリソースリンク先までをシームレスにたどれるようになりました。
こまごまと修正
各サービスへの問い合わせは全て「並列」でやっていて高速処理化しています。あと今回、日本語文字列が入っているケースの場合は、Pubmed, arXivへの検索はかけないようにしたので少し処理を軽減。Bookmarkletにバージョンのチェック機能を追加しました。古いバージョンのBookmarkletを使っていると下記のように表示がでます。
おわりに
今回のケースに関してもデータベースとして機能させるのか、ナレッジベースとして機能させるのか、有用なデータがあればあるほど機械可読なシステム設計かどうかの差は大きいと感じています。Web API的なものがなければスクレイピングするだけですが、やはりWeb API的なものを公開して欲しいなあと*1。
*1:という自分が公開していない
どこでもリゾルバの公開
論文名とか書誌情報だけがころっと目の前にあったりなんかして、どこかにフルテキストがないかな、でもあっちもこっちも検索するのはめんどいよね、というシチュエーションで役に立つ仕組みはないかねと思って「Docodemo Resolver β」というものを作ってみました。
Docodemo Resolver β
http://haseharu.org/labs/d_resolve/about.php
起動自体は簡単で、Bookmarklet を作ったのでそれをブラウザに登録しておきます。論文名をテキスト選択した状態でさきほど登録した Bookmarklet をクリックすると中間窓*1が開きます。
下の方は切れていますが画面はこんな感じです。
現在、中間窓に表示されるサービスは「CiNii Articles」「NDL Search」「J-STAGE」「JAIRO」「arXiv」「Pubmed」の6種類です。論文タイトル名をキーに6種類のデータベースに検索をかけます。PDF有無までわかると使いやすいだろうと思ってCiNii Articlesのみ表示させてます*2。中間窓から、フルテキストへ一直線でナビゲートできます。ただし、利用者の契約情報等持っていないので「無料で」見られるかどうか、はクリックするまでわかりません。
リンクリゾルバってサービスの提供側にがっちり組み込まれていて利用範囲が狭いなあ、1対多じゃなくて多対多の仕組みに持ち込めたら便利だよねえ、持ち運べたらいいのに、と思ったのがそもそもの始まり。そこから動的にナレッジベースを作れないかね、と思ったのがそもそもの始まりでぼんやり仕組みだけイメージしていたのですが、某研修で似たような案件があり役立つかなあ、と思い続きを作ってみました。
利用者の契約情報とかはほぼ無視でタイトルドリブンなナレッジベースの一つのカタチとしてありかなあ、と。
機械可読でPDF有無までデータ吐きだすようにしたらダイナミックナレッジベースを名乗ってもいいかなあ、と。
いやいやGoogle Scholarも対象に入れなきゃ使えないよね、と思いつつ、まだ入れてません*3。
あとは、ふつーに横断検索の仕組みとして動くようにしてあります。
「Flat UI」
3ヶ月前にComing soon! とかいいつつ放置してある*1「Red Data Books」ではやりのフラットデザインでやってみるかー、と思って「Flat UI」をカタチだけ使ってみることに。
Flat UI
http://designmodo.github.io/Flat-UI/
Pro版もあるようですが、とりあえずフリーで使える範囲で。
Red Data Books
http://haseharu.org/labs/rdbs/
これ、Bootstrapベースです。
http://getbootstrap.com/
けっこう、使いやすくっていいかもしれません。
*1:いつものこと
「情報管理」をkindleで読む
前に作ったJ-Stageの論文をkindleで読めるよう変換するスクリプトですがいまのところ特に問題なく使えています*1。公開後、図表等の画像もちゃんと表示するように少し手を加えました。
- るるるkindle
http://haseharu.hatenablog.com/entry/2013/03/17/071008
まとめてダウンロードできたら便利かもねえ、と思いつつ。でも全部読むことないし。
1論文あたり3-4MBくらいの容量になるようです。図表等の画像がなければ100-200KB程度。新しいkindle paperwhite欲しいなあとも思いつつ。
*1:といっても情報管理くらいしか読んでないのですが
シェルスクリプト × Web API
シェルスクリプトでWeb API的なものを使うメモ。
たぶんWeb API的なものをつかってデータをがーっともらってくる場合、シェルスクリプトが一番手軽です。
ほんの数行でかけます*1。
たとえば、CiNii API(RDF)を通じてNCIDを使って資料タイトルを取り出す。
1件だけなら1行*2。
curl "http://ci.nii.ac.jp/ncid/AA12227144.rdf" | xpath '//rdf:RDF/rdf:Description/dc:title[1]/text()'
看護・保健科学研究
いいですね。
100件とか1000件とかある場合。while文で。
AA12227144 AA11354292 AN00023058 AN10507651
NCIDを別ファイル(ncid.txt)で用意しておいて、
while read id do DATA=$(curl "http://ci.nii.ac.jp/ncid/${id}.rdf") TITLE=$(echo ${DATA} | xpath '//rdf:RDF/rdf:Description/dc:title[1]/text()') echo ${id}'\t'${TITLE} >> ncid_result.txt done < ncid.txt
で回します。
AA12227144 看護・保健科学研究 AA11354292 千葉看護学会会誌 = Journal of Chiba Academy of Nursing Science AN00023058 榮養學雑誌 AN10507651 日本精神科看護学会誌
無事データとれてます。
他にもたとえば、dc:languageあたりもとりたいよ、という場合、
LANGUAGE=$(echo ${DATA} | xpath '//rdf:RDF/rdf:Description/dc:language/text()')
で追加していけばおっけーです。
NCIDのマッチングが失敗した場合、別途失敗したNCIDをncid_false.txtに書き込む処理をif文で組み込んでみます。
while read id do DATA=$(curl "http://ci.nii.ac.jp/ncid/${id}.rdf") FLAG=$(echo ${DATA} | grep 'DOCTYPE html') if [ "${FLAG}" == "" ] then TITLE=$(echo ${DATA} | xpath '//rdf:RDF/rdf:Description/dc:title[1]/text()') LANGUAGE=$(echo ${DATA} | xpath '//rdf:RDF/rdf:Description/dc:language/text()') DATE=$(echo ${DATA} | xpath '//rdf:RDF/rdf:Description/dc:date/text()') OWNERCOUNT=$(echo ${DATA} | xpath '//rdf:RDF/rdf:Description/cinii:ownerCount/text()') echo ${id}'\t'${TITLE}'\t'${LANGUAGE}'\t'${DATE}'\t'${OWNERCOUNT} >> ncid_result.txt else echo ${id} >> ncid_false.txt fi sleep 1 done < ncid.txt
AA12227144 看護・保健科学研究 jpneng 2001 5 AA11354292 千葉看護学会会誌 = Journal of Chiba Academy of Nursing Science jpn 1996 49 AN00023058 榮養學雑誌 jpn 1941 406 AN10507651 日本精神科看護学会誌 jpn 1990 82
実はCiNiiでRDF取得する場合、失敗したときの値はxmlで返ってきません。「html」で表示されるため失敗時の条件判断は「grep 'DOCTYPE html'」で判定、という感じにしてあります。