Hatena::ブログ(Diary)

大風呂ダ敷 このページをアンテナに追加 RSSフィード Twitter

2013-09-12

「sirogane」version 2013/08/31 05:14:39 主にhtmlやfeedの解析アルゴリズムの強化。ラベル型配列とか数値文字参照とかルート相対パスとか色々。


ミユ「GUIの見た目上シークバーのログ内検索が追加されてますがfeed(RSS,Atom)の解析向上に力入れてました。

シークボールの下にある虫眼鏡アイコンをクリックすると
f:id:ooblog:20130911082152p:image

検索ワード入力。
f:id:ooblog:20130911082149p:image

表示中のログの中から検索(双眼鏡アイコン予定のログ全体検索は未実装)。
f:id:ooblog:20130911082146p:image

フレア「未来記事が存在するブログは毎回手動で日付操作しなきゃならならんの?

URLをコピペ
f:id:ooblog:20130911083346p:image

URLで検索
f:id:ooblog:20130911083343p:image

日付変更がfavicon.ltsvでも可能になってたので取りあえずミク誕6歳。
f:id:ooblog:20130911083341p:image

日付変更してからのRSS取得。
f:id:ooblog:20130911083337p:image

siroganeは未来のフィードがRSSに流れて来た時どうするよ。
f:id:ooblog:20130911083334p:image

ミユ「未来feedを読み飛ばしたり過去feedをあえて拾い直すモードの追加はreadmeに書いてないけど次回更新に回す予定。まだ日付で篩にかける処理が怪しい挙動ではあるし。」

フレア「今回の更新で「fc2」「blogger」で飛び石になってた事と「blogos」のRSSが数値文字参照だった事と「ch.nicovideo.jp」からアイコン拾えるようになった…でしたっけ。解説よろ。」
ミユ「飛び石の理由はsiroganeがtitle→link→dateの順番でタグを読み込んでいたのが理由なんですが、ブログサービスによってタグの順番は異なってます(XMLの文法的には問題無い)。

  • hatena
    • title→link→date
  • fc2
    • link→title→date
  • blogger
    • date→title→link

つまり3の階乗(3!=1*2*3)で6パターンが文法上存在します。将来読むべきタグが増えると4の階乗(4!=1*2*3*4)で24パターンに増える恐れもあります。」
フレア「24パターン判定をif文で記述なんてやってられない気がするのですがHSPには解決策はあるのでしょうか。

箱ABCD 4つの変数があり、これらの変数にはさまざまな値が入ってきます。入ってきた値により次に実行する処理を判断しなければなりません。if文を入れ子にして最小限の処理が行われるように実装したところ、入れ子が多いところで4つくらいになってしまいました。
「仕様書」がいわゆるルールベースで記述されているのに、それをC#などの手続き型言語で実装しようとすると入れ子になってしまうことを悩まれているのだろうと思いました。

複雑な条件式でif文の入れ子が多くなってしまう場合について - Insider .NET会議室

米国防総省の給与システムはCOBOLで、700万行に及ぶコードの大半は1960年代に書かれたものだという。
米軍は、二度とコンピュータに落とし込めないような複雑怪奇な給与体系になってるの?←傷病手当の扱いが複雑みたいですね。←そもそも、現在のシステムが正しい給料を出しているのかどうか、誰がどうやって確認したんでしょうか?
COBOLのコード自体が帳票みたいなものだから、単にうまいパーザを作れば1割くらいに縮退しうるんじゃないだろうか。←こういうのこそコンピューターに自動でやらせればいいのに。専用コンパイラのようなものを一つ設計すればいのだから。

COBOLで書かれた米国防総省の給与システム700万行、実質的に更新不可能|スラッシュドット・ジャパン

BANCStarプログラムにおける合法な文字種は、0から9までの数字と,コンマ、マイナス記号、キャリッジリターンだけである。空行は許されていなかった。もし、ファイル内に"."があるならば、コンパイラーはクラッシュする。コメントは厳格に禁止されていた。
コード中のラベルは絶対番地であった。そのため、新しいページが追加されるか削除されるかした場合、以降のGOTOは必ず再調整されなければならなかった。
内部表現を生成するより高級な言語を開発するべきだと思うのだが、なぜかそうはならないで、人間が低級なコードを手書きするようになるとは、悲惨だ。おそらく、長期的な視野がなく、その日その日の目標を達成することだけが評価されるような環境だからこそ起こる悲劇なのだろう。

本の虫: 最悪のプログラミング言語、BANCStar


ミユ「HSPにはラベル型の変数が用意されてるので実行時にプログラムの順番をソートアルゴリズムで入れ替えできます。
説明用に簡略化したソースがこちら。本当ならscrapeTAGptrにはinstrでタグを文字列検索した値(見つからない場合は-1)が入ります。

#const SCRAPETAGMAX       3
#const SCRAPETAGMAXFACT   3  // 3!
 dim    scrapeTAGptr,SCRAPETAGMAX+1: scrapeTAGptr=         3,        2,        1
 ldim   scrapeTAGlab,SCRAPETAGMAX+1: scrapeTAGlab=*feedtitle,*feedlink,*feeddate
 dim    scrapeSORTptrL,SCRAPETAGMAXFACT: scrapeSORTptrL=0,0,1
 dim    scrapeSORTptrR,SCRAPETAGMAXFACT: scrapeSORTptrR=1,2,2

 repeat SCRAPETAGMAXFACT   // sort
  if( scrapeTAGptr(scrapeSORTptrL(cnt))>scrapeTAGptr(scrapeSORTptrR(cnt)) ){
   scrapeTAGptr(SCRAPETAGMAX)=scrapeTAGptr(scrapeSORTptrL(cnt))
    scrapeTAGlab(SCRAPETAGMAX)=scrapeTAGlab(scrapeSORTptrL(cnt))
   scrapeTAGptr(scrapeSORTptrL(cnt))=scrapeTAGptr(scrapeSORTptrR(cnt))
    scrapeTAGlab(scrapeSORTptrL(cnt))=scrapeTAGlab(scrapeSORTptrR(cnt))
   scrapeTAGptr(scrapeSORTptrR(cnt))=scrapeTAGptr(SCRAPETAGMAX)
    scrapeTAGlab(scrapeSORTptrR(cnt))=scrapeTAGlab(SCRAPETAGMAX)
  }
 loop
 repeat SCRAPETAGMAX
  gosub scrapeTAGlab(cnt): if( ptScR<0 ){ break }
 loop
stop

*feedtitle
 mes "「title」"
return
*feedlink
 mes "「link(Atom=alternate)」"
return
*feeddate
 mes "「date(Atom0.3=modified,Atom1.0=updated,RSS1.0=dc:date,RSS2.0=pubDate)」"
return

実際のソースはmes(printf)では無くタグの解析をしていますし、dateを扱うタグが4種類ありさらに日付フォーマットが2種類あります(ISO8601とRFC2822)。

RSS2.0 他のフィードと違い、日付はRFC2822形式(例:Sun, 05 Nov 2006 16:53:33 +0900)。

floatingdays: RSS/AtomフィードのXMLの作り方メモ


フレア「変数swapしてる所がもどかしいこそばゆい」
ミユ「HSPに限らずポインタの使用にはリスクがあるから仕方ないね(HSPにもdupはあるが「有効なのはクローン元の変数に代入が行なわれるまでの間」なのでswapの最中にポインタが移動する恐れがある)。
hspda.dll引っ張ってsortval/sortgetを使う手法も無いわけじゃないけどそこまで大量データのソートじゃないですし。
ちなみにC言語だと関数でもポインタ使えるらしいです。

printf("%d",printf);などとすると、この関数が存在しているアドレスが表示されます。では、関数へのアドレスを持った変数(関数ポインタ)はどのように宣言するのでしょうか。
例えば次のような関数があったとします。int compare(char x,char y); この関数へのポインタは以下のように宣言します。int (*p_compare)(); つまりこれは「戻り値がint型の関数へのポインタp_compare」という意味になります。
では関数ポインタはどのような場合に有効なのでしょうか。主に次の2点が挙げられます。
1.関数の再利用性・汎用性を高めプログラムの量を減らす
2.多数の分岐が存在する条件式における処理を高速にする
switch〜case文ですが・・・実は、下に行くほど真偽の判定回数が多くなってしまいます。全ての条件に同等のコストで条件分岐することは出来ないのでしょうか?そこで登場するのが関数ポインタの配列です。
(配列の数が少なく書ききれる量ならば)int (*switch_func[])() = {func_1, func_2, func_3, func_4, func_5, func_6, func_7, ・・・}; あとはswitch〜case文の場所を次の1行で置き換えます。 switch_func[value](data1, data2);

配列とポインタ(関数ポインタ)



ミユ「siroganeでは今の所文字参照をサポートしてないのですが「blogos」のRSSが数値文字参照を多用して難読化状態だったので、数値文字参照だけとりあえず対応してみようと。
Googleリーダー無き今、(2chまとめアンテナ系とは異なる方向性の)複数のブログをざっくり眺めるのには寄稿系便利なので。

細かい話はさて置いて、この「寄稿(実態としては、ニュースサイト側へ転載を許可し、ニュースサイトが独自の判断でブログから記事を転載する)」に関しては、オリジナルのブログと、寄稿先のメディアとで、同じ記事が重複してしまうという問題があります。
Googleは、コンテンツ重複の対策として、いくつかの提案をしています。METAタグでsysdication-sourceやoriginal-sourceを指定する
どの程度効果があるのかは不明ですが、ニュース記事を複数サイトに配信しているような場合、オリジナルではsysdication-sourceを、配信(寄稿)を受けた側ではsysdication-sourceとoriginal-sourceを指定することで、オリジナルを判別するよ、というものです。
こういう「転載」が、ブロガーにとって何の特にもならない、とは限りません。相手はまがりなりにも商用のメディアですから、記事が評価されたのだと考えていいでしょう。それに、自分のブログの読者とは違う層の多くの人に記事を読んでもらうこともできます。

記事をBLOGOSやガジェット通信に「寄稿」するのはブロガーにとって百害あって一利なしか? :Heartlogic[旧館]

HTMLやXMLには「&」を「&amp;」と表すだけでなく、「&#38;」と数字で表すこともでき、前者を文字実体参照、後者を数値文字参照と呼びます。前者の文字実体参照では表せる文字は限られますが、後者の数字文字参照ではUNICODEで表せる文字ならどんな文字でも表すことができます。
この文字と数値文字参照の相互変換、つまり「☆」を「&#9734;」に変換したり、逆に「&#9825;」を「♡」に変換したりしてくれるスクリプトです。

文字列⇔数値文字参照相互変換ページ | ψ(プサイ)の興味関心空間

HSPで数値文字参照を簡単に実装するにはJScript召喚が簡単なので上記のスクリプトを参考にモジュールtsvtool5.asに記述。
下記のソースは単体テスト兼ダイアリーでもレイアウトが崩れないようにアレンジ。

#module
 #defcfunc JSCharRef str charstr
  sdim retstr,260: sdim _charstr,260: _charstr=charstr
  if( instr(_charstr,0,"&#")>=0 ){
   strrep _charstr,"&#x","&#0x"
   newcom objJS,"ScriptControl": objJS("Language")="JScript"
    objJS->"AddCode" "var conv_regexp=new RegExp(\"&#([0-9A-Fa-fx]+);\",\"gi\");"
regexpcode={"
  \"%s\".replace(
   conv_regexp,function(matchedString,subMatch1){
    return String.fromCharCode(parseInt(subMatch1));
   }
  )
"}
    comres _retstr: objJS->"Eval" strf(regexpcode,_charstr): retstr=_retstr
   delcom objJS
  }
  else{
   retstr=charstr
  }
 return retstr
#global

teststr="&#x6570;&#x5024;&#x6587;&#x5b57;&#x53c2;&#x7167;"
mes teststr
mes JSCharRef(teststr)


フレア「subMatch1ってどっから湧いてきた変数なの。」
ミユ「JavaScriptの正規表現の置換に匿名関数を使ってるだけで、関数が内部で使用する変数は引数も含めて適当な変数名が使えるってだけです。

JavaScriptでは、文字列や数値を引数としてセットするのとまったく同じ要領で、ある関数をそのほかの関数の引数としてセットすることが可能だ。そして、このような関数のことを「高階(こうかい)関数」と呼ぶ。
匿名関数を用いることで、いわゆる「使い捨て」の関数定義を、高階関数を呼び出すコードにそのまま組み込むことができる

連載:Ajax時代のJavaScriptプログラミング再入門:第2回 JavaScriptの関数をマスターしよう 3/4 - @IT

正規表現または検索文字列を使って文字列内のテキストを置換します。stringObj.replace(rgExp,replaceText)
stringObj オブジェクトの名前またはリテラル文字列を指定します。メソッドの戻り値は、置換によって生成される文字列です。
rgExp  正規表現を表すStringオブジェクトまたはリテラル文字列
replaceText Internet Explorer 5.5 以降では、replaceText 引数で、置換テキストを返す関数を指定することもできます。

replace メソッド JavaScript MSDN

関数の第一引数はマッチした部分文字列そのものを保持します。
第二引数として関数を指定するとき、その関数はマッチが完了された後に実行されます(この形式における関数の使用は、しばしばラムダ式と呼ばれます)。
第一引数がRegExpオブジェクトだった場合、それに続くn個の引数は、括弧でキャプチャしたマッチによって記憶されたサブマッチの文字列として使うことができます。最終的な置換が作成される前にサブマッチの結果をさらに変形したい場合、関数を使わなくてはなりません。

String.replace-JavaScript|MDN



ミユ「あと最近までルート相対パスの存在知らなかったので読めなかったfeedが多数あったけどかなり改善されたかと思います。

ふと思った 大規模なサイトはディレクトリ構造をどうしてるんだろう?と
フォルダが増えると「../」が増えてややこしくなってくるし、簡単に階層を変えれなくなってしまう。かといって絶対パスにしちゃうとドメインやフォルダ名に依存しすぎてしまうとか思っていた。だがそんな問題はルート相対パスが解決してくれた。
ルート相対パス これは、「/」から始めるとルートディレクトリを基準にアクセスしてくれるというものである。
具体的には、「http://host_name/」がルートディレクトリだった場合、「/」から始めさえすればどのサブディレクトリからでも「http://host_name/」を基準としてファイルにアクセスできるということである。
全体のサイトを通して使用するcssファイルやjsファイル、画像などはルートディレクトリ直下に作ったフォルダ内に入れて管理することができる。
※あくまでサーバを通さないとブラウザはルートディレクトリを認識してくれないのでApacheなどを使わずローカルで開発している場合、ルート相対パスは使えないのでご注意を。

ルート相対パス!!? | TM Life



フレア「ニコ動のアニメのアイコンってどうなりました?」
ミユ「公式チャンネル(ユーザーブロマガではない)だと「img data-original」みたいな文字列があるのでそっちから拾うように変更。

公式チャンネル特有のこういうアイコンを拾いたい。
f:id:ooblog:20130911081802p:image

方法はRSSの取得と同じでチャンネルのトップをsirofeed.ltsvにドロップ。siroganeを前面に固定するとドロップがかなり安定。
f:id:ooblog:20130911081759p:image

成功すると普段の「favicon.ico」ではなく「icon.nimg.jp/channel/ch*****.jpg」を拾う…はず。
f:id:ooblog:20130911081755p:image

RSSが取得できたら時報の時刻設定。
f:id:ooblog:20130911081753p:image

フレア「はず、というのは?」
ミユ「たまに凝ったレイアウトなチャンネルだとfeed発行されて無さげなので必ずRSSが取得できるとは限らないです。
将来的には、はてなアンテナの上級者向けの範囲指定でも参考にsiroganeの方でも対応したいですね。方言の予感しかしない正規表現に足突っ込むとか今やらないけど。

「○○が含まれる行以下、」「××が含まれる行より上だけをチェック」と、更新をチェックする範囲をブラウザで閲覧できる文字列で指定することができます。
上級者向け設定は同じURLを登録している全ユーザー共通の設定ですので、編集時には他のユーザーの方の迷惑にならないようお気をつけください。上級者向け設定を変更すると、最終変更者のユーザ名が記録・表示されます。

更新をチェックする範囲を指定する - はてなアンテナのヘルプ


フレア「sirogane前面にしたままURLや日付入力などのダイアログを出すとダイアログが裏に回るバグがあるから上記キャプのようにいかないのでは。」
ミユ「体感的にはかなり致命的バグだと重いますが次回更新にさせてくださいorz
現状対策は、タスクバー右クリック経由で入力ダイアログを閉じる→sirogane全面固定解除→入力ダイアログ再表示で治るはずです。
VBScriptのInputBoxと「gsel ginfo_sel,2」みたいなウィンドウ全面とが共存を想定されてないので本当はウィンドウ前面搭載した時点でダイアログ片付けなければならなかったのです。」
フレア「GUI強化ついでに長文quoteをスクロールしなくても読めるように対策よろ。」

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/ooblog/20130912/1378937605