「XPath」を含む日記 RSS

はてなキーワード: XPathとは

2022-05-06

[]RStudio最新版インストールするスクリプトを書いた(Debian/Ubuntu)

RStudioがPCから気がついたら消滅していたので何回もやり直すのが面倒で書いた

Debian/Ubuntubash

コメントアウトをいじればFedoramacOSでも動くと思う

https://pastebin.com/HiPqLVq7 (6/4 shコマンドでも動くように修正 以前はbash hogehoge起動していたので動作確認していなかった)

エラーでここに貼れなかった

実行したディレクトリダウンロードする

パッケージインストールするのでsudoとかが必要

必要パッケージについて(コメントアウトオフに)

util-linux(rev) libxml2-utils(xmllint) gpg curl coreutils(sha256sum)とR関連

  1. rev まずデフォルトで入っている 文字列を逆さまにするコマンド
  2. xmllint 同上 xpathを扱えるコマンド(xmlを扱うコマンド) Debianでは入っていなかった
  3. gpg 同上 署名関連 これがないとインストール出来ない環境もある
  4. curl 同上 getリクエストとかを送れる bashだけでHTTPとかを送るのは苦痛なので
  5. sha256sum 同上 ハッシュ値確認
  6. R関連 これがないと動かない
コード関連備考
xmllint
echo "$HTML" | xmllint --nowarning --xpath hogehoge --html - | hogehoge

こうしないとxmllintがエラーでhtlmなどをうまく読み取らない

sed 's/href="//g;s/"//g;s/\s/\n/g;s/^.?$//g;s/^\n//g'

href="hogehoge"の形で出てxmllint内で除去出来なかったのでsed妥協

hrefが1回しか出ないのでひとまとめにできそうだが面倒なので分けた

この書き方なら複数回出ても除去できるはず

先頭の謎のスペースの除去が面倒だった

sha256sum
echo "$HASH"  "$FIELNAME" | sha256sum --status -c ;echo $?

スペースが2つないと書式で怒れられてハッシュ値が合っていてもsha256sumが終了ステータス0で正常終了を返してくれない

使ったツール

VScodium

ShellCheck

https://open-vsx.org/vscode/item?itemName=timonwong.shellcheck

XPath Helper

https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl

最後

zenn.devに書こうか迷ったがどちらの方が良かったのだろうか…

ダウンロードしたサーバーがやられてるならハッシュ値改ざんするだろうgpgで確認しないと意味ないでしょとかsudoでやったらディレクトリがとか色々ガバあるからかいい感じに改良して

参考

https://cran.rstudio.com/bin/linux/debian/

https://www.rstudio.com/code-signing/

https://www.rstudio.com/products/rstudio/download/

2014-04-24

システムテストの方が効率良いって言ってるけど

http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html

を読んでみたんだけど、これも結構理想論な気がすんだよな。

デザイナが全員HTML構造気にしてくれる訳でもないし、

歴史のあるサイトだったりすると読んでも意味の分からないユーティリティ的なセレクタがよく出てくる。

こういうのが現実

page.has_selector?(:xpath, '//table.tokushu1/tr.header/td[3]/div/div//span.click_left')

しかもA/Bテストが始まったりしてテスト書く負荷が高くなりメンテできなくなる。

ただスマートフォンアプリはデザイナがレイアウトいじる事が少ないので、

システムテストだけでもかなりテスト品質は保てる。

2013-08-04

wikiのビューアアプリについて

最近ゲームwikiスマホタブレットで見る機会が多くて

wikiのビューアアプリとか無いのかと探した結果

ゲームwikiアプリ

にたどりついた

任意wikiURLを登録出来るものかと思って入れてみるも

予め登録されているものの中から選ぶ仕様だった

海外はどうか知らないけど)wikiを探していると比較@wikiを見る機会が多いか

そこの共通するフォーマットを落とし込めば閲覧できるwikiの数は一気に増えるのにと思いつつ

出来ない理由があるのだろうといくつかの@wikiソースを見たところ

同じサービス内にもかかわらずメニューのxpathがそろっていなくてびっくりした

せめて位置ぐらいと思ったけどそれなら

ページURL、そのページの最終更新日サイズ

情報を(メニューも一つのページ情報として)全ページ分吐き出してれば

更新日なりサイズなりが違っているページ、新しく増えたページだけを取りに行く

ってアプリが作られそうな気がするんだけどな

見ようとするたびに読込み直されるのは面倒だよね

2013-06-30

AutoPagerizeを連番URLでも使えるようにする

page-1 page-2 page-3みたいなやつ

autopagerize incrementalでググるとそれっぽいのが出てくる

こんなかんじの記述Autopagerize適当場所に追加したら連番URLでも使えるようになるはず

var pages = getElementsByXPath(this.info.pageElement, htmlDoc);

var url = this.getNextURL(this.info.nextLink, htmlDoc);

if (this.info.incremental) {

var exp = new RegExp(this.info.incremental.nextMatch,'i');

var _m = this.info.incremental.nextLink;

var step = this.info.incremental.step || 1;

url = this.requestURL.replace(exp,function(m0,m1){

var n = parseInt(m1,10) + step;

return _m.split('#').join(n);

});

}

var next = getFirstElementByXPath(xpath, doc);

if (next) {

if (this.info.incremental) {

var loc = this.requestURL || location.href;

var exp = new RegExp(this.info.incremental.nextMatch,'i');

var nextLink = this.info.incremental.nextLink;

var step = this.info.incremental.step || 1;

if (loc.match(exp)) {

return loc.replace(exp,nextLink.replace("#",parseInt(RegExp.$1)+step));

} else if (!loc.match(exp)) {

return loc + nextLink.replace("#",step);

}

} else {

return next.getAttribute('href') || next.getAttribute('action') || next.getAttribute('value');

}

}

連番に適応するSITEINFOはこんなかんじになる

pageelementは普通のsiteinfoと同じ

nextlinkはリンクをたどるわけじゃないので意味ないのだが一応書いておく必要があるので'//a'とでも書いておけばいい

url: '^http://matome\.naver\.jp/odai/'

,incremental: {

nextMatch: 'page=(\\d+)'

,nextLink: 'page=#'

}

,pageElement: '//div[@role="main"]'

,nextLink: '//a'

サンプル

http://matome.naver.jp/odai/2135645268395674701

2012-12-12

Ruby on Railsアダルトサイト作ったよー

例に漏れ件のエントリーに影響を受けまして、Ruby on Rails を利用したサービスを作ってみました。

一つもアクセスがないため宣伝ついでに利用したgem作成する際に参照したサイトを載せますので、「Rails初心者っす」とか、自分と同じく「そもそもプログラミングとか知らねっす」という方はちょっとしたナレッジとしてご活用くださいまっせ。開発ガンガンやってる方には価値ある情報たぶんないよー。

作った人

とどのつまり性的健康青年休職中で暇でした。

作ったもの

シコったサイトクリップするのでシコリップ

動機

シコったオカズウェブ上にクリップするサービスで問題解決?

開発環境

最初Mac標準のエディタで書いてたけど、どこかの記事を読んでからは「Sublime Text 2 (http://www.sublimetext.com/)」に乗り換えました。すごく…便利です…。ターミナルMac標準のアレです。オススメがあったら教えてください。

gem

プロセス

完成までにやったこと、実装するために参考にしたサイトを並べます

RubyRails環境を構築する。(http://www.oiax.jp/rails/rails3/install.html)

簡単にウェブアプリの土台を作れるScaffoldという機能を使って遊んでみる。(http://www.techscore.com/tech/Ruby/Rails/quick-start/Rails4/4-1)

行き詰まったので本を買う。(たのしRubyRuby on Rails 3 アプリケーションプログラミングRails 3 レシピブック)(※ 同タイミングで買ったわけではないです。簡単にウェブアプリを作るだけなら「Ruby on Rails 3 アプリケーションプログラミング」とインターネット接続できる環境があれば十分だと思います。ていうか他の二冊はまだ全部読んでない。)

ひと通り分かった気になり、作りたいものを作る作業へ。

$ rails new sicolip

こちらを参考にシコシコ適用

色んなgemがあって迷う。

・Device(https://github.com/plataformatec/devise)
・omniAuth(https://github.com/intridea/omniauth)

でも、

・Deviceはメールアドレスでの認証
・omniAuthはtwitter/fb認証

個人的に

エロサイトメアドを登録したくない
・エロサイト認証twitter/fbってなんか怖い

ということで、自前で実装。has_secure_password(gem:bcrypt-ruby) を利用する。

ここここを参考に。

サイトクリップURL投稿)したときに該当するサイトタイトルとか内容を取得する処理。

Nokogiri::HTML(open(target_url))

こんな感じでNokogiriオブジェクトを取得して、

return doc.xpath('//title').text

こんな感じでタイトルを取得する。こちらxpathほかのお勉強

ログインしている人にしかクリップURL投稿)をさせたくない。そんなときに使える認可処理。

cancanの実装はここここを参考に。

クリップしたサイト情報タグ管理したい。タグ機能の実装を手抜きできるのがこのgem

https://github.com/mbleigh/acts-as-taggable-on

http://prototype-beta.com/tags/acts-as-taggable-on

上記を参考に。

クリップしたサイト情報タイトルや内容、またはタグから検索したい。

その処理を手抜きさせてくれるのがsunspotさんサーバデプロイしたあとに

$ rake sunspot:solr:start

するのをよく忘れて動かない><ってなります

http://railscasts.com/episodes/278-search-with-sunspot?language=ja&view=asciicast

http://outoftime.github.com/sunspot/docs/

will_pagenateっていうgemもあるんだけど、kaminariが最近流行りらしい。

https://github.com/richardiux/sunspot_with_kaminari

クリップするためにこのサイトに飛ぶのちょっとめんどくさい。

ということで、はてなブックマークみたいなブックマークレットを作る。

http://d.hatena.ne.jp/ky2009/20090108/1231405893

herokuとやらが設定周りの色々めんどくさいことを肩代わりしてくれるという噂。しか無料

→ sunspotが有料オプションでした。やめる。

AWSというAmazonサービスが設定によっては無料らしい。

→ ほんとに無料だった。AWS内のElastic Beanstalkというサービスが、herokuみたいにめんどくさいことを色々やってくれる。

http://blog.serverworks.co.jp/tech/2012/06/28/aws-elastic-beanstalk/

http://qiita.com/items/811cd9b614d8d300628e

おわり

そんなこんなで出来上がったもの陳腐ものかもしれませんが、まがいなりにもひとつサービスができました。ここ1カ月だらーっとRubyRailsをさわってみて感じたことは、ウェブアプリを作るのって特別なことじゃないんだなーっていう。どこかで誰かも言ってましたけど、開発している最中パズルを解いてる感覚でした。ウェブに転がるピースを探して、フレームワークにあてはめていくようなそんな感覚

おしまい

2011-04-02

play on tumblr 動いてる?

via http://coderepos.org/share/browser/lang/javascript/userscripts/playontumblr.user.js?rev=38679 | text post image open : http://gyazo.com/0722c749cb50c704d4e9923bdd6b6fce.png -> http://gyazo.com/e8f082af69a038e0ea58775c2cec7ad5.png — Gist

最新はこれでいいんですか?

誰も話題にしてないので俺だけかな

reblogcount しか動いてなかったので自力で直そうと頑張ってみたが、

よくわからないのでぐっちゃぐちゃになってしまった

プログラミング素人ですすみません

一応動画再生画像の拡大2種の3つに関しては動くようにできた

likeは使ってないのでとくに見てませんすみません

ここがわからない
if (img[n].style.display != 'none') {
  click($X('./a', img[n])[0]);
  return stdin;
}
else{
  click($X('./preceding-sibling::a[1]', img[n])[0]);
  return stdin;
}

および

if (mov[n].style.display != 'none') {
  click($X('.//a', mov[n])[0]);
  return stdin;
}

これは何をしてるんでしょうか?

したままだとどうもうまくいかなかったので丸ごと削ってしまった

クリックすべき要素を直接XPath指定、にしたんだけどマズイ?

以下patchです

@include に www.tumblr.com/queue* も勝手に足してしまいました

どなたかまともにしてくださいm(__)m

--- 20101127_play_on_tumblr.user.js
+++ 20110402_play_on_tumblr.user.js
@@ -6,6 +6,7 @@
 // @include        http://www.tumblr.com/show/*
 // @include        http://www.tumblr.com/tumblelog/*
 // @include        http://www.tumblr.com/tagged/*
+// @include        http://www.tumblr.com/queue*
 // ==/UserScript==
 
 (function() {
@@ -43,25 +44,15 @@
         command: function(stdin) {
           try {
             if (!stdin.length) stdin = execute('current-node');
-            var img = $X('.//div[starts-with(@id, "highres_photo")]', stdin[0]);
+            var img = $X('.//img[contains(@id, "thumbnail_photo_")]', stdin[0]);
             for (var n = 0; n < img.length; n++) {
-              if (img[n].style.display != 'none') {
-                click($X('./a', img[n])[0]);
-                return stdin;
+                click(img[n]);
               }
-              else{
-                click($X('./preceding-sibling::a[1]', img[n])[0]);
-                return stdin;
-              }
-            }
-            var mov = $X('.//div[contains(@id,"watch_") and .//a]', stdin[0]);
+            var mov = $X('.//img[contains(@id,"video_thumbnail_")]', stdin[0]);
             for (var n = 0; n < mov.length; n++) {
-              if (mov[n].style.display != 'none') {
-                click($X('.//a', mov[n])[0]);
-                return stdin;
+                click(mov[n]);
               }
-            }
-            var timg = $X('.//img[contains(@src,"tumblr.com/tumblr_")]|.//img[@class="inline_external_image"]', stdin[0]);
+            var timg = $X('.//img[contains(@class, "inline_external_image")]', stdin[0]);
             for (var n = 0; n < timg.length; n++) {
               click(timg[n]);
             }

2009-06-17

やっぱLLだな

SQL + Perl/Python/Ruby/Java + JavaScript + CSS + HTML、おまけにXMLとかJSONとかYAMLとか。DOMとかXPathとか。

2009-06-13

ugigiの検索結果から作品へのリンクを生成するGreasemonkeyを作ったよ

http://anond.hatelabo.jp/20090611195327

javascriptが全然分からないのでググりまくってなんとかできた。

XPathで要素の指定をもうちょっとなんとかするとか、今後の課題は多い。

&になっている箇所は&に置換して下さい。

あと、ugigiの検索結果をAutoPagerで自動的に読み込むようにしようと挑戦してみたものの挫けたよ。

どのようにnextlinkを指定すれば上手く行くのだろう。

// ==UserScript==
// @name           ugigi link test
// @namespace      http://anond.hatelabo.jp/
// @include        http://ugigi.dvrdns.org/?*
// ==/UserScript==

var sakuhin = document.getElementsByClassName('sakuhin');
for (var i = 0; i < sakuhin.length; i++) {
	var relatedurl = unescape(sakuhin[i].getElementsByClassName('link')[0].childNodes[0].href);
	var siteinfotext = sakuhin[i].getElementsByClassName('sinfo')[0].getElementsByTagName('a')[0].text;
	var linkurl = genurl(relatedurl, siteinfotext);
	if (linkurl != null) {
		var a = document.createElement('a');
		a.textContent = 'Link';
		a.href = linkurl;
		var title = sakuhin[i].getElementsByClassName('title')[0];
		title.appendChild(a);
	}
}

function genurl(relatedurl, siteinfotext) {
	match = relatedurl.match(/\/([a-z_]+)(\d*)\/(\d+$)/);
	var board = match[1];
	var boardnum = match[2];
	var idnum = match[3];
	var lognum = siteinfotext.match(/\d+$/);
	var url;
	switch (board) {
		case 'ssw_l':
			url = 'http://coolier.sytes.net:8080/sosowa/ssw_l/?mode=read&amp;amp;key=' + idnum + '&amp;amp;log=' + lognum;
			break;
		case 'ssw_p':
			url = 'http://coolier.sytes.net:8080/sosowa/ssw_p/?mode=read&amp;amp;key=' + idnum + '&amp;amp;log=' + lognum;
			break;
		case 'compe':
			url = 'http://www10.atpages.jp/thcompe/compe' + boardnum + '/?mode=read&amp;amp;key=' + idnum + '&amp;amp;log=0';
			break;
		case 'yotogi':
			url = 'http://yotogi.com/yotogi/?mode=read&amp;amp;key=' + idnum + '&amp;amp;log=' + lognum;
			break;
		case 'comp':
			var nechocompenum = siteinfotext.match(/[一二三四]/);
			switch (nechocompenum[0]) {
				case '一':
					url = 'http://easy2life.sakura.ne.jp/necho/comp/anthologys.cgi?action=html2&amp;amp;key=' + idnum;
					break;
				case '二':
					url = 'http://easy2life.sakura.ne.jp/necho/comp2/anthologys.cgi?action=html2&amp;amp;key=' + idnum;
					break;
				case '三':
					url = 'http://green.ribbon.to/~ronron/comp/?mode=read&amp;amp;key=' + idnum + '&amp;amp;log=';
					break;
				case '四':
					url = 'http://green.ribbon.to/~ronron/comp4/?mode=read&amp;amp;key=' + idnum + '&amp;amp;log=0';
					break;
				default:
					url = null;
					break;
			}
			break;
		default:
			url = null;
			break;
	}
	return url;
}

2009-01-29

人力検索はてなで見たくない質問を見えなくするスクリプト 「いないいない」

// ==UserScript==
// @name          inai_inai
// @description	  人力検索はてなで見たくない質問を見えなくするスクリプト  「いないいない」 
// @include       http://q.hatena.ne.jp/list*
// @version       0.1
// ==/UserScript==

(function(){
  // 見たくない質問をテーブルから削除する場合は true を、
  // 見たくない質問のテキストの色を白にする場合は true を指定して下さい。
  var delRow=false;
  var xpath ='//*[@class="questionlisttable"]';
  var tbody = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  var rows = tbody.rows;
  
  // denies の定義を修正して見たくない質問のユーザIDを追加して下さい。
  // 例) var denies=['inai_inai','tabun_inai','kitto_inai'];
  var denies=['inai_inai'];
  for(var i=rows.length-1;i&gt;=1;i--){
    var name=rows[i].cells[5].childNodes[0].toString().match(/http:\/\/q\.hatena\.ne\.jp\/(\S*)\//)[1]
    for(var j=0;j<denies.length;j++){
      if(name==denies[j]){
        if(delRow){
          // delete row
          tbody.deleteRow(i)
        }
        else{
          // change color of text
          // question
          rows[i].cells[1].childNodes[1].style.color="white";
          // point
          rows[i].cells[3].style.color="white"
          // userid
          rows[i].cells[5].childNodes[0].style.color="white";
          // time
          rows[i].cells[6].style.color="white";
        }
        break;
      }
    }
  }
}
)();
簡単な説明
これは何?

人力検索はてな?」で見たくない質問を見えなくする greasemonkey スクリプトです。

これを使うと、あらかじめ設定したユーザーIDの人の質問を見えなくすることが出来ます。

greasemonkey とは?

greasemonkey とは Mozilla Firefox 上で動作するアドオンです。Google で検索するとたくさんヒットするので使いたい方は調べてみて下さい。

見たくない質問のユーザIDを指定するには?

スクリプト中の

var denies=['inai_inai'];

の部分を

var denies=['inai_inai','tabun_inai','kitto_inai'];

のように変更して下さい。このようにすると、id:inai_inai、id:tabun_inai、id:kitto_inai がした質問が見えなくなります。

質問が見えなくなるとは?

既定では、設定したユーザIDがした質問に該当するTableの文字色を白にすることで見え難くします。

スクリプト中の

var delRow=false;

の部分を

var delRow=true;

にすると、Tableから該当する質問自体を削除することで見えなくなります。

ここでいう「削除」とは、人力検索はてな?から削除する訳ではなく、ブラウザ上で見えなくしているだけです。だから、greasemonkey の設定でこのスクリプト削除したり、greasemonkey を無効にすればまた表示されるようになります。

注意点は?

このスクリプト文字コードUTF-8 にしておかないとスクリプトインストールの時に文字化けします。

ライセンスは?

The BSD License に準じます(http://opensource.org/licenses/bsd-license.php)。

サポートは?

人力検索はてな?で質問してみたらどうでしょうか。ただし、このスクリプトを最初に書いた人が答えるとは限らないと思います。

2008-07-22

[]関連エントリーのツリーをたどれるグレモン

結局概要表示機能追加した。unsafeWindow使いまくり大丈夫かいな。

// ==UserScript==
// @name	Hatena Bookmark Tree Expander
// @namespace	http://anond.hatelabo.jp/
// @include	http://b.hatena.ne.jp/entry/*
// ==/UserScript==
// <div class="info">
//   <ul id="similar_entries" class="bookmarklist">
//     <li></li>
//   </ul>
// </div>
// <div class="info">
//   <ul id="referred_entries" class="bookmarklist">
//     <li id="referred-entry-\d+"></li>
//   </ul>
// </div>
// <div class="info">
//   <ul id="relation_diary" class="bookmarklist">
//     <li id="diary-{id}-\d+"></li>
//   </ul>
// </div>
(function() {

function main() {
	loadBookmarkCommentViewer();
	similar.prototype.rootAppend();
	referred.prototype.rootAppend();
}

function HBTM(target) {
	this.target = target;
	this.targetXPath = "//ul[@id='"+target+"']/li";
	this.targetRegExp = new RegExp('<ul id="'+target+'"(.|\\s)*?</ul>');
}
HBTM.prototype = {
	openIcon:
		'<img width="15" height="15" class="icon" style="opacity: 0.6" src="http://anond.hatelabo.jp/images/common/open.gif"/>',
	closeIcon:
		'<img width="15" height="15" class="icon" style="opacity: 0.6" src="http://anond.hatelabo.jp/images/common/close.gif"/>',
	loadingIcon:
		'<img width="13" height="13" class="icon" src="http://anond.hatelabo.jp/images/common/loading.gif"/>',
	commentIcon: function(url) {
		return '<img class="hatena-bcomment-view-icon" src="http://r.hatena.ne.jp/images/popup.gif" onclick="iconImageClickHandler(this, \''+url+'\', event);">'
	},
	create: function() {
		this.comment = document.createElement("span");
		this.comment.innerHTML = this.commentIcon($X("string(descendant::a/@href)", this.node).value());
		this.open = document.createElement("a");
		this.open.href = "javascript:void(0)";
		this.open.innerHTML = this.openIcon;
		this.close = document.createElement("a");
		this.close.href = "javascript:void(0)";
		this.close.innerHTML = this.closeIcon;
		this.close.style.display = "none";
		this.loading = document.createElement("span");
		this.loading.innerHTML = this.loadingIcon;
		this.loading.style.display = "none";
		this.node.appendChild(this.comment);
		this.node.appendChild(document.createTextNode(" "));
		this.node.appendChild(this.open);
		this.node.appendChild(this.close);
		this.node.appendChild(this.loading);
		this.open.addEventListener("click", bind(this.openAct, this), false);
		this.close.addEventListener("click", bind(this.closeAct, this), false);
	},
	openAct: function() {
		this.open.style.display = "none";
		if (this.tree) {
			this.tree.style.display = "block";
			this.close.style.display = "inline";
		} else {
			this.loading.style.display = "inline";
			this.load();
		}
	},
	closeAct: function() {
		if (this.tree) {
			this.tree.style.display = "none";
			this.close.style.display = "none";
			this.open.style.display = "inline";
		}
	},
	load: function() {
		var url = $X("string(descendant::a[starts-with(@href, '/entry/')]/@href)", this.node).value();
		GM_xmlhttpRequest({
			method: "GET",
			url: "http://b.hatena.ne.jp"+url,
			onload: bind(this.loadCallback, this)
		});
	},
	loadCallback: function(result) {
		var match = result.responseText.match(this.targetRegExp);
		if (match) {
			var sandbox = document.createElement("div");
			sandbox.innerHTML = match[0].replace(this.target,"");
			this.tree = sandbox.firstChild;
		} else {
			this.tree = document.createElement("ul");
		}
		this.append();
		this.loading.style.display = "none";
		this.close.style.display = "inline";
	},
	append: function() {
		this.tree.style.backgroundColor = "transparent";
		this.tree.style.listStyleType = "circle";
		this.node.appendChild(this.tree);
		$X("li", this.tree).each(function(n) {
			var a = $X("a",n).node();
			var c = $X("count(//li/a[@href='"+a.href+"'])").value();
			if (c > 1) n.parentNode.removeChild(n);
		});
		$X("li", this.tree).each(bind(function(node){new this.constructor(node)}, this));
	},
	rootAppend: function() {
		$X(this.targetXPath).each(bind(function(node){new this.constructor(node)}, this));
	}
};

function similar(node) {
	this.node = node;
	this.create();
}
similar.prototype = new HBTM("similar_entries");
similar.prototype.constructor = similar;

function referred(node) {
	this.node = node;
	this.create();
}
referred.prototype = new HBTM("referred_entries");
referred.prototype.constructor = referred;

function loadBookmarkCommentViewer() {
	var head = document.getElementsByTagName("head")[0];
	var script = document.createElement("script");
	script.type = "text/javascript";
	script.src = "http://b.hatena.ne.jp/js/BookmarkCommentViewerAllInOne.1.2.js";
	head.appendChild(script);
	var css = document.createElement("link");
	css.rel="stylesheet";
	css.href="http://d.hatena.ne.jp/css/base.css";
	css.type="text/css";
	css.media="all";
	head.insertBefore(css, head.firstChild);
	window.addEventListener("load",function(){
		var BCV = unsafeWindow.BookmarkCommentViewer;
		BCV.options['screenshot'] = true;
		var asyncCommnetView = BCV.asyncCommnetView;
		BCV.asyncCommnetView = function(url, onCompleteCallback) {
			var div = asyncCommnetView(url, function(){
				onCompleteCallback.apply(this, arguments);
				new unsafeWindow.Ten.XHR("http://b.hatena.ne.jp/entry/rss/"+url, {}, function(result) {
					if (! result.responseText.match(/<description>(.*?)<\/description>/))
						return;
					if (! RegExp.$1)
						return;
//					var desc = document.createTextNode("desc: "+RegExp.$1);
					var desc = document.createElement("li");
					desc.appendChild(document.createTextNode("desc: "+RegExp.$1));
					div.lastChild.insertBefore(desc,div.lastChild.getElementsByTagName("li")[0]);
				});
			});
			return div;
		};
		BCV.asyncCommnetView.origin = asyncCommnetView;
	}, false);
}

function bind(f,o) {return function() {return f.apply(o, arguments)}}

function $X(xpath, context) {
	if (!(this instanceof $X))
		return new $X(xpath, context);
	this.xpath = xpath;
	this.context = context || document;
}
$X.prototype = {
	evaluate: function() {
		var result = document.evaluate(this.xpath, this.context, null, this.type, null);
		switch (result.resultType) {
			case XPathResult.STRING_TYPE : return result.stringValue;
			case XPathResult.NUMBER_TYPE : return result.numberValue;
			case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
			case XPathResult.FIRST_ORDERED_NODE_TYPE: return result.singleNodeValue;
		}
		return result;
	},
	node: function() {
		this.type = XPathResult.FIRST_ORDERED_NODE_TYPE;
		return this.evaluate();
	},
	value: function() {
		this.type = XPathResult.ANY_TYPE;
		return this.evaluate();
	},
	each: function(func) {
		this.type = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE;
		var result = this.evaluate();
		for (var i=0; i<result.snapshotLength; i++)
			func(result.snapshotItem(i));
	}
};

main();

})();

2008-06-27

http://anond.hatelabo.jp/20080627085010

ご紹介いいただいたgreasemonkeyインストールすると、特定IDの「このエントリーを含む日記」を非表示にすることができるのですか?

舌足らずでした。

現状のままでは出来ません。しかし、たぶん若干の変更で対応できます。

このグリモンには、非表示にする条件を設定するためのインターフェースがありません。設定は直接スクリプトファイルを書き換えて行います。いうなれば雛形みたいなものです。

ですので、若干でも、javascript正規表現xpathが理解できる人が対象です。

ちなみに、具体的に書き換えるべき変数は、itemxpathと、filters配列です。

というわけで、上記は敷居が高いのですが、rikuoさんのまとめ記事の方で、幾つかその他の方法が上げられています。いずれも、コメントに対するものですが、含む日記に応用できるものがあります。詳しくは記事を読んでいただくとして、


以下、書き換え用自分メモ

2008-03-14

XPathってそういう風につかうのか・・・

http://anond.hatelabo.jp/20080308200619

> firefoxでしか確認していないけれど、URL正規表現XPathで指定できる様にしてみたよ。

sugeeeeeeeeeeeee

XPathってそういう風に使えるのか・・・

JavaScriptXPathが使えることすらしらないかったw

増田に投稿してみるもんだなー

気づきがあってよいわ

2008-03-08

[][greasemonkey][seahorse]はてブのhotentryで、2chコピペブログや「ネタ」を削除す...勝手に改造

firefoxでしか確認していないけれど、URL正規表現XPathで指定できる様にしてみたよ。

// ==UserScript==
// @name           filter for Hatena::Bookmark
// @namespace      http://anond.hatelabo.jp/
// @include        http://b.hatena.ne.jp/hotentry*
// @include        http://b.hatena.ne.jp/entrylist*
// origin http://anond.hatelabo.jp/20080302214727
// ==/UserScript==
(function(){
	var itemxpath = "//div[@class='entry']";
	function xpathgenURL(url) {return "//div[@class='entry' and descendant::a[starts-with(@href,'"+url+"')]]"}
	var filters = [
		// start with '//' then xpath
		// moconico douga
//		{"tag": "div", "name": "entry", "pattern": "nicovideo\.jp"},
		"//div[@class='entry' and descendant::a[contains(@href,'nicovideo.jp')]]",
/*
		// tag of "2ch"
		{"tag": "a", "name": "tag", "pattern": "2ch", "parentNum": HatebuTagParentNum},
		{"tag": "a", "name": "tag", "pattern": "\\*2ch", "parentNum": HatebuTagParentNum},
***/
		// start with 'http' then url
		// 2ch blogs  
		//  livedoor
//		{"tag": "div", "name": "entry",
//			"pattern": /http:\/\/blog\.livedoor\.jp\/(insidears|dqnplus)\//},
		"http://blog.livedoor.jp/insidears/",
		"http://blog.livedoor.jp/dqnplus/",
//		{"tag": "div", "name": "entry",
//			"pattern": /http:\/\/(guideline|alfalfa|news4vip)\.livedoor\.biz\//},
		"http://guideline.livedoor.biz/",
		"http://alfalfa.livedoor.biz/",
		"http://news4vip.livedoor.biz/",
		// typeof /regexp/ is function (@firefox) then regexp pattern
		//  fc2
//		{"tag": "div", "name": "entry",
//			"pattern": /http:\/\/(urasoku|news23vip|waranote|vipvipblogblog|netanabe|res2ch|kanasoku|tenkomo)\.blog\d+\.fc2\.com\//},
		/http:\/\/(urasoku|news23vip|waranote|vipvipblogblog|netanabe|res2ch|kanasoku|tenkomo)\.blog\d+\.fc2\.com\//,

		// tag of "neta"
//		{"tag": "a", "name": "tag", "pattern": "ネタ", "parentNum": HatebuTagParentNum},
		"//div[@class='entry' and descendant::a[@class='tag' and string()='ネタ']]",
//		{"tag": "a", "name": "tag", "pattern": "*ネタ", "parentNum": HatebuTagParentNum},
		"//div[@class='entry' and descendant::a[@class='tag' and string()='*ネタ']]",

		// hatena anonymouse diary
//		{"tag": "div", "name": "entry", "pattern": /http:\/\/anond\.hatelabo\.jp\//}
		"http://anond.hatelabo.jp/",
	];

	for (var i=0; i<filters.length; i++) {
		var filter = filters[i];
		var type = typeof filter;
		var regexp;
		var xpath;
		if (type == "function") {
			xpath = itemxpath;
			regexp = filter;
		} else if (type == "string") {
			if (filter.match(/^http/)) {
				xpath = xpathgenURL(filter);
			} else if (filter.match(/^\/\//)) {
				xpath = filter;
			} else {
				next;
			}
		}
		var removeNodes = document.evaluate(xpath,document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
		for (var j=0; j<removeNodes.snapshotLength; j++) {
			var node = removeNodes.snapshotItem(j);
			if (!regexp || node.innerHTML.match(regexp)) {
				node.parentNode.removeChild(node);
			}
		}
	}
})();

ついでに増田版も作ってみたよ。

// ==UserScript==
// @name           filter for Hatelabo::AnonymousDiary
// @namespace      http://anond.hatelabo.jp/
// @include        http://anond.hatelabo.jp/
// @include        http://anond.hatelabo.jp/*?page=*
// @exclude        http://anond.hatelabo.jp/YourID/*
// ==/UserScript==
// origin http://anond.hatelabo.jp/20080302214727
(function(){
	var itemxpath = "//div[@class='section']";
	function xpathgenURL(url) {return "//div[@class='section' and descendant::a[starts-with(@href,'"+url+"')]]"}
	var filters = [
		// start with '//' then xpath
		"//div[@class='section' and child::h3[starts-with(string(),'■はてな嫌われ者!')]]",
		// start with 'http' then url
		"http://anond.hatelabo.jp/",
		// typeof /regexp/ is function (@firefox) then regexp pattern
		/釣り/,
	];

	for (var i=0; i<filters.length; i++) {
		var filter = filters[i];
		var type = typeof filter;
		var regexp;
		var xpath;
		if (type == "function") {
			xpath = itemxpath;
			regexp = filter;
		} else if (type == "string") {
			if (filter.match(/^http/)) {
				xpath = xpathgenURL(filter);
			} else if (filter.match(/^\/\//)) {
				xpath = filter;
			} else {
				next;
			}
		}
		var removeNodes = document.evaluate(xpath,document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
		for (var j=0; j<removeNodes.snapshotLength; j++) {
			var node = removeNodes.snapshotItem(j);
			if (!regexp || node.innerHTML.match(regexp)) {
				node.parentNode.removeChild(node);
			}
		}
	}
})();

2008-03-05

Re: [greasemonkey][seahorse]はてブのhotentryで、2chコピペブログや「ネタ」を削除す...

こんなときのXPathじゃまいか。といってみる。

この機会に使ってみるといいよ。正規表現みたいにチョー便利だから。

2007-06-01

トラックバックツリートップのエントリ以外を表示しない

っていうユーザースクリプト作ったよ。これ使うととってもすっきり。Re: 増田の読み方ってどうしてますか?と組み合わせればめちゃめちゃすっきり。

// ==UserScript==
// @name	anond unvisualizer with innerlink
// @namespace	http://anond.hatelabo.jp/
// @description	unvisualize specific section at Hatelabo::AnonymousDiary
// @include	http://anond.hatelabo.jp/*
// ==/UserScript==
(function() {
	var target = document.evaluate(
		"//div[@class='section' and child::*[not(@class='sectionfooter') and descendant::a[starts-with(@href,'http://anond.hatelabo.jp/2') or starts-with(@href,'/2') and not(child::span[@class='sanchor'])]]]",
		document,
		null,
		XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
		null);
	for(var i=0; i<target.snapshotLength; i++) {
		target.snapshotItem(i).style.display = "none";
	}
})();

仕組みは増田エントリへのリンクがあるエントリを日表示にしてるだけだよ。xpath超便利。

だから、ツリートップのエントリリンクを追記すると消えちゃう!でも気にしない!!

2007-05-17

Re: NGワードを含むエントリをあぼんするGreasemonkey

// ==UserScript==
// @name	unvisualizer
// @namespace	http://anond.hatelabo.jp/
// @description	unvisualize section including specific word at Hatelabo::AnonymousDiary
// @include	http://anond.hatelabo.jp/*
// @exclude	http://anond.hatelabo.jp/hatena/*
// ==/UserScript==
(function() {
	var target = document.evaluate(
//		"//div[@class='section' and contains(descendant::text(),'\u3042\u307c\u3093')]",
		"//div[@class='section' and descendant::*[contains(text(),'NG') or contains(text(),'2ch')]]",
		document,
		null,
		XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
		null);
	for(var i=0; i<target.snapshotLength; i++) {
		target.snapshotItem(i).style.display = "none";
	}
})();

キーワードべた書きだけど、とりあえずこんな感じで。

ただ、日本語がよくわからん。xpathって日本語だめ?'\u3042\u307c\u3093'って「あぼん」だよね?

コメントアウトしてあるやつもなんで駄目なのかわかんない。xpathよくわからん。

おして!エロイ人><

[追記]

念のため、excludeに自分のID以下のページを入れといた方が良いかもね。

その他、好きにして。

2007-04-22

xpath

ようやく、すこしわかった気がする。

トラックバックリスト

//div[@class='refererlist']/ul/li/a[1]

特定のタグのついたエントリ

//div[h3/a[@href='/c/Rimo']]

別の記述方法

//h3/a[@href='/c/Rimo']/../..

まだまだひよっこです。そこで

教えて増田xpathのえろい用法、活用例を!!

 
ログイン ユーザー登録
ようこそ ゲスト さん