本文来自依云's Blog,转载请注明。
GreaseMonkey 代码如下:
// ==UserScript== // @name is-programmer 后台评论地理位置显示 // @namespace http://lilydjwg.is-programmer.com/ // @description 通过 JSONP 查询 IP 地址对应的地理位置并显示 // @include http://*.is-programmer.com/admin/comments* // @include http://*.is-programmer.com/admin/messages* // ==/UserScript== var qurl = function(ips){ return 'http://localhost:2000/queryip?q=' + ips.join(',') + '&cb=?'; }; var letsJQuery = function(){ var ip_header = document.evaluate('//th[@class="helpHed" and text()="IP"]', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0); $(ip_header).after('<th class="helpHed">地址</th>'); var ip_cells = document.getElementsByClassName('comment_ip_col'); var ips = []; var i; for(i=0, len=ip_cells.length; i<len; i++){ ips.push(ip_cells[i].textContent); } $.getJSON(qurl(ips), function(data){ var ans = data.ans; for(i=0, len=ip_cells.length; i<len; i++){ $(ip_cells[i]).after('<td class="comment_addr_col">'+ans[i]+'</td>'); } }); }; function GM_wait(){ if(typeof unsafeWindow.jQuery == 'undefined') { window.setTimeout(GM_wait, 500); }else{ $ = unsafeWindow.jQuery; letsJQuery(); } } GM_wait();
光有这个脚本是不够的,因为没有 IP 地址数据库。我不想像这样用 chrome 权限调用子进程之类的手段,而是从本地 HTTP server 取得数据,这样以后可以方便地扩展。HTTP server 使用 Python 的 tornado 框架写成,名字是“Web Service Provider”的缩写:
#!/usr/bin/env python3 # vim:fileencoding=utf-8 from subprocess import getoutput from functools import lru_cache import json import tornado.web import tornado.httpserver from tornado.options import define, options @lru_cache() def lookupip(ip): return getoutput('cip ' + ip).replace('CZ88.NET', '').strip() or '-' class IPHandler(tornado.web.RequestHandler): def get(self): q = self.get_argument('q').split(',') addr = [] for ip in q: a = lookupip(ip) if 'illegal' in a: a = '(错误)' elif '\n' in a: a = '' addr.append(a) ans = { 'ans': addr, } cb = self.get_argument('cb', None) if cb: self.set_header('Content-Type', 'text/plain; charset=utf-8') self.write('%s(%s)' % (cb, json.dumps(ans, ensure_ascii=False))) else: self.write(ans) def main(): define("port", default=2000, help="run on the given port", type=int) tornado.options.parse_command_line() application = tornado.web.Application([ (r'/queryip$', IPHandler), ], debug=True, ) application.listen(options.port) tornado.ioloop.IOLoop.instance().start() if __name__ == "__main__": try: main() except KeyboardInterrupt: pass
用的是 Python 3.2,我很喜欢它的lru_cache
装饰器。
Oct 13, 2011 09:44:01 PM
哇哈哈哈,抢到沙发
Oct 14, 2011 02:00:59 AM
这个好棒~