はてなキーワード: XPathとは
RStudioがPC内から気がついたら消滅していたので何回もやり直すのが面倒で書いた
コメントアウトをいじればFedoraやmacOSでも動くと思う
https://pastebin.com/HiPqLVq7 (6/4 shコマンドでも動くように修正 以前はbash hogehoge起動していたので動作確認していなかった)
エラーでここに貼れなかった
util-linux(rev) libxml2-utils(xmllint) gpg curl coreutils(sha256sum)とR関連
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回しか出ないのでひとまとめにできそうだが面倒なので分けた
この書き方なら複数回出ても除去できるはず
先頭の謎のスペースの除去が面倒だった
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/
http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html
歴史のあるサイトだったりすると読んでも意味の分からないユーティリティ的なセレクタがよく出てくる。
こういうのが現実。
page.has_selector?(:xpath, '//table.tokushu1/tr.header/td[3]/div/div//span.click_left')
しかもA/Bテストが始まったりしてテスト書く負荷が高くなりメンテできなくなる。
最近、ゲームのwikiをスマホ、タブレットで見る機会が多くて
にたどりついた
任意のwikiのURLを登録出来るものかと思って入れてみるも
(海外はどうか知らないけど)wikiを探していると比較的@wikiを見る機会が多いから
そこの共通するフォーマットを落とし込めば閲覧できるwikiの数は一気に増えるのにと思いつつ
出来ない理由があるのだろうといくつかの@wikiのソースを見たところ
同じサービス内にもかかわらずメニューのxpathがそろっていなくてびっくりした
せめて位置ぐらいと思ったけどそれなら
の情報を(メニューも一つのページ情報として)全ページ分吐き出してれば
更新日なりサイズなりが違っているページ、新しく増えたページだけを取りに行く
ってアプリが作られそうな気がするんだけどな
見ようとするたびに読込み直されるのは面倒だよね
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'
サンプル
例に漏れず件のエントリーに影響を受けまして、Ruby on Rails を利用したサービスを作ってみました。
一つもアクセスがないため宣伝ついでに利用したgemや作成する際に参照したサイトを載せますので、「Rails初心者っす」とか、自分と同じく「そもそもプログラミングとか知らねっす」という方はちょっとしたナレッジとしてご活用くださいまっせ。開発ガンガンやってる方には価値ある情報たぶんないよー。
最初はMac標準のエディタで書いてたけど、どこかの記事を読んでからは「Sublime Text 2 (http://www.sublimetext.com/)」に乗り換えました。すごく…便利です…。ターミナルはMac標準のアレです。オススメがあったら教えてください。
完成までにやったこと、実装するために参考にしたサイトを並べます。
RubyとRailsの環境を構築する。(http://www.oiax.jp/rails/rails3/install.html)
簡単にウェブアプリの土台を作れるScaffoldという機能を使って遊んでみる。(http://www.techscore.com/tech/Ruby/Rails/quick-start/Rails4/4-1)
行き詰まったので本を買う。(たのしいRuby、Ruby 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の投稿)をさせたくない。そんなときに使える認可処理。
クリップしたサイトの情報をタグで管理したい。タグ機能の実装を手抜きできるのがこの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カ月だらーっとRubyとRailsをさわってみて感じたことは、ウェブアプリを作るのって特別なことじゃないんだなーっていう。どこかで誰かも言ってましたけど、開発している最中はパズルを解いてる感覚でした。ウェブに転がるピースを探して、フレームワークにあてはめていくようなそんな感覚。
おしまい!
最新はこれでいいんですか?
誰も話題にしてないので俺だけかな
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]); }
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;key=' + idnum + '&amp;log=' + lognum; break; case 'ssw_p': url = 'http://coolier.sytes.net:8080/sosowa/ssw_p/?mode=read&amp;key=' + idnum + '&amp;log=' + lognum; break; case 'compe': url = 'http://www10.atpages.jp/thcompe/compe' + boardnum + '/?mode=read&amp;key=' + idnum + '&amp;log=0'; break; case 'yotogi': url = 'http://yotogi.com/yotogi/?mode=read&amp;key=' + idnum + '&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;key=' + idnum; break; case '二': url = 'http://easy2life.sakura.ne.jp/necho/comp2/anthologys.cgi?action=html2&amp;key=' + idnum; break; case '三': url = 'http://green.ribbon.to/~ronron/comp/?mode=read&amp;key=' + idnum + '&amp;log='; break; case '四': url = 'http://green.ribbon.to/~ronron/comp4/?mode=read&amp;key=' + idnum + '&amp;log=0'; break; default: url = null; break; } break; default: url = null; break; } return url; }
// ==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>=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 とは Mozilla Firefox 上で動作するアドオンです。Google で検索するとたくさんヒットするので使いたい方は調べてみて下さい。
スクリプト中の
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)。
結局概要表示機能追加した。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(); })();
ご紹介いいただいたgreasemonkeyをインストールすると、特定IDの「このエントリーを含む日記」を非表示にすることができるのですか?
舌足らずでした。
現状のままでは出来ません。しかし、たぶん若干の変更で対応できます。
このグリモンには、非表示にする条件を設定するためのインターフェースがありません。設定は直接スクリプトファイルを書き換えて行います。いうなれば雛形みたいなものです。
ですので、若干でも、javascript、正規表現、xpathが理解できる人が対象です。
ちなみに、具体的に書き換えるべき変数は、itemxpathと、filters配列です。
というわけで、上記は敷居が高いのですが、rikuoさんのまとめ記事の方で、幾つかその他の方法が上げられています。いずれも、コメントに対するものですが、含む日記に応用できるものがあります。詳しくは記事を読んでいただくとして、
以下、書き換え用自分メモ
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); } } } })();
こんなときのXPathじゃまいか。といってみる。
っていうユーザースクリプト作ったよ。これ使うととってもすっきり。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"; } })();
// ==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以下のページを入れといた方が良いかもね。
その他、好きにして。