読み書きプログラミング

日常のプログラミングで気づいたことを綴っています

サイトの画像を一括ダウンロード

訳あって、サイトに表示されているimg画像を一括してダウンロードするスクリプトを書きました。

((func) ->
    scr = document.createElement 'script'
    scr.src = "//ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"; # 短いのに大げさですが、jQueryを使います
    scr.onload = ->
        func jQuery.noConflict true
    document.body.appendChild scr
) ($) ->
    $('img').each (num) -> # セレクタを変更すると欲しい部分だけにしぼれる
        a = document.createElement 'a'
        a.download = num + '.jpg' # jpg決めうちの品のないコード
        a.href = $(this).attr 'src'
        evt = document.createEvent 'MouseEvent'
        evt.initEvent 'click', true, false
        a.dispatchEvent evt
        return
    return

これをコンパイルして、自分のサイトに置きます。

次に、このスクリプトを読み込むブックマークレットを作ります。

javascript:(function(d,s){s=d.createElement("script");s.src="<スクリプトのURL>?"+Date.now();d.body.appendChild(s)})(document)

取得したいサイトを開いて、ブックマークレットをクリックすると、画像のダウンロードが始まります。
(Chromeの場合、初回だけ複数ダウンロードを許可するかどうか確認のウィンドウが開きました。)

ファイル名に<番号>.jpgを指定していますが、他の種類の画像もあるので、本来対称のsrc属性を調べて決定すべきです。
src属性からハッシュを消して拡張子を取り出すのがそれっぽい処理ですが、srcはdataURLの場合もあるのでご注意ください。

不具合

Chromeの場合、最初の0から19までの画像は<番号>.jpgの名前で保存されましたが、それ以降はimages.jpeg, image (番号).jpegという名前になりました。なぜでしょう?自分の用は足せたので原因を調べたりしていません。あしからず。

Twitterボタンを動的に更新する

[2016/06/08追加]
動的にボタンを追加するAPIがあるみたいですね。
dev.twitter.com

Twitterボタンには以下の属性が設定可能です。

type
ボタンのタイプ
size
ボタンのサイズ
lang
ボタン表示の言語設定
text
ツイート内容
url
添付するURL
hashtags
ハッシュタグ
id
ボタン(iframe)のid
time
ボタン生成時刻
original_referer
ボタンが配置されたページのURL
dnt
Twitterによるカスタマイズのオプトアウトのオンオフ
ウェブアプリでゲームを作って、ゲームの成績をツイートするような場合には上記のtextに結果を埋め込みたいです。
ボタンに変換されるアンカーaを動的に生成、追加して、twttr.widget.load()を実行すればいいのですが、元々ボタンが設置されている場合、削除してload()を実行するのは、それなりにオーバーヘッドがあるかなと思いました。

なので、iframeのsrcを直接変更してみたのですが、ボタンが更新されない。調べたところ、上記のパラメータがsrcのハッシュ部分に埋め込まれていて、ハッシュだけの更新の場合、iframeは再読み込みを実行しないからでした。
原因がわかれば対策は簡単で、キャッシュを外すよくあるテクニックで、ダミーのタイムスタンプを付けることで解決しました。

以下、コードスニペット(CoffeeScript, jQuery使用)です。

parseTwitterButtonSrc = (url) ->
    match = url.match /(.*)#(.*)/
    unless match?
        return null
    result =
        page: match[1]
        params: {}
    for eq in match[2].split '&'
        match = eq.match /(.*)=(.*)/
        if match?
            result.params[decodeURIComponent match[1]] = decodeURIComponent match[2]
    result

composeTwitterButtonSrc = (obj, timestamp = false) ->
    head = obj.page
    if timestamp
        head += "?dummy=#{Date.now()}"
    head + '#' + (encodeURIComponent(k) + '=' + encodeURIComponent(v) for k, v of obj.params).join '&'

updateButtonText = ($target, text) ->
    parsed = parseTwitterButtonSrc $target.attr 'src'
    parsed.params.text = text
    $target.attr 'src', composeTwitterButtonSrc parsed, true
    return

新浪微博の各ポストへのURL生成

新浪微博の各ポストに当たるURLを生成する必要があったので、調べました。

URLはhttp://weibo.com/<user id>/<post mid>という構造になっていて、post midはpost idから計算できます。
post midを計算するAPI(Querymid)が用意されていたようですが、今の提供されていないようです。


それ以前に単なる関数なのにRESTで取得するのが嫌だった人がいて、関数を実装されていました。

Using base62 to generate a Sina Weibo post permalink

ちょっと長いコードですが、どうやら大部分はbase62の実装のようです。

Rubyにはbase62のgemがあったので、それを使って、id2midだけ実装しました。

require 'base62'

def id2mid id
    id.to_s.reverse.scan(/.{1,7}/) # 下から7桁ずつに分割
        .map { |a| a.reverse.to_i.base62_encode }.reverse # 各パートをbase62エンコード
        .join('').swapcase #くっつけて大文字小文字変換
end

終わり。(短くてすいません)

meteor.comにデプロイした古いMeteorアプリでのsiperableの注意点

追記
去年の10月にAJAX Crawling (Deprecated)はご覧の通りdeprecatedになっており、meteorのspiderableパッケージは今となっては特に有効ではないということのようです。

Meteorアプリを検索エンジンのボットに読み取ってもらうにはspiderableパッケージを使います。
spiderableパッケージはPhantomJSを起動してボットが読み取れる様アプリがレンダリングした結果のHTMLをボットに提供します。
ところが、いつ頃からかmeteor.comにデプロイしたアプリでspiderableのレンダリングがうまくいかなくなりました。

不思議に思いながら放置していたのですが、今回調査したところ、

  1. どうやらmeteor.comのPhantomJSはバージョン1の模様
  2. PhantomJS v1はFunction.prototype.bindをサポートしてない
  3. Meteorはproduction build(minificationなど)する時に.bindを使っている部分がある
  4. なのでlocalや--debugの時は動いてもproductionで動かなくなる

ということが起こっていました。
問題ないアプリもあるので、使っているパッケージに依存しているようです。

.bindのpolyfillを入れれば直るはずということで、es5-shimパッケージを追加したところ、直りました。

es5-shimは今ではmeteor createでデフォルトで追加されるパッケージのようです。
ずいぶん前から作り続けているアプリだったので今回のような問題が起こりました。

それにしても、meteor.comのPhantomJS、バージョンアップした方がいいんじゃないかな?

SGFパーサ

Rustでコンピュータ碁に取り組むプロジェクト「きり」、ちょっと地味ですが初めての成果公開します。
SGFパーサを作ってcrate.ioに公開しました。
レポジトリ

y-ich/rust-sgf: Smart Game Format parser in Rust

rust-pegを使って書きました。

GoGui付属のツール

コンピュータ碁の開発者の多くが、GoGuiをUIや開発ツールとして利用しているようです。
GoGuiにはコンピュータ碁の開発開発用ツール(スクリプト)が付属されているので、どんなものがあるかメモってみました。

http://gogui.sourceforge.net/doc/tools.html

gogui-adapter

GTPのクライアントとサーバーの間に挟み込むアダプタ。ログ機能と(loadsgfやundoなど)GTP機能の一部を別コマンドで代替する機能を提供。
gogui-client

標準入出力を使うGTPクライアントをネットワーク経由で使えるようにするアダプタ。
gogui-display

現局面を表示するアダプタ。
gogui-dummy

コントローラをテストするランダム着手のクライアント。
gogui-twogtp

2つのGTPクライアントを対戦させるアダプタ。
gogui-regress

GTPで記述されたリグレッションテストを実行するスクリプト。(すいません、リグレッションテストってググったのですが、意味わかりませんでした。プログラムやシステムの変更後に他の動作に影響ないか調べるテストのことで、単体テストやインテグレーションテストのような技術用語ではなく、テストプロセス用語と思いました。gogui-regressの場合、要するにGTPで書かれたテストを実行するということのようです。)
gogui-server

GTPサーバーをネットワーク経由で使えるようにするアダプタ。
gogui-statistics

対局のコレクションのすべての局面に対して数値を戻すGTPコマンドを発行し集計するスクリプト
gogui-terminal

GTPクライアントをターミナル化するプログラム。デバッグ用コンソール実装の省略が可能。
gogui-thumbnailer

対局のコレクションのすべての局面に対して数値を戻すGTPコマンドを発行し集計するスクリプト
gogui-convert

freedesktop.org仕様のSGFファイルのサムネイルを生成するプログラム。

オープンソースのコンピュータ囲碁

オープンソースのコンピュータ囲碁にどんなものがあるのか調査したメモを公開します。
他にご存知の方、教えてください。

  • KataGo

レポジトリ: https://github.com/lightvector/KataGo
言語: C++, Python
ライセンス: 独自(著作権と許可の表記義務)
コメント: Leela Zeroより5倍以上の学習効率

  • Cygo

レポジトリ: https://github.com/syarig/Cygo
言語: Python
ライセンス: GPLv3
コメント: AlphaGo Fanを参考にしたもの。

  • PhoenixGo

レポジトリ: https://github.com/Tencent/PhoenixGo
言語: C++
ライセンス: BSD
コメント: Tencent社内でAlphaGo Zeroのレプリカを目指したもの。

  • ELF OpenGo

URL: https://research.fb.com/facebook-open-sources-elf-opengo/
レポジトリ: https://github.com/pytorch/ELF
言語: Python, C++
ライセンス: BSD
コメント: Facebook社内でAlphaGo Zeroのレプリカを目指したもの。韓国のトッププロに対して14戦14勝。

  • Minigo

レポジトリ: https://github.com/tensorflow/minigo
言語: Python
ライセンス: Apache
コメント: Google社内でAlphaGo Zeroのレプリカを目指したもの。活発に開発が続いている。
ウェイト情報: https://cloudygo.com/
ウェイト: https://console.cloud.google.com/storage/browser/minigo-pub/

  • Leela Zero

URL: http://zero.sjeng.org/
レポジトリ: https://github.com/gcp/leela-zero
言語: C++
ライセンス: GPLv3 or later
コメント: AlphaGo Zeroのレプリカを目指したもの。活発に開発が続いている。
ウェイト情報: https://zero.sjeng.org/

  • AQ

URL: https://github.com/ymgaq/AQ
言語: C++
ライセンス: MIT
コメント: TensorFlowを使っているのでNNの応用がしやすい。

  • Rn

URL: https://github.com/zakki/Ray/
言語: 限りなくCなC++
ライセンス: BSD
コメント: RayにDeep Learningを追加したもの。活発に開発が続いている。

  • Ray

URL: http://computer-go-ray.com/
レポジトリ: https://github.com/kobanium/Ray
言語: 限りなくCなC++
ライセンス: BSD
最新安定版: 8.0

URL: http://www.gnu.org/software/gnugo/
レポジトリ: http://git.savannah.gnu.org/cgit/gnugo.git/
言語: C
ライセンス: GPL3
最新安定版: 3.8(2009)
行数: 87,000行
コメント: 2011年まで3.9の開発が続いていましたが、2013年のコミットを最後にアクティビティがなくなっている。

  • Pachi

URL: http://pachi.or.cz/
レポジトリ: https://github.com/pasky/pachi
言語: C
ライセンス: GPL2
最新安定版: 11(2015)
行数: 20,000行
コメント: 現在も開発が続いている。

  • Fuego

URL: http://fuego.sourceforge.net/
レポジトリ: http://sourceforge.net/projects/fuego/
言語: C++
ライセンス: GPL3
最新安定版: 1.1(2013)
行数: 72,000行
コメント: 現在も開発が続いている。

  • Oakfoam

URL: http://oakfoam.com
レポジトリ: https://bitbucket.org/francoisvn/oakfoam/wiki/Home
言語: C++
ライセンス: BSD
最新安定版: 0.2.0(2014)

  • A Monte-Carlo Go AI

URL: http://www.ryanlothian.com/projects/go/
レポジトリ: https://github.com/ryanl/go-ai
言語: C++
ライセンス: GPL3
最新安定版: (2012)

  • Library of Effective GO routines

レポジトリ: https://github.com/lukaszlew/libego
言語: C++
ライセンス: GPL
最新安定版:

  • Orego

レポジトリ: https://github.com/Orego/Orego
言語: Java
ライセンス:
最新安定版:

  • Iomrascálaí

レポジトリ: https://github.com/ujh/iomrascalai
言語: Rust
ライセンス: GPL3

  • gogo

レポジトリ: https://github.com/khadiwala/gogo
言語: Go
ライセンス:
最新安定版:

  • Isana

レポジトリ: https://github.com/foozea/isana-go
言語: Go
ライセンス:
最新安定版:

  • Michi

レポジトリ: https://github.com/pasky/michi
言語: Python
ライセンス: MIT
最新安定版:
コメント: Pachi作者によるミニマル実装

Michiは他言語への移植がされています。

  • Michi-c

レポジトリ: https://github.com/db3108/michi-c
言語: C
ライセンス: MIT
最新安定版:
コメント: MichiのC言語移植

  • Michi-c2

レポジトリ: https://github.com/db3108/michi-c2
言語: C
ライセンス: MIT
最新安定版:
コメント: Michi-cの改良版

  • Michi-Go

レポジトリ: https://github.com/traveller42/michi-go
言語: Go
ライセンス: MIT
最新安定版:
コメント: MichiのGo言語移植

  • Kurt

レポジトリ: https://github.com/lefant/kurt
言語: Haskell
ライセンス:
最新安定版:

  • Creating board games in Haskell in 100 lines of code

URL: http://keera.co.uk/blog/2013/03/19/creating-board-games-in-haskell/
言語: Haskell
ライセンス:
最新安定版:

  • DarkForest

URL: https://github.com/facebookresearch/darkforestGo
言語: Lua/C++
ライセンス: BSD

  • MuGo

URL: https://github.com/brilee/MuGo
言語: Python
コメント: A minimalist Go engine modeled after AlphaGo

  • DeltaGo

URL: http://home.q00.itscom.net/otsuki/delta.html
言語: C
ライセンス: 無断での商用利用は不可
コメント: AlphaGoのSupervised-Learning Policy Networkのレプリカ

  • WeiRustQi

URL: https://github.com/kuking/weirustqi
言語: Rust
ライセンス: GPL 3.0

レポジトリ: https://github.com/Mononofu/pony-mcts
言語: Pony/Rust

  • RustyGo

レポジトリ: https://github.com/mratsim/rustygo
言語: Rust

バイナリ配布のプログラム

  • Leela

URL: https://www.sjeng.org/leela.html
言語: ?
最新安定版: 0.10.0
コメント: 0.9.0が一手15秒でKGS 8d(CPU Skylake 3.5GHz4コア(i5-6600)、GPU R9-390)