Stimulator

機械学習とか好きな技術話とかエンジニア的な話とかを書く

xonshにおけるxontribの紹介

- はじめに -

この記事は、Xonsh Advent Calendar 2017 - Qiita 14日目の記事です。

xonshにおけるいわゆる拡張機能であるところのxontribについて書いていきます。

「オススメXontrib!」と行きたい所ですが、そもそも2017年末時点で公開されているxontribは少ないのでほぼ全てです。

 

- xontribとは -

xontribはxonshの拡張群です。

例えばhogeパッケージをロードするには、以下Commandを入力します。

xontrib load hoge

~/.xonshrcに上記Commandを直接書くか、~/.config/xonsh/config.json内にあるxontribsという名前のlistにパッケージ名を書いておくと、xonshセッション起動時にロードされます。

手前味噌ですが、私も作っています。


現行のxontribパッケージについては、公式ドキュメントにまとまっています。
Xontribs — xonsh 0.9.11 documentation
この中にあるやつないやつで、少しだけ便利になるやつだけ紹介していきます。

[2019/06/29] 続編で作る側になろうという記事も書きました
vaaaaaanquish.hatenablog.com


 

- 補完 -

apt_tabcomplete

apt-getコマンドをtabで補完できるようにします

# 導入
pip install xonsh-apt-tabcomplete
xontrib load apt_tabcomplete

apt-getのinstall、remove、apt-cacheのsearchの補完がサポートされています。
github.com

Ubuntuなどaptを良く使う環境でxonshを使う時は入れておくと良いと思います。

 

docker-tabcomplete

dockerコマンド周りをtabで補完できるようにします

# 導入
pip install xonsh-docker-tabcomplete
xontrib load docker_tabcomplete

docker imageの補完などがxonsh上で上手くいかないのですが、こちらを導入することで解決します。
github.com

dockerで複数のコンテナを扱いながら開発している場合に便利です。

 

scrapy-tabcomplete

scrapyコマンド周りをtabで補完できるようにします

# 導入
pip install xonsh-scrapy-tabcomplete
xontrib load  scrapy_tabcomplete

scrap crawlコマンドやscrapy checkコマンドの結果のcacheから、次のコマンドを補完してくれます。

github.com

scrapyをコンソール上で使っている人(そんな人が居るかどうかは別として)には使えると思います。

 

fzf-widgets

sshコマンドの補完、historyの検索をサポートしてくれます。

公式のGIFが大体全てを説明してくれています。
https://raw.githubusercontent.com/shahinism/xontrib-fzf-widgets/master/docs/cast.gif

# 導入
pip install xontrib-fzf-widgets
xontrib load fzf-widgets

github.com

historyや補完はもともと強力なxonshですが、sshのconfigから補完は一応デフォでやってくれないので便利。

 

thefuck

コマンドを打ち間違えた時に「fuck」と入力すればコマンド候補を入力してくれるxontrib。
xonshrcの書き方の記事にもある$SUGGEST_COMMANDSをもうちょっと便利にする感じ。

# 導入
pip install xontrib-thefuck
xontrib load thefuck

xonsh記事ではないけど以下見ると大体の概要がわかります
thefuckのインストール方法 - Qiita

github.com


  

- UI -

powerline

おなじみpowerlineのサポートxontribです
見た目を色々できます

https://github.com/santagada/xontrib-powerline/raw/master/screenshot.png

# 導入
pip install xontrib-powerline
xontrib load powerline

プロンプトの右側を $PL_PROMPT、下側を $PL_TOOLBAR で設定します。
whoやbranchなどはセクションです。
pl_available_sectionsコマンドで全ての使えるセクションを表示できます。pl_build_promptコマンドで再ロードします。

$PL_PROMPT = '!'    # 使わない時
$PL_TOOLBAR = 'who>time'

xonshrcの書き方の記事でも紹介した $PROMPT も使えます。

github.com

iterm2ではpowerlineフォントが化けたり、表示が重なったりします。
その時は以下で対応できます。
iTerm2+powerline文字化け対策めも - Qiita

一回やってしまえばカッケーコンソールでxonshできます。

// 追記:2019/09/15
現在開発が止まっているようでした(開発者とも連絡がつかない状態)。私が別途xontrib-traceback2というのを作っています。
github.com

 

prompt-vi-mode

promptの表示に「vi-modeかどうか」を加えます。

# 導入
pip install xontrib-prompt-vi-mode
import xontrib.prompt_vi_mode

導入後は、xonshrcの書き方の記事でも出た、$PROMPTや$RIGHT_PROMPTに "{vi_mode}" もしくは "{vi_mode_not_input}"を突っ込むだけです。

こんな感じ
f:id:vaaaaaanquish:20171213175148p:plain

github.com

仕方ないですがimportなところに注意です。
私はptkのショートカットを登録してINSERTとNORMALを切り替えています。
vim開けばよくね…」と言われればそれはそう。


 

- タスク、操作 -

z

ディレクトリ移動を潤滑にするxontrib。
/home/work に行ったことがあれば $ z work とだけ入力すれば高確率で移動できる。

# 導入
pip install xontrib-z
xontrib load z

基本的にはcacheされたとこに行きます

github.com

アドベントカレンダー内の以下でも紹介されていて、zshのz.shを上手く書き換えているので一読すると吉です。
qiita.com

 

autoxsh

.autoxsh」というスクリプトファイルをディレクトリに設置しておくと、そのディレクトリにcdした時に毎回そのスクリプトが実行されるようになります。

# 導入
pip install xonsh-autoxsh
xontrib load autoxsh

初回の実行時には以下autoxshを許容し実行するかのメッセージが出るのでYesで実行

Unauthorized ".autoxsh" file found in this directory. Authorize and invoke? (y/n/ignore): y

github.com

.autoxshは普通のxonshスクリプトが記述できるので、lsコマンドの自動実行や、注意喚起のprint、envの切り替えを記入しておくと便利です。

 

schedule

スケジューラです。
コマンドにtimeオブジェクトを投げておくと、指定時間に実行したり、delayをかけて実行したりできます。

# 導入
pip install xontrib-schedule
xontrib load schedule

以下scheduleパッケージwrapperです
schedule — schedule 0.4.0 documentation

import time

def func():
    print("20秒経ちました")

schedule.when(time.time()+20).do(func)

時間指定のwhenと、遅延実行のdelayが使えます。

github.com

これに似た方法を上手く使えば「xonshrcに書いておいて最速でxonshを起動しつつ、よく使うパッケージを遅れて読み込む」なんてこともできそうです。いつかやりたい。


 

- おわりに -

その他にも、xonsh用のenvである"vox"用のxontribxonsh上でcondaを扱うためのxontrib簡易エディタxoを提供するxontribコマンドを保存していくxontrib…などが使えそうです。

voxはまだ使った事無く、anacondaは宗教上無理。エディタはvimだしな…となって今の記事に収まっています。


Githubリポジトリを見てもらえば分かりますが、xontribは数行Pythonを書けばできてしまいます。
xonshでは実際色んなイベントをデコレータを付けることでキャッチできるので、自身でxontribを作っていくのもかなり簡易だと感じます。
 

xonsh アドベントカレンダーも後半戦に入り、空きが出てきたのでなんとか登録だけでもお願いします!
後半戦のどこかでxontrib作れたらいいなと思っています。

qiita.com

xonshrcを書く

- はじめに -

この記事は、Xonsh Advent Calendar 2017 - Qiitaの9日目の記事です。

1日目にXonshを勧める記事を書いて「アドベントカレンダーでxonshrcのオススメ設定が出揃う」と言ったものの、なかなかそれらしい記事が出てこないので書いておきます。


Python Prompt Toolkitが使えるなら、アドベントカレンダー内の以下の記事もオススメです。
qiita.com


追記2018/06/22:
さらにちゃんとまとめました
vaaaaaanquish.hatenablog.com
vaaaaaanquish.hatenablog.com


追記2019/08/28
さらに最新のxonsh 0.9.10のEnvを全て実装付きでまとめました
こちらのほうが参考になると思います。
vaaaaaanquish.hatenablog.com

 

- 私のxonshrc -

先に結論として設定している最もシンプルな部分のrcを出しておきます。
xonshrcを制御するxonsh/configファイルについては基本的にはdefaultのものを利用しています。

# vi風の操作
$VI_MODE = True
# Ctrl + D で終了しない
$IGNOREEOF = True
# tabではなく空白4つ
$INDENT = "    "
# 補完時に大小区別しない
$CASE_SENSITIVE_COMPLETIONS = False
# 補完選択Enterで即実行しない
$COMPLETIONS_CONFIRM = True
# 連続重複コマンドを保存しない
$HISTCONTROL = (ignoredups)
# 括弧を補完
$XONSH_AUTOPAIR = True
# ディレクトリ名を入力すればcdできる
$AUTO_CD = True
# エラー全て吐くように
$XONSH_SHOW_TRACEBACK = True
# プロンプトの設定タイムアウトのメッセージ抑制
$SUPPRESS_BRANCH_TIMEOUT_MESSAGE = True

# 見た目ウザかったら切か変更する
# 参考:http://xon.sh/tutorial.html#customizing-the-prompt
# プロンプト上には場所だけ出す
$PROMPT = "{INTENSE_YELLOW}[ {cwd} ] {GREEN}$ "
# 下部にuser, host情報を追加
$BOTTOM_TOOLBAR = "{BACKGROUND_WHITE}{BLACK}{user}@{hostname}"
# 右にbranch情報
$RIGHT_PROMPT = "{curr_branch}"
# lsコマンドの結果の見た目
$LS_COLORS="di=34:ln=35:so=32:pi=33:ex=31:bd=46;34:cd=43;34:su=41;30:sg=46;30:tw=42;30:ow=43;30"

#えいりあす
aliases["lt"] = "ls -ltr"
aliases["l"] = "ls -ltr"
aliases["la"] = "ls -la"
aliases["ll"] = "ls -l"
aliases["so"] = "source"
aliases["v"] = "vim"
aliases["vi"] = "vim"
aliases["vx"] = "vim ~/.xonshrc"
aliases["vv"] = "vim ~/.vimrc"
aliases["vs"] = "vim /etx/ssh/ssh_config"
aliases["cp"] = "cp -i"
aliases["rm"] = "rm -i"
aliases["ju"] = "jupyter notebook"

見た目はこんな感じ

f:id:vaaaaaanquish:20171209154013p:plain

これだけで大体良い感じですが、Pythonで関数を作ってそこにaliasを貼ることももちろんできるので、加えて幾つか記述していますがそれらについてはまた別途。


 

- xonshrcで使える環境変数まとめ -

以下ではxonshrcで使える環境変数をまとめておきます。
基本的には、以下Referenceに書いてある内容です。
Environment Variables — xonsh 0.9.11 documentation

  

見た目、表示系

    # カラーテーマ
    # 自分はdefaultでiTerm2側の設定を利用
    # xonfig styles コマンドで全てのスタイル表示
    # 良さげなのだと'native'
    $XONSH_COLOR_STYLE = ‘default’

    # 下部に表示するツールバー
    # prompt-toolkitが導入されているShellのみ
    $BOTTOM_TOOLBAR

    # Shell上のシンタックスハイライト強調表示
    $COLOR_INPUT = True

    # コマンド実行の戻り値にもシンタックスハイライト
    $COLOR_RESULTS = True

    # インデント文字列
    # 空白4つとかTabとか任意に
    $INDENT = "    "

    # 改行した時にでてくる左端の文字
    # 指定された長さ以下だった場合は繰り返し表示される
    $MULTILINE_PROMPT = "."

    # 右揃えで表示する文字列
    $RIGHT_PROMPT = ""

    # プロンプトのサブプロセス、書式設定などのタイムアウト
    $VC_BRANCH_TIMEOUT = 0.1

    # プロンプトの設定タイムアウトのメッセージ抑制
    $SUPPRESS_BRANCH_TIMEOUT_MESSAGE = False

    # MercurialのbranchをTerminalに表示するか
    $VC_HG_SHOW_BRANCH = True

    # datetime.strptime()で出せる時間の表示の仕方
    $XONSH_DATETIME_FORMAT = ‘%Y-%m-%d %H:%M’

    # xonshの見た目の色々、文字のシンボル
    # http://xon.sh/envvars.html#xonsh-gitstatus
    $XONSH_GITSTATUS_*

    # エラーが出たときトレースバックを表示するかどうか
    $XONSH_SHOW_TRACEBACK = False

    # defaultプロンプトの見た目設定
    # http://xon.sh/tutorial.html#customizing-the-prompt
    $PROMPT = xonsh.environ.DEFAULT_PROMPT

    # titleとpromptのカスタマイズ
    # http://xon.sh/tutorial.html#customizing-the-prompt
    $PROMPT_FIELDS = xonsh.prompt.PROMPT_FIELDS

    # PROMPTのエラー表示版
    $XONSH_STDERR_POSTFIX
    $XONSH_STDERR_PREFIX

 

操作

    # マウス操作で履歴戻ったりするかどうか
    # prompt_toolkitが導入されているShellのみ
    $MOUSE_SUPPORT = False

    # Ctrl + D で終了しない
    $IGNOREEOF = False

    # vi風の操作
    $VI_MODE

 

補完

    # キー入力ごとに評価する
    $UPDATE_COMPLETIONS_ON_KEYPRESS = False

    # プロンプト間でコマンドをcacheしない設定にするか
    # Trueにすると毎回キー入力待ち再評価が発生する
    $UPDATE_PROMPT_ON_KEYPRESS = False
    
    # 補完時に大文字小文字区別するか
    # LinuxだとdefaultでTrue
    # 個人的にはFalse派
    $CASE_SENSITIVE_COMPLETIONS

    # コマンド履歴の保存の仕方
    # ignoredupsは重複コマンドを保存しない
    # ignoreerrは失敗したコマンドを保存しない
    $HISTCONTROL = (ignoredups, ignoreerr)

    # 補完時に[]と()を考慮する
    $COMPLETIONS_BRACKETS = True

    # ユーザ確認する前に補完を表示する上限数
    $COMPLETION_QUERY_LIMIT = 100

    # Tab補完メニューで表示する行数
    # prompt-toolkitが導入されているShellのみ
    $COMPLETIONS_MENU_ROWS = 5

    # Tab補完メニューが表示されている時にEnterで即実行するか
    # Trueなら実行しない
    # prompt-toolkitが導入されているShellのみ
    $COMPLETIONS_CONFIRM = False

    # Tab補完のPathのsubsequence matching
    # ~/u/ro で ~/lou/carcolh をよしなに補完してくれるみたいなやつ
    $SUBSEQUENCE_PATH_COMPLETION = True

    # Pythonスクリプトの補完
    # 基本的にdefaultがサイコー
    # prompt-toolkitが導入されているShellのみ
    $COMPLETIONS_DISPLAY = multi

    # あいまい補完をするか
    $FUZZY_PATH_COMPLETION = True

    # 補完サジェストを出す
    # defaultでTrue
    $AUTO_SUGGEST_IN_COMPLETIONS = True

    # 補完サジェストを 右矢印キーで入力
    # $SHELL_TYPE=prompt_toolkitが指定されている必要あり
    # defaultがTrueなのでptkが入っていればデフォで動いてるはず
    $AUTO_SUGGEST = True

    # BASHの補完機能をそのまま利用するための
    # defaultでは以下、tupleを指定する
    $BASH_COMPLETIONS = ('/usr/share/bash-completion/bash_completion', )

    # パターンマッチなどglobした時に結果をソートするか
    $GLOB_SORTED = True

    # 実行可能なファイルの拡張子
    # 大文字で書く必要がある
    $PATHEXT = [".EXE"]

    # 変なコマンドを入力したら もしかして を出す
    $SUGGEST_COMMANDS = True

    # もしかして最大数
    $SUGGEST_MAX_NUM = 5

    # もしかしてサジェストの誤字数
    $SUGGEST_THRESHOLD = 3

    # 出力後に新しい空行を追加するか
    $XONSH_APPEND_NEWLINE = False

    # [], ()などの括弧を補完するか
    $XONSH_AUTOPAIR = False

    # 全てのコマンド実行をcacheするか
    $XONSH_CACHE_EVERYTHING = False

    # コードをcacheしておくか(T)、毎回コンパイルして実行するか(F)
    $XONSH_CACHE_SCRIPTS = True

 

ディレクトリ移動

    # ディレクトリ名を入力すればcdできる
    $AUTO_CD = False

    # ディレクトリ移動したらスタックにpush
    # dirstack実装 : https://pypkg.com/pypi/xonsh/f/xonsh/dirstack.py
    $AUTO_PUSHD = False

    # pushdした時にdirで現在のスタック内容を表示しない
    $PUSHD_SILENT = False

    # dirstack最大数
    $DIRSTACK_SIZE = 20

    # CD時にshとのroot関係が壊れないようにPATH指定するやつ
    # zshでいうこれ : https://robots.thoughtbot.com/cding-to-frequently-used-directories-in-zsh
    $CDPATH = ("/", )

    # cwdコマンドで指定したディレクトリに向けたショートカット
    $DYNAMIC_CWD_ELISION_CHAR = "/"

    # cwdプロンプト変数の文字数の指定
    $DYNAMIC_CWD_WIDTH = (inf, ‘c’)

 

変数、設定

    # PYTHON_PATH
    $PATH = (...)

    # 前回の作業ディレクトリ
    $OLDPWD

    # サブプロセスモードで文字列内の環境変数を展開するか
    $EXPAND_ENV_VARS = True

    # xonshの場所
    $XONSH_CONFIG_DIR = $XDG_CONFIG_HOME/xonsh

    # 外部のaliasを優先するかどうか
    # $XONSH_CONFIG_DIR/config.jsonに書くのでxonshrcに書いても意味はない
    $FOREIGN_ALIASES_OVERRIDE = False

    # $XONSH_CONFIG_DIR/config.jsonが読まれたかどうかがboolで入ってるので判定用
    $LOADED_CONFIG

    # 読見込まれたRCが動いているかのbool値のlist
    $LOADED_RC_FILES = (~/.xonshrc)

    # 連続でコマンド実行した時にスリープする秒数
    $XONSH_PROC_FREQUENCY = 0.0001

    # pretty printingの戻り値があるかどうか
    # import pprintしたりするなら
    $PRETTY_PRINT_RESULTS

    # configファイルへのPATH
    $XONSHCONFIG = $XONSH_CONFIG_DIR/config.json

    # rcファイルへのPATH
    $XONSHRC = ['/etc/xonshrc', '~/.xonshrc']

    # デスクトップ標準のディレクトリ
    $XDG_CONFIG_HOME = ~/.config

    # デスクトップ標準のデータディレクトリ
    $XDG_DATA_HOME = ~/.local/share

    # 実際のxonshデータが入っている場所
    $XONSH_DATA_DIR = $XDG_DATA_HOME/xonsh

    # ディレクトリプッシュがされているかどうかのフラグ
    $PUSHD_MINUS

    # xonsh環境が変化したかのフラグ
    $UPDATE_OS_ENVIRON

    # python実行環境へのPATH
    $VIRTUAL_ENV

    # インタラクティブ実行で動いてるかどうかのフラグ
    $XONSH_INTERACTIVE

    # xonshがログインシェルになっているかどうかのフラグ
    $XONSH_LOGIN

    # xonshスクリプトを実行している場合、そのスクリプトへの絶対Path
    $XONSH_SOURCE

 

Windows向け

    # Windowsのanxicon用
    $ANSICON = False

    # 補完した時に"/"を強制的に使用
    $FORCE_POSIX_PATHS = False

    # cmd.exe上で色を変える
    $INTENSIFY_COLORS_ON_WIN = True

    # Winでユニコード使う
    $WIN_UNICODE_CONSOLE

 

その他

    # readline, prompt_toolkit, random, best
    # 基本的にはptlが使われてそれ以外の状況ではよしなに選択してくれるbestでOK
    $SHELL_TYPE = best

    # プロンプトのタイトル
    # http://xon.sh/tutorial.html#customizing-the-prompt
    $TITLE = xonsh.environ.DEFAULT_TITLE

    # 文字コード
    $LANG = ‘C.UTF-8# サブプロセスが利用するエンコーディング
    $XONSH_ENCODING

    # エンコーディングエラーを処理するフラグ
    # https://docs.python.org/3/library/codecs.html#error-handlers
    $XONSH_ENCODING_ERRORS = surrogateescape

    # サブプロセスでエラーが出た時終了させるかどうか
    # xonshプロンプト上ではあまり良くないが、 xonshスクリプトを実行する時効果あり
    # subprocess.CalledProcessErrorがraiseされる
    $RAISE_SUBPROC_ERROR

    # historyでjson以外にsqliteが選べる
    $XONSH_HISTORY_BACKEND = ‘json’

    # historyファイルの保存先
    $XONSH_HISTORY_FILE = ~/.xonsh_history

    # コマンドやファイルのhistory保存数
    # http://xon.sh/envvars.html#xonsh-history-size
    $XONSH_HISTORY_SIZE = (8128, 'commands')

    # Standard I/OをHistoryに保存するか
    $XONSH_STORE_STDIN
    $XONSH_STORE_STDOUT

    # 端末エミュレータによるTerminalの設定色々。基本触る機会はない
    $TERM

    # エラーのトレースバックログを保存するPathの指定
    $XONSH_TRACEBACK_LOGFILE = "/"

    # デバッグ機能、数値に応じて以下が出てくる
    # 1, 重複importの抑制情報
    # 2, 入力変換、コマンド置換の情報
    # 3, PLYデバッガによる解析結果
    $XONSH_DEBUG = 0


 

- おわりに -

ひとまずまとめて終わりです。

またアドベントカレンダー内に空きがあれば自作のrcに書いている関数群を出していこうと思います。

誰か今からpip installして埋めてくれてもいいのよ!

qiita.com


 

xonshの過去のコマンド履歴を可視化する

- はじめに -

この記事は、Xonsh Advent Calendar 2017 - Qiitaの6日目の記事です。

せっかくxonshではMatplotlibが使えたりするので、Command履歴の分析等の補助をする関数を書いてメモしておきたいと思います。


 

- xonshのhistory -

xonshの過去の入力履歴は以下で呼び出す事ができます。

__xonsh_history__

実際には、xonshのコマンド履歴は以下のようにSession毎にjsonファイルで管理されています。

history file
# ~/.local/share/xonsh/xonsh-7305fb13-34ea-44fd-9845-197fe015359d.json

さっそくの余談ですが、このバックエンドにsqliteを指定する事も可能です(Tutorial: History — xonsh 0.6.0.dev151 documentation)。


__xonsh_history__で得られるxonsh.history.json.JsonHistoryオブジェクトは、Commandの履歴を取得するためのメソッドを2種類持っています。

__xonsh_history__.items()    # 今のSessionでのHistory
__xonsh_history__.all_items()    # 過去全てのSessionでのHistory

どちらもIteratorが返ってくるので、例えば現在過去全てのコマンド履歴を取得するには以下のように

for x in __xonsh_history__.all_items():
    print(x["inp"])

Reference : History Backend JSON – xonsh.history.json — xonsh 0.6.0.dev151 documentation


また、jsonを直接読みにいく事ももちろんでき、xonshのhistory.jsonを直接読みに行くスクリプトは、アドベントカレンダー内の以下の記事でも既に書かれています。

qiita.com


 

- 過去のコマンドを可視化 -

以下の記事でも利用したitermplotパッケージを利用して、iTerm2上にインラインに表示してみます。
導入や綺麗な表示の仕方は以下記事で。
(以下記事内にiTerm2以外の方法も一応記述しています)
vaaaaaanquish.hatenablog.com


空白で区切られた最初のコマンド部分が10文字以下のものをCounterに投げてMatplotlibに可視化します。

import itermplot
import matplotlib.pyplot as plt
import numpy
from collections import Counter

data = Counter([x["inp"].split(" ")[0] for x in __xonsh_history__.all_items() if len(x["inp"].split(" ")[0])<10])
labels, values = zip(*data.items())
indexes = np.arange(len(labels))

plt.figure(figsize=(20,10))
plt.bar(indexes, values, width)
plt.xticks(indexes, labels, rotation='vertical')
plt.show()

結果がxonshコンソール上で見えます
f:id:vaaaaaanquish:20171206225049p:plain


ちょっと業務で使ったものを削った結果を出していますが、これは恥ずかしいですね。

xonshなのでimportやforが多いのは当たり前ですが、ls しすぎだし、X, Yといった変数を使っていたり、果にはexitもかなり使っています。xonshが嫌いなのでしょうか。
これがまだ手元のMacなので良いですが、普段はリモートサーバで作業しているので、そちらではより酷いものが見れると思います(公開はしないですが)。


しかし、これでlsというコマンドにめちゃくちゃ時間を取られている事が分かりました。lsは基本的には自動的に発動するようにしていくのが吉という事ですね。

 
 
ついでなので最も多いimportから、何を多く使っているか見てみます。

data取得箇所を変えてやれば実現できそうです。

data = Counter([x["inp"].split(" ")[1] for x in __xonsh_history__.all_items() if x["inp"].split(" ")[0]=="import"])

 
import time, plt, mathが多そう。xonshrcに書いておいて事前importするようにすれば私の仕事も減りそうです。
f:id:vaaaaaanquish:20171206230255p:plain


 

- おわりに -

ギリギリ滑り込みセーフで記事を書きましたが何とかなりました。

もうちょっと分析らしいところまで行きたかったのですが、(見せてもOKそうな)Historyが以外に少なく、時間も微妙だったので断念しました。
まあでもギリギリでも可視化まで出来たのは、Pythonという言語がシェルで扱える事の利点でもあるなと思いました。

今まで使っていたzshのログのconvertとか前後のコマンドを確認とかまでやれれば良かった…が、アドベントカレンダーに空きを見つけて書きたいと思います。


それでも全然空きがありそうなので、xonsh試したい方でも是非ご参加下さい!!

qiita.com


 

Xonshでmatplotlibグラフをコンソールにインライン描画してメモリ状況を観察する

- はじめに -

この記事はXonsh Advent Calendar 2017 4日目の記事です。

Xonshの中にはxontribというメソッド群が存在します。
その中のmplhooksは、画像の描画をサポートしてくれます。

本記事では以下について記述します

  • xontrib.mplhooksを利用したxonshコマンドプロンプト上へのMatplotlibグラフのインライン描画
  • vm_statコマンドを利用したMac OS Xのメモリ状況の取得とPythonによるparse
  • Xonshでメモリ状況のリアルタイム可視化

以下アジェンダです


 

- Xonshのグラフインライン描画 -

Xonshでグラフは端末状にインライン描画する方法は、以下の2種類が容易されています。

  • xontrib.mplhooks.display_figure_with_iterm2(fig)
  • xontrib.mplhooks.show()

以下がソースコードです。
xontrib.mplhooks — xonsh 0.5.12.dev97 documentation
xonsh/mplhooks.py at master · xonsh/xonsh · GitHub
Pythonなのですぐ読めます。

display_figure_with_iterm2は、 iterm2_toolsを使ってiTerm2上にグラフを描画するようになっています。
showは、iterm2_toolsがimportできればdisplay_figure_with_iterm2で描画、iterm2_toolsが存在しない場合はplt.gcf()で現状プロット図を取得してきてRGB値をcolor stringにして描画する形になっています。

iTerm2でインライン描画

私はiTerm2利用者ですので以下でiterm2_toolsを導入しています。

pip install iterm2_tools

GitHub - asmeurer/iterm2-tools: iTerm2 tools for Python

以下エラーが出るのでXonshコンソールを再起動しておきます。

NameError: name 'display_image_bytes' is not defined

再起動後、Xonshコンソール上で以下を淡々と入力していきます。
もしくは適当にxshスクリプトにしてもOKです。

import matplotlib.pyplot as plt
import xontrib.mplhooks
import numpy as np
x = np.linspace(-3, 3, 20)
y = x ** 2
fig = plt.figure(figsize=(6, 4))
ax1 = fig.add_subplot(1, 1, 1)
ax1.plot(x, y)
xontrib.mplhooks.display_figure_with_iterm2(fig)

f:id:vaaaaaanquish:20171121140615p:plain:w350
xonsh上でもインライン描画できました

 

Terminal.app上のxonshでインライン描画

試しにMacにデフォルトで付随するTerminal.appでもXonsh上でインライン描画をしてみます。

上記iTerm2の時と同じGraphを作って以下。

xontrib.mplhooks.show()

f:id:vaaaaaanquish:20171121141037p:plain:w350
ちょっとアレですがまあまあ…

iTerm2の描画は良いですね

 

itermplotでインライン描画

上記2つに加えてiTerm2にはインライン描画パッケージとして、itermplotというのがあります。
GitHub - daleroberts/itermplot: An awesome iTerm2 backend for Matplotlib, so you can plot directly in your terminal.

Animation supportもされており、インラインでリアルタイム表示ができそうです。
(といっても事前にGIF画像にしてiTermの表示機能に送る形ですが…)

導入はpipで、xonshを起動する前にMPLBACKENDにitermplotを指定しておくとplt.show()がインライン描画になります。

pip install itermplot
export MPLBACKEND="module://itermplot"

また、後述しますがリアルタイム表示するにはImageMagickが必要なのでインストールしておきます。

brew install imagemagick

sampleスクリプトを動かしてみます。

import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.show()

f:id:vaaaaaanquish:20171202214602p:plain:w350
いちばんつよそう

背景が黒い場合は以下で良さげな表示に

export ITERMPLOT=rv


  

- vm_statコマンドでメモリ可視化 -

Macでメモリ状況を出力するコマンドではfreeやtop、vm_statといった選択肢があります。

今回は適当にvm_statを選択します。
Xonshであれば以下コマンドどちらも結果を得ることができます

vm_stat
$(vm_stat)    # python string

vm_statコマンドの結果をparseしてdictにする関数を作って実行してみます。

def vms():
    vm_dic = {}
    for i,x in enumerate($(vm_stat).split("\n")):
        row = x.split(":")
        if i>1 and len(row)==2:
            vm_dic[row[0]] = int(row[1].strip().replace(".",""))*4096/(1024.0 ** 3)
    return vm_dic

以下のようにGB単位でメモリ状況が出力されます。

$ vms()
{'"Translation faults"': 2588.0195083618164,
 'Anonymous pages': 7.266414642333984,
 'Compressions': 54.13356018066406,
 'Decompressions': 33.81982421875,
 'File-backed pages': 2.6624984741210938,
 'Pageins': 32.48748779296875,
 'Pageouts': 0.26355743408203125,
 'Pages active': 4.984306335449219,
 'Pages copy-on-write': 82.98124694824219,
 'Pages inactive': 4.944099426269531,
 'Pages occupied by compressor': 3.5574417114257812,
 'Pages purgeable': 0.14667129516601562,
 'Pages purged': 1.3369598388671875,
 'Pages reactivated': 22.909423828125,
 'Pages speculative': 0.000507354736328125,
 'Pages stored in compressor': 8.809425354003906,
 'Pages throttled': 0.0,
 'Pages wired down': 2.446277618408203,
 'Pages zero filled': 1392.7644996643066,
 'Swapins': 16.50379180908203,
 'Swapouts': 17.286388397216797}

 
せっかくですのでwatchコマンドのように、メモリ状況をリアルタイムで表示し続けてみます。

import json
while True:
    vm_dic = vms()
    $[clear]
    print(json.dumps(vm_dic, indent=4))

f:id:vaaaaaanquish:20171121144149g:plain:w400

watch vm_statでよくない!?みたいな何かが出来上がりました。

vms functionをprintするスクリプトにして、watchもできます。
watchコマンドはデフォルトでsh -cにコマンドを飛ばすだけなので、--exec, -xで指定できるよう環境設定するか、以下のようにxonshを定期的に作るという酷いやつで対応できます。

# mac -> $ brew install watch
watch "xonsh sample.xsh"

watch vm_statでよくない!?みたいな何かです。

  

- vm_statをMatplotlibでリアルタイム描画 -

上記2項目で作った関数を利用して、Matplotlibでvm_statの結果をリアルタイム描画してみます。

wired, active, inactive, speculative辺りがusedメモリに関連する項目ですのでそちらを可視化してみます。
(occupied by compressorも必要かな?)

スクリプトが適当です。

import time
import xontrib.mplhooks
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot') 

def init_data(fig, id, title):
    x = np.zeros(100)
    y = np.zeros(100)
    subplot = fig.add_subplot(2,2,id)
    subplot.set_title(title)
    subplot.set_ylabel('GB')
    subplot.set_xlabel('time')
    li, = subplot.plot(x, y)
    return x, y, subplot, li

def set_data(x,y,vm_dic,key):
    x = np.append(x, time.time())
    x = np.delete(x, 0)
    y = np.append(y, vm_dic[key])
    y = np.delete(y, 0)
    return x,y

def update_fig(x, y, subplot, li):
    li.set_xdata(x)
    li.set_ydata(y)
    subplot.set_ylim(min(y), max(y))
    subplot.set_xlim(min(x), max(x))

def watch_vms_windows():
    fig = plt.figure()
    x,y,subplot,li = init_data(fig, 1, "Pages active")
    x2,y2,subplot2,li2 = init_data(fig, 2, "Pages inactive")
    x3,y3,subplot3,li3 = init_data(fig, 3, "Pages speculative")
    x4,y4,subplot4,li4 = init_data(fig, 4, "Pages wired down")
    count = 0
    while True:
        vm_dic = vms()
        x,y = set_data(x, y, vm_dic, "Pages active")
        x2,y2 = set_data(x2, y2, vm_dic, "Pages inactive")
        x3,y3 = set_data(x3, y3, vm_dic, "Pages speculative")
        x4,y4 = set_data(x4, y4, vm_dic, "Pages wired down")
        if count > 100:
            update_fig(x, y, subplot, li)
            update_fig(x2, y2, subplot2, li2)
            update_fig(x3, y3, subplot3, li3)
            update_fig(x4, y4, subplot4, li4)
            plt.pause(.01)
        else:
            count += 1
            print(count, end="\r")

以下参考にしています。
Arduino で測定したデータを Matplotlib でリアルタイムプロット | org-技術

100ループ回してGraph描画に十分なデータを集めたらGraph描画を開始するスクリプトです。

f:id:vaaaaaanquish:20171121144909g:plain

QuickTime Playerを利用して画面の動画を撮っているのでactiveがガンガン上昇しinactiveが下降、メモリ利用と廃棄が頻繁に行われている事がわかります。


$[clear] して display_figure_with_iterm2(fig) でインライン描画するスクリプトにする事も可能で、試しましたがdisplay_figure_with_iterm2では実行時描画になるため、思ったより綺麗に表示されませんでした。


 

- MatplotlibのAnimationモジュールを使ってリアルタイム描画を実現する -

Matplotlibにはpltで作られた配列をアニメーションにして表示するモジュールが存在する。
全てのGraphを事前に配列に取っておいて描画するArtistAnimation、動的に生成していくFuncAnimationの2つである。
animation module — Matplotlib 2.1.0 documentation

Animationはgifやmp4を生成するだけなので、これらを前述したitermplotに流してiTerm2にインライン描画する。

itermplotのカッケー背景はAnimationには対応してないので以下だけ設定しておく。

export MPLBACKEND="module://itermplot"
export ITERMPLOT_FRAMES=100

適当に書いたコード

import time
import xontrib.mplhooks
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
plt.style.use('ggplot') 

class VMS:
    def __init__(self, fig):
        self.fig = fig
        self.x, self.y, self.subplot, self.li = self.init_data(1, "Pages active")
        self.x2, self.y2, self.subplot2, self.li2 = self.init_data(2, "Pages inactive")
        self.x3, self.y3, self.subplot3, self.li3 = self.init_data(3, "Pages speculative")
        self.x4, self.y4, self.subplot4, self.li4 = self.init_data(4, "Pages wired down")
        self.c = 0
        for i in range(100):
            self.plotsub(i)
        
    def init_data(self, id, title):
        x = np.zeros(100)
        y = np.zeros(100)
        subplot = self.fig.add_subplot(2,2,id)
        subplot.set_title(title)
        subplot.set_ylabel('GB')
        li, = subplot.plot(x, y)
        return x, y, subplot, li

    def vms(self):
        vm_dic = {}
        for i,x in enumerate($(vm_stat).split("\n")):
            row = x.split(":")
            if i>1 and len(row)==2:
                vm_dic[row[0]] = int(row[1].strip().replace(".",""))*4096/(1024.0 ** 3)
        return vm_dic

    def count(self):
        self.c += 1

    def plotsub(self, frame):
        vm_dic = self.vms()
        self.count()
        # subplot1
        self.x = np.append(self.x, self.c)
        self.x = np.delete(self.x, 0)
        self.y = np.append(self.y, vm_dic["Pages active"])
        self.y = np.delete(self.y, 0)
        self.li.set_xdata(self.x)
        self.li.set_ydata(self.y)
        self.subplot.set_ylim(min(self.y), max(self.y))
        self.subplot.set_xlim(min(self.x), max(self.x))
        self.subplot.set_xticks(np.arange(min(self.x), max(self.x), 20))
        # subplot2
        self.x2 = np.append(self.x2, self.c)
        self.x2 = np.delete(self.x2, 0)
        self.y2 = np.append(self.y2, vm_dic["Pages inactive"])
        self.y2 = np.delete(self.y2, 0)
        self.li2.set_xdata(self.x2)
        self.li2.set_ydata(self.y2)
        self.subplot2.set_ylim(min(self.y2), max(self.y2))
        self.subplot2.set_xlim(min(self.x2), max(self.x2))
        self.subplot2.set_xticks( np.arange(min(self.x2), max(self.x2), 20) )
        # subplot3
        self.x3 = np.append(self.x3, self.c)
        self.x3 = np.delete(self.x3, 0)
        self.y3 = np.append(self.y3, vm_dic["Pages speculative"])
        self.y3 = np.delete(self.y3, 0)
        self.li3.set_xdata(self.x3)
        self.li3.set_ydata(self.y3)
        self.subplot3.set_ylim(min(self.y3), max(self.y3))
        self.subplot3.set_xlim(min(self.x3), max(self.x3))
        self.subplot3.set_xticks( np.arange(min(self.x3), max(self.x3), 20) )
        # subplot4
        self.x4 = np.append(self.x4, self.c)
        self.x4 = np.delete(self.x4, 0)
        self.y4 = np.append(self.y4, vm_dic["Pages wired down"])
        self.y4 = np.delete(self.y4, 0)
        self.li4.set_xdata(self.x4)
        self.li4.set_ydata(self.y4)
        self.subplot4.set_ylim(min(self.y4), max(self.y4))
        self.subplot4.set_xlim(min(self.x4), max(self.x4))
        self.subplot4.set_xticks( np.arange(min(self.x4), max(self.x4), 20) )


fig = plt.figure(figsize=(8,8))
vms = VMS(fig)
animation.FuncAnimation(vms.fig, vms.plotsub, blit=True)
plt.show()

plt.show()がitermplotによって継承されてればインラインで見れる
f:id:vaaaaaanquish:20171203221702g:plain

これは動的に見れている訳ではなく、事前に100フレーム分をgif画像にしてbyteIOでiTerm2に送り込んでいるだけなのでリアルタイムの本質を見失っている状態である。

iTerm2に表示できるGIFのフレーム数を上手くコントロールできないとか課題は多いがまあできたという事で…

 

- おわりに -

「これ watch vm_stat で良くね!?」
「リアルタイムインライン描画とは」
Pythonスクリプトなら os.system や commands.getoutput でコマンド実行できるよね!?」
「これXonshじゃなくても良くない!?」
等の耳が痛い声が聞こえて来ます。

どんどんおかしい方向に進んだ気がしますが、xonshの繁栄のための知見として納めておきます。

おわり。

 

Webスクレイピングする際のルールとPythonによる規約の読み込み

- はじめに -

この記事は Webスクレイピング Advent Calendar 2017 - Adventar の1日目の記事です。

近年では、Pythonが様々な場面で使われるようになりました。
Webからデータを取ってくる際のスクリプトとして利用し、そのままデータを機械学習における学習データとするといった案件も多く見るようになっています。

ありがたい事に本年度書きました以下の記事は、はてなブログに投稿されたPython関連の記事の中で歴代はてブ数1位だそうです。

Webスクレイピングも日に日に情報が増え、様々なパッケージやフレームワークによって手軽になっています。

本記事は、スクレイピングやクローラを記述する際に抜けがちな、「規約」について記載するものです。

スクレイピングの間隔はどうすればいい?規約は?違法でないの?という人のために法律等もまとめています。

追記2019/01/07:
著作権法が改正され、機械学習モデリングなどに使えるスクレイピング関連のデータの取扱も変わりました。
以下の記事が詳しいので一読しておくと良いでしょう。
www.itmedia.co.jp


アジェンダ


 

- Webスクレイピングにおけるルール -

Webスクレイピングまとめ記事の後半で記載しているが、ネット上のデータを収集して取り扱う上での著作権法対象のWebサーバに適切にアクセスし身元の開示や負荷を考える上での動産不法侵入の2つを特に気にすべきである。

よりシンプルに以下にまとめてあるため、参考に。
https://vaaaaaanquish.hatenablog.com/entry/2017/06/25/202924#法律の話


 

著作権法

前者の著作権法は、スクレイピングしたデータでデータセットを作って公開したりしたらダメ、データ分析に使用する場合は他法律に触れなければOK等といった内容で、SNS等でもよく議論に上がる知的財産権に属する内容である。

日本におけるスクレイピングでの著作権の取扱は「つまるところ、データ分析や教育、引用等の認められた利用の範囲内であれば、スクレイピング行為自体は著作権法上認められた行為」となっている。これについては、以下記事が最も参考になる。
「日本は機械学習パラダイス」 その理由は著作権法にあり - ITmedia NEWS

公開されている情報の利用、機械学習におけるデータの取得等は、著作権法においては問題ない。
しかし得たデータの分析においては問題ないが、それらを公開したり、そのデータを直接的に利用して金銭を得る事は問題となる。
また当然、各サービスの規約や後述する動産不法侵入、robot.txtによって制限されている場合がある。

また、取得するスクリプトの公開等についても現状グレーとなっている。

ちなみに取得著作物が自由に使えるパターンについては文化庁のWebサイトにある以下を見ておくと良い。

 

動産不法侵入

後者の動産不法侵入は、スクレイピングするコードを書いたのだから意図性がある、相手のサーバへの負荷を考慮する、Webページが提示する条項を守るといった内容である。
著作権等で認められた場合でも高負荷なbotを作成した場合、例えツールを利用しただけの場合でも意図性が優先され裁判となる可能性がある。

相手のサーバの負荷、ネットワークの負荷、アクセス先の制約について「知らなかった」で済まされないようになっており、また実際の判例も存在する。

 
本記事で取り扱う規約保持のスクリプトは、主に後者の動産不法侵入の内容に含まれるWebページが提示する条項を守る「同意の欠如」から身を守るためのものである。

主に以下の内容をPythonスクリプトで実行していくための記事である。

  • aタグにrel="nofollow"が設定されていたら辿らない
  • robots metaタグの属性記載に従う
  • HTTP ヘッダーのX-Robots-Tagに従う
  • robots.txtに従う
  • User-agentなどを正しく設定する


   

- robot.txt -

metatagやHTTPヘッダーの確認も重要であり、後述するが、まず前提としてrobot.txt周りの話を記述する。

robot.txtとは

robot.txtとはクローラーに対する指示書である。

1994年に採用されたMK1994、および拡張のMK1996Google, Yahoo and Microsoftが2008年に出してきたGYM2008、2007年のACAP等が存在し、各検索サービス等が対応したりしていなかったりというのが現状である。

そもそもは検索エンジンのクローラに対する指示書。
これ以上の歴史的経緯は割愛するが、気になる場合は以下追っていくと良。
Nikita The Spider * Articles and News
Robots Exclusion Standard - WikipediaAutomated Content Access Protocol - Wikipedia

 
Webスクレイピング、クローリングをする上では、HTACCESS等より拘束力はないが、まずはじめにrobot.txtの準拠をしておくと良い。

robot.txtの拘束力については、「法として定義されたルールではない」「検索エンジンに向けたものでありスクレイピングにおいて準拠すべきか」などの議論が幾度となく繰り返されているが、そちらについてはここでは強く言及しないものとする。

拘束力についての議論もありながら、現実robot.txtの準拠については事件の判例にも関わっている。
検索エンジンと著作権 - 三浦基/小林憲一
フィールド対Google事件 - Wikipedia
Google、新聞記事掲載が著作権侵害とするベルギーの判決にコメント

また、以下日本における「1回URL叩いたら1秒Sleepしましょう」という言説の元となっている、国立国会図書館法に関連する資料にもrobot.txtに関する記載がある。
国立国会図書館法によるインターネット資料の収集について

この国立国会図書館の資料については、言及しておく。
岡崎市立中央図書館事件について調べ、容疑者のブログ等をよく読むと理解できるはずだが、「1アクセスごとに1秒の間隔」という基準に意味は何の意味もなく、これらの言説は無視すべきである(筆者はそういった基準を国立国会図書館が公開している事自体どうかと思う)。この岡崎市中央図書館の件は、スクレイピング時に間隔を開けていたにも関わらず、サーバ側の不具合によって高負荷と判断され、逮捕、起訴猶予となった。高木浩光氏のブログにもあるように、明らかな誤認逮捕であり、警察、検察ならびに岡崎市の技術理解が乏しい事が分かったというだけの事件ではあったものの、この事件のように「相手のサーバにとっての高負荷」が発生してしまうだけで裁判となる可能性があり、その事について我々は肝に命じておくべきである。

 
要は「節度」となるのだが、実際の判例を見るに準拠しておいて損はないだろう。


これらが気になる場合は、以下の書籍に歴史的経緯や判例の項目があるため、一読すべきである。

Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術

Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術

 

robot.txtフォーマット

  
robot.txtはドメイン直下に配置されるテキストファイルであり、Webスクレイピングやクローリングを行う際、以下のように読みに行く事になる。

https://hogehoge.com/robot.txt

以下にrobot.txtのsampleを示す。

User-agent: *
Disallow: *

User-agent: Googlebot
Allow: *
Disallow: /private

上記は「Googleクローラーは/private以外どこでもアクセスしていいけど、それ以外のbotは全て禁止する」という指示を記したものである。

基本的にMK1994のSyntaxに従っていれば、python内のurlib.robotparserでparseする事が出来る。
後述するように、自作パーサーを作る他、Robotexclusionrulesparser、reppyといったパーサーパッケージも存在する。

また、一部Webスクレイピングまとめ記事でも紹介したようなmechanizeパッケージ等、自動でrobot.txtを読み込んでキャッシュしておき、規約に応じたスクレイピングが可能なものもある。

# mechanize
# set_handle_robots(False)しなければ以下エラーになる
httperror_seek_wrapper: HTTP Error 403: request disallowed by robots.txt

http://wwwsearch.sourceforge.net/mechanize/

後述するようにスクレイピングのためのフレームワークとしても有名なScrapyにもそれらを適応するパラメータが存在する。


 

- Pythonスクリプトでの規約の読み込み -

上記の内容を踏まえ、Pythonで各規約情報を読み込むスクリプトを示す。
ここでは「aタグのrelチェック」「robot metaの検出」「HTTPヘッダーのチェック」に加えて、既存のPython謹製パーサーによるrobot.txtのパースについて記述する。

aタグのrelチェック

aタグにはrel属性でnofollowが指定されている場合がある。
rel="nofollow"はスパムコメントに対する防御策として提案され、コメント欄等にスパムURLが投稿される可能性のある箇所に自動的にnofollowを付ける事で、GoogleやYahooの検索エンジンにおけるリンク先考慮のPageRankを下げないように設置するものである。
nofollow - Wikipedia
RFC 3667 - IETF Rights in Contributions
RFC 3668 - Intellectual Property Rights in IETF Technology

近年ではSEO対策に加え、スクレイピング負荷対策等に使われる場合がある。

robot.txtに比べスクレイピング、クローリングに対する拘束範囲は小さいが、rel="nofollow"されたリンクはWebサイト作者の意図しないリンクである可能性が高いため、処理しておくと良い。


BeautifulSoupならfindAllの引数としてlambdaや正規表現が渡せるので、それらを利用する。

from bs4 import BeautifulSoup
import re

html = """
<html><body>
<a href="sample.com" />
<a rel="nofollow" href="badsample.com" />
<a rel="nofollow" href="badsample.com" />
<a href="sample.jp" />
<a href="sample.ne.jp" />
</body></html>
"""

soup = BeautifulSoup(html, "html5lib")
# hrefが設定されておりrelにnofollowが設定されてないaタグを探す
links = soup.findAll('a', href=True, rel=lambda x: "nofollow" not in str(x).lower())
for link in links:
    print(link['href'])


lxmlを使って解析している場合はrel属性のついたlinkを探せるfind_rel_linksがある。

import lxml.html

h = lxml.html.fromstring(html)
for x in h.find_rel_links("nofollow"):
    print(lxml.html.tostring(x))


 

robot metaの検出

クローリングされないため、Webサイトにmetatagとしてnofollow、noarchive、noindexを設置する方法がある(他にもnocacheや特定サービス拒否のcontent属性がある)。noarchiveであればそのページを保存しないし、nofollowがついていれば以降リンクを走査しないようにしておくと安全。
http://www.robotstxt.org/meta.html
HTML 4.01仕様における記載

BeautifulSupの解析器にLambdaを投げるのが吉。

from bs4 import BeautifulSoup
html = """
<html><body>
<meta content="nofollow" name="robots"/>
<meta content="noarchive" name="robots"/>
<meta content="noindex" name="robots"/>
<a href="sample.com" />
</body></html>
"""

soup = BeautifulSoup(html, "html5lib")
meta = soup.find_all('meta',
                     attrs={"name":"robots"},
                     content=lambda x: "nofollow" in str(x).lower() or "noarchive" in str(x).lower())
print(meta)
print(len(meta) > 0)


 

HTTPヘッダーにおけるX-Robots-Tagのチェック

Googleによると、HTTPヘッダーでも上記metatag設定と同義の事ができるらしい。
Robots meta tag and X-Robots-Tag HTTP header specifications  |  Search  |  Google Developers

一応チェックできる。例えばrequestsなら下記。

import requests
r = requests.get('https://hogehoge.com')
print( "nofollow" not in str(r.headers.get("X-Robots-Tag")) )
print( "noarchive" not in str(r.headers.get("X-Robots-Tag")) )

設定してるWebページがそこまで多い訳じゃないが、見ておくと良さげ。

 

urllib.robotparserを使ったrobot.txtのparse

21.10. urllib.robotparser — robots.txt のためのパーザ — Python 3.6.5 ドキュメント

Pythonデフォルトで使えるパーサ。

Googleのrobot.txtをparseしてみる。

[https://www.google.com/robots.txt]

以下のように読み込んでcan_fetchしていく

import urllib.robotparser
rp = urllib.robotparser.RobotFileParser()
rp.set_url("https://www.google.com/robots.txt")
rp.read()

# エージェントがURLを見れるか
if rp.can_fetch("*", "https://www.google.com/search"):
    print("OK")
else:
    print("NG")

# クローラの遅延時間指定パラメータの取得
# なければNone
print(rp.crawl_delay("*"))
print(rp.request_rate("*"))

参考:Parsing Robots.txt in python - Stack Overflow

 

Robotexclusionrulesparserを使ったrobot.txtのparse

Robotexclusionrulesparserはurllib.robotparserのBSD License代替スクリプト
Nikita The Spider * A Robot Exclusion Rules Parser for Python

前述したGYM2008とMK1994/96との構文の差で発生する問題(ワイルドカード*をどう読むか)等について触れられており、両者をparseできるようになっている。non-ASCIIやBOM等にも対応。
RobotExclusionRulesParser and RobotFileParserLookalikeの2つのクラスを提供していて前者がwrapperになっている。
BSDライセンスなのでGithubで検索すると導入しているところがちらほら。

以下URLのスクリプトを利用するか、pipで導入する。
http://nikitathespider.com/python/rerp/robotexclusionrulesparser-1.7.1.py

pip install robotexclusionrulesparser

使い方はほぼurllibと同じ。

import robotexclusionrulesparser

rerp = robotexclusionrulesparser.RobotExclusionRulesParser()
rerp.fetch('https://www.google.com/robots.txt')
if rerp.is_allowed('*', '/search'):
    print("OK")
else:
    print("NG")

get_crawl_delayやparseもあるので結構使える。
複数のWebサイトを取って回る、urllibじゃparseできない時に有用。

 

reppyを使ったrobot.txtのparse

robot.txtのparseパッケージ
クロール遅延やサイトマップの読み込み、robots.txtをキャッシュしておく機能が備わっている。
GitHub - seomoz/reppy: Modern robots.txt Parser for Python

導入はpipで

pip install reppy

使い方もほぼ上記と同じ。
sitemapが見れるだけでなくHeaderWithDefaultPolicyでこちらのPolicyに合わせてbool値が出せたりする。

from reppy.robots import Robots

# This utility uses `requests` to fetch the content
robots = Robots.fetch('https://www.google.com/robots.txt')
if robots.allowed('https://www.google.com/search', 'robot'):
    print("OK")
else:
    print("NG")
    
print(robots.agent('*').delay)
print(list(robots.sitemaps))

reppyの強みはcacheにある。

from reppy.cache import RobotsCache
robots = RobotsCache(capacity=100)
robots.allowed('https://www.google.com/search', 'robot')
print(robots.cache)

これによりrobotsを使いまわしながら、複数のサイトのrobot.txtを採用しながらスクレイピングを行うことができる。

 

scrapyではどうすればいいの?

scrapyでは、以上のrobot.txtパーサを利用しなくてもurllibを利用してくれるパラメータが存在する。

ご存知の通り、scrapyのデフォルト設定はスクレイピング先のサーバに負荷をかけまくる極悪設定になっているので、必ず以下くらいを設定しておくと良い。

DOWNLOAD_DELAY = 5
ROBOTSTXT_OBEY = True 

負荷を気にするなら、そもそもScrapyを使わないという選択肢も大いにあるが…


 

- おわりに -

robots.txt、Metatags辺りに対応する方法についてまとめておきました。

最近、辻さんがTwitterで仰っていましたが、robot.txtとnoindexを情報隠ぺいのように使う企業も存在します(下記はrobot.txtとタグの優先順序により失敗していましたが…)。


直近だと、Ads.txtなるものも出てきました。
Industry Aligns to Adopt ads.txt Specification – IAB Tech Lab

今後クローラ界隈がどうなっていくかは未知ですが、する側もされる側も良識を持って対応しなければいけないというのが現状で、こうしていれば間違いない、批判されないという方法はありません。

日本では解析のためのWebスクレイピングが認められている訳ですが、その中でも全員が節度を持って行動する事が全員のためになると私は思います。
「日本は機械学習パラダイス」 その理由は著作権法にあり - ITmedia NEWS


最後になりましたが、上記に加えてWebスクレイピングを行う際はUser-Agentを適切に設定しましょう。

明日はanoChickさん!期待です!
adventar.org


Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術

Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術

 

Pythonistaに贈るXonshのススメ

- はじめに -

この記事は Xonsh Advent Calendar 2017 1日目 の記事です。

タイトルが煽りです。

なんとなく贈るという単語が12月っぽいです。

内容は、Pythonで動くShellである「xonsh」の勧めを書く記事です。


追記2018/06/25:

xonshの設定に関する記事を書きました。
本記事よりも利用した上でのxonshの概要やメリット、デメリット、設定方法まで詳しく以下記事に書いてます。
vaaaaaanquish.hatenablog.com

xonsh 0.7.0が出ていますが、現在prompt-toolkit2.0の各機能対応中という感じです。
これは、ptk1.x -> 2.xにおいて結構な破壊的変更があるためです。現状はpip install xonshする時に
pip install xonsh==0.6.10
pip install prompt_toolkit==1.0.15
としておくと良いと思います。

 

- xonshとは -

xonshは、Pythonで作られたクロスプラットフォームUnixライクなシェル言語とコマンドプロンプトです。

sh + Pythonインタプリタのような取扱が可能です。
つまり以下のような事ができます。

f:id:vaaaaaanquish:20171118064346p:plain:w400:h350

もはやシェルスクリプトを触っているのかPythonを書いているのか分からなくなってきます。

後述しますが、もちろんShell scriptとPython scriptをサブプロセスで動作させ、それぞれの結果を参照する事も可能です。


XonshはPyCon2016でも発表されており、YouTubeに動画が上がっています。
youtu.be
その時のスライドが以下
http://lucasicf.github.io/talks/shell_python/#/


良い機能をいくつか挙げると、xonshrcがPythonで書ける、ptkとprompt-toolkitに対応しており拡張も書ける、pygmentsによるシンタクッスハイライト、proctitle対応などがあります。

bashzshユーザ各位に殴られそうな、公式の比較の表があるので貼っておきます。

f:id:vaaaaaanquish:20171118065738p:plain
http://xon.sh/index.html#comparison


基本的に疑問があったら、Githubのissueで作者がカジュアルに色々答えてくれてたりします。
StackOverflowよりissueみたいな状態です。
もちろん私のTwitterでも答えれる限りで答えます。


 
ちなみに下記ツイートみたく「まだ日本語の情報が全然ないのでアドベントカレンダーを書いてほしい」とTwitterで散々言っていましたが、アレはほぼウソで、英語の情報も全然ないのでみんなGithub issueに集まるというのが今です。使ってみた記事を書くなら今です!


ドキュメント : http://xon.sh/index.html
Github : https://github.com/xonsh/xonsh
作者がxonshについて語るpodcast : https://www.podcastinit.com/episode-29-anthony-scopatz-on-xonsh/


 

- 導入 -

http://xon.sh/#contents 内のInstallationに書いてある。
Mac, Windows, Linuxそれぞれの代表的なパッケージ管理やpip、condaを使ってのインストールが可能。

pyenv上のpipでインストールすると `/Users/hoge/.pyenv/shims/xonsh` にXonshが入る。
今時居ないかもしれないが、仕事の都合で2系と3系を行き来するという場合は不便な場合がある。

そもそもvenvやvirtualenv、pewなどがbashzsh向けに作られているために上手く動作しないので、Xonshでは Vox なる独自のenvツールが用意されている。
http://xon.sh/python_virtual_environments.html
virtualenvっぽい形式で操作が可能なので、純粋に標準Pythonで入れてVoxで十分な環境構築が可能である。

 
試しにPython3.xに付随するpipで導入してみる。
readline shellとして使いたい時はgnureadlineも必要。引数周りが激的によくなる。

pip install xonsh
pip install gnureadline

Macの場合のみ以下bashの補完パッケージを入れておく。

brew install bash-completion2

xonshコマンドで実行するか、`which xonsh` した先のxonshを標準コマンドプロンプトとして登録すれば終わり。

$ xonsh


 

- 使ってみよう -

導入は済んだね!

イエーイ!!
よくできました!!

それじゃあさっそくテンション上げて使ってみましょう!!
 

Pythonとshell scriptどちらも走る

変数を使ったりコマンドを使う事もできるよ!簡単だね!

 $ ls -l
total 0
 $ ls = 100
 $ l = 20
 $ ls -l
80
 $ del ls
 $ ls -l
total 0

面白いね!

 

サブプロセスとして走らせる

shell scriptとpython stringの相互変換もできるよ!
その結果をpipeしたりredirect、I/O redirect、background jobにすることも容易だよ!

もちろん下に書くサブプロセス演算子は複合して色々書けるけど悪用しないでね!公式もそう言ってるよ!絶対ダメだよ!
http://xon.sh/tutorial.html#nesting-subprocesses
 

shell script -> python string

$()でPython Stringが返ってくるよ!

x = $(ls -l)
print(x)    # lsの結果
shell script -> python class

!()でClassが返ってくるよ!

x = !(ls .)
print(type(x))    # <class 'xonsh.proc.CommandPipeline'>
python -> shell script

@でPythonスクリプトの結果が文字列が返ってくるよ!

import sys
echo @(sys.version_info.major)   # 3
python -> stdio

実行結果を直接出力してNone返す事もできるよ!

x = ![ls -l]    # この行が走った時点で標準出力される
x is None    # True

 

スクリプトとして走らせる

xonshコマンドで-cオプションをつければスクリプトが走るよ!

xonsh -c "echo @(7+3)"

test.xshでスクリプトファイルを書くこともできるよ!

#!/usr/bin/env xonsh
# test.xsh
echo @(7+3)

上のファイルを走らせるよ!

xonsh test.xsh

別fileからのスクリプトのインポートもPythonらしさあるよ!

from test import *

以下が参考になるよ!
http://xon.sh/tutorial.html#executing-commands-and-scripts
http://xon.sh/tutorial.html#importing-xonsh-xsh

 

xonshrc

Pythonでxonshrcが書けるよ!

Pythonで関数を定義してその関数にaliasを貼ったりできるからPythonさえ書ければshell script忘れてもまあ書けるし、「よく分からんけどネットで見つけたshコピペしてbashrcに貼ってる」みたいなPythonエンジニアにはオススメだよ!もちろんそんなエンジニアは居ないと思うけどね!!

/etc/xonshrcを書こうね!

# xonshrc
def _hello(args, stdin=None):
    return ('Hello, World!', None)
aliases['hello'] = _hello

実行してみよう!

 $ source /etc/xonshrc
 $ hello    # Hello, World!

http://xon.sh/tutorial.html#customizing-the-prompt

xonshrcのイケてるセッティングはきっとXonsh Advent Calendar 2017で出揃うから要チェックだよ!


 

- bashからの移行 -

Bash to Xonsh Translation Guide — xonsh 0.7.0 documentation

ガイドがあるよ!簡単だね!

 
 

- おわりに -

テンションに疲れましたがこんな感じです。

Xonshはまだまだ情報がネットになく、日本語の記事は多分この記事が最初という感じですが、Pythonを日常的に使っていればかなり便利に取り扱う事ができるシェルだと思います。

Futureでは、urwid base化やPython2系対応、各Mac OS検証が提言されており、コミッターも募集しています。Pythonユーザの増加から考えても、今後も拡張が続きそうです。


python toolkitを使ってみた記事やxonshrcのイケてる書き方から、RNNでコマンド予測してみたみたいなハードな記事まで、アドベントカレンダーは未だ人を募集しています

さあ今すぐpip install

qiita.com

 
追記1:

アドベントカレンダー1日早く投稿してしまいました…
 
追記2:

xonshの読み方について

聞き間違いっぽい↓

今一番有力
コンシュが正解として俺もコンシュと読んでる


一応公式ページでランダムに表示される文言の中に [コンシュ] が入っている。
f:id:vaaaaaanquish:20180520181037p:plain

その他、カンク/コンクという強めの説もある。
GitHub - xonsh/xonsh: Python-powered, cross-platform, Unix-gazing shell
`pronounced conch`



正直わからんのでコンシュで…

 
 

CIKM2017聴講メモ(後編)

- はじめに -

シンガポールで行われているInternational Conference on Information and Knowledge Management (CIKM) 2017に参加した。

workshop day + main conference day (3day) の合計4日間。
メモはその場で書いたものを少し編集しただけで、論文を詳しく読めているものと読めていないものがある。論文読みは別途。
メモだけは長くなりそうなので前半後半に分ける。

以下が前半

各文献は以下から追える
dblp: 25. CIKM 2017


 

- Conference(3日目) -

大雨で笑った。シンガポール蒸し暑いし、スコールが厳しい。
また最後のセッションが3つしかないのはDEMOみたいなのがあったからで、今回はそちらを見ていた。

Metaricaみたいなデータ分析、ビジュアライズツールの作者がDEMOをしていた。
Metarica:https://hpi.de/naumann/projects/data-profiling-and-analytics/metacrate.html
他で気になったのは特段無かったかなあ…

 

Online learning, Stream mining

BoostVHT: Boosting Distributed Streaming Decision Trees

オンラインなBoostingは並列化難しいと言われているが、提案するBoostVHTなら分散エンジンにも乗るし分類も適切にできるよという話。

Vertical Hoeffding Tree(VHT)は、1つのModel Aggregatorが複数の統計計算をコントロールしてその結果を使って学習していくモデル。計算した複数の結果から上位を選んで(木であれば)葉の分割するしないを決定してModel Aggregatorが更新されていく。

VHTのつらいところはOzaBoostとかAdaBoost、OSBoostといった最近のBoostingモデルに適応する時に、各インスタンスの重みを変更する部分で相互接続が必要になること。なので、Model Aggregatorの部分を以下のように逐次的な感じにしてやれば良いのではという話。

f:id:vaaaaaanquish:20171118225545p:plain:w350f:id:vaaaaaanquish:20171118225553p:plain:w350<

既存のMOA(OzaBoostの並列拡張)と同等くらいに早くて精度が高い。
Boosting好きそうな登壇者とBoosting好きそうな質問者による質疑があり、Git公開も考えてるとのことだった。

VHT: Kourtellis, Nicolas, et al. "VHT: Vertical hoeffding tree." Big Data (Big Data), 2016 IEEE International Conference on. IEEE, 2016.
MOA: Bifet, Albert, et al. "Moa: Massive online analysis." Journal of Machine Learning Research 11.May (2010): 1601-1604.
SAMOA: Morales, Gianmarco De Francisci, and Albert Bifet. "SAMOA: scalable advanced massive online analysis." Journal of Machine Learning Research 16.1 (2015): 149-153.

 

Stream Aggregation Through Order Sampling

論文: Stream Aggregation Through Order Sampling

ユニークキーの無いデータで効率的にオーダーサンプリングするアルゴリズム、Priority-Based Aggregation(PBA)の提案。

スライドにも数式多く、時間ないと分からない部分が多すぎるので論文を読む。

 

FUSION: An Online Method for Multistream Classification

論文: FUSION

ストリーム状のデータ分類では、データにあるドメイン情報があるはずで、それらを利用してsourceを学習した結果を活かしながらtarget学習できるアーキテクチャを提案。

f:id:vaaaaaanquish:20171118233930p:plain:w350

図内のDensity Ratio Estimation Module(DRM)が入力データストリームと今までの分布の差を計算、Drift Detection Module(DDM)に回りしきい値を超えた場合に「入力データ分布が変わった(driftした)」として学習が進むアーキテクチャ

結果いい感じだけどどういった状態で使うかなぁというイメージ。

 

Deep Learning 1

部屋を間違えて1つ目の発表を聞き逃す等した

Length Adaptive Recurrent Model for Text Classification

論文: Length Adaptive Recurrent Model for Text Classification

テキスト分類のLSTMに対して以下のようにFCN付けて拡張したLength Adaptive Recurrent Model(LARN)を提案。

f:id:vaaaaaanquish:20171118235602p:plain:w350

まあテキスト全体と一部の効果どっちも欲しいよねという前提で分からんでもないモデル。
結果はバニラLSTMと比較しているのだが、質疑で「バニラLSTMとの比較はフェアではないのではないか」とかなり激しめの口調で指摘する人が居るなどしていた。心が痛い。

 

Multi-Task Neural Network for Non-discrete Attribute Prediction in Knowledge Graphs

論文: Multi-Task Neural Network for Non-discrete Attribute Prediction in Knowledge Graphs

Graph Embeddingの新しいネットワークの提案。
ネットワークのRelationalとAtributeそれぞれ入出力にした1つのネットワークMULTI-TASK KNOWLEDGE GRAPH NEURAL NETWORK (MT-KGNN)。

f:id:vaaaaaanquish:20171119002056p:plain:w350

気持ちは分からなくもないが、何で左右に挟まれてたりするかは聞いてたが謎だった…

 

Movie Fill in the Blank with Adaptive Temporal Attention and Description Update.

論文: http://delivery.acm.org/10.1145/3140000/3132922/p1039-chen.pdf?ip=175.177.5.173&id=3132922&acc=OPEN&key=4D4702B0C3E38B35.4D4702B0C3E38B35.4D4702B0C3E38B35.6D218144511F3437&CFID=822711636&CFTOKEN=60985772&__acm__=1511019051_cba0bc5f027c502b908eb39acc33e0d2

動画から文章が出てほしいタスクを解くため、大きめのネットワークモデルを提案。
なんかまずは穴埋めからやっていた。

f:id:vaaaaaanquish:20171119002845p:plain:w350

モデルの図はデカいけど、やってる事はシンプルで多層LSTM挟んでConcatしてMLP。結果はめちゃくちゃ良いわけではないような感じだったがこれいかに。


 

- Conference(4日目) -

Efficient Learning

Sequence Modeling with Hierarchical Deep Generative Models with Dual Memory

論文: Sequence Modeling with Hierarchical Deep Generative Models with Dual Memory

discrete sequencesで似たテキストが欲しい時、RNN、CNNだとOverfitting、Lack diversityしやすい。Deep Generative Modelsだとpoor result。
長期、短期の記憶を考慮したVAE拡張のsequenceアーキテクチャを提案。

Dual Memoriesと呼んでいて、Encoding側にBroad Memory(B-HDGM)、Generative側にDeep Memory(D-HDGM)を組み合わせ接続したBi-BD-HDGM。
f:id:vaaaaaanquish:20171119181716p:plain:w350

デカいすぎてもうこれ分からんなという感じで、学習時間もVAE等に比べて遅くなるが、結果は良い感じの文章。
質疑では、良くない文章が生成される場合もありそうだとの指摘があったが全般的に良くなる(?)といった回答だった。

 

Active Learning for Large-Scale Entity Resolution

論文: Active Learning for Large-Scale Entity Resolution

IBM Researchの人。発表が丁寧だった。
「アイツだれだっけ…」を解決したい(Entity Resolution, ER)。TwitterIBMのEnterpriseデータをマッチングしたいけどデカいし全然マッチングしないので、両者から適切に検索しマッチングさせたい。
そこでactive learningベースで高いprecisionとrecallを出せるERLernを提案。

プロファイルデータのマッチングのルールを学習(名前ANDステータスOR…みたいな)。
そのルールを元にqueryを生成してマッチングユーザを探す。

f:id:vaaaaaanquish:20171119185337p:plain:w350

Twitterとのマッチングとか、入力になる特徴量を増やすのが難しいのでこういったアーキテクチャは使われそう。

 

Indexable Bayesian Personalized Ranking for Efficient Top-k Recommendation

論文: Indexable Bayesian Personalized Ranking for Efficient Top-k Recommendation

Top-K推薦検索のタスクでは速度と精度どちらも大事。
MFはitem行列デカい。exhaustive-searchはpracitialじゃない(力任せ探索は実践向きじゃない)。

item Vectorをhash tableかけてTop-K itemをだすLocality Sensitive Hashing(LSH)、Maximum Inner Product Search(MIPS)、Nearest Neighbar Search(NNS)、Maximum Cosine Similarity Search(MCSS)あたりあるけど内積検索と同等レベルではない。

Bayesian Probabilistic Matrix Factorizationを参考に、相対的なTop-Kを出せるIndexable Bayesian Personalized Ranking(Indexable BPR)を提案。
speedも精度もかなり上がってハッピーそう。

Bayesian Probabilistic Matrix Factorization: Salakhutdinov, Ruslan, and Andriy Mnih. "Bayesian probabilistic matrix factorization using Markov chain Monte Carlo." Proceedings of the 25th international conference on Machine learning. ACM, 2008.

 

Latency Reduction via Decision Tree Based Query Construction

論文: Latency Reduction via Decision Tree Based Query Construction

Facebook社の人の発表。
Linked Inのジョブレコメンド、ジョブサーチについて。

query生成にはTerm MatchとDecision TreeとLinear Modelが入ってるらしい。
検索では当たり前になりつつあるWANDオペレータとFLEXオペレータで繋げたqueryを生成。

f:id:vaaaaaanquish:20171119192306p:plain:w600

アーキテクチャAWS配置がプレゼン内に出てきたが、さほど複雑な使い方はしておらず、拡張子しやすさやDecision Treeによる確認、改修のしやすさを大事にしている段階とのこと。
というかFacebook社もAWSだったの何気に初めて知ったかも。

 

Adversarial IR

Sybil Defense in Crowdsourcing Platforms

論文: Sybil Defense in Crowdsourcing Platforms

クラウドソーシングって色んな所で活用できるけど、悪意のあるユーザがアカウントを大量に使って攻撃してきた場合に品質保証できないから、対策したい。
従業員の類似性を定量化するフレームワークで、いくつかの質問で悪意あるユーザをグルーピングしていくだけでなく、オンラインに検出する方法を提案。

普通にいくつかの質問の答えに重みを付けていたのでう〜んという感じ

 

HoloScope: Topology-and-Spike Aware Fraud Detection

論文: HoloScope
Github: GitHub - shenghua-liu/HoloScope: HoloScope: Topology-and-Spike Aware Fraud Detection

ネットの詐欺師の検出。大体悪意あるユーザは大量の偽アカウントやIP大量購入したりしてくるので、一般的な手法だと攻撃として目立ちにくい。

なんなら中国では、国民の53.1%がネットに触れていて、平均3時間/日≒8年分が1日に消費されていて世界2位で、年間で7,500億ドルが動いている。Methbotのfakeレビューやfake投稿は日に3000億件あるし、それらが5百万ドル稼いでると予測されているという話からスタート。規模〜。

手法的には簡易で、Graphトポロジーと時間軸におけるスパイクを利用してユーザを検出。そのユーザ分けに使う動的な重み付け、ユーザ評価を含んだ検出フレームワークを提案。

 

Building a Dossier on the Cheap: Integrating Distributed Personal Data Resources Under Cost Constraints

論文: Building a Dossier on the Cheap

TwitterとかNetflixとか色んなデータを合わせれば、特定個人の個人情報や機密情報って結構作れるから危ない。公開するデータの危なさを評価するフレームワークと、予測モデルみたいなのを作ったという話。

特段難しい事はしていないが、今後こういったタスクをやる時にまた読むかもくらい。

 

DeMalC: A Feature-rich Machine Learning Framework for Malicious Call Detection

論文: DeMalC

アリババ社の人の発表。
中国では2015年に590,000件電話詐欺が発生しているし、悪意ある電話本当損失になる。
かと言って、データは無いしあっても不均衡だし詐欺師は検出されないよう進化するし、ブラックリストでもなかなか対策できない。

なのでIPアドレスから端末UIDからありとあらゆるデータをマイニングして判別するようなDeMalCフレームワーク作りましたという内容。
精度が91%になっているけど、実際それで検出するのはなかなか…という感想。

 

Representation learning

An Attention-based Collaboration Framework for Multi-View Network Representation Learning

論文: An Attention-based Collaboration Framework for Multi-View Network Representation Learning

いろいろなネットワークの形から目的とする人について学習タスクでも、DeepWak, LINE, w2vみたく、ノード空間の埋め込みがやりたい。

複数のネットワークをそれぞれ学習させるのではなく、まとめて1つの入力にする。
f:id:vaaaaaanquish:20171119204118p:plain:w350

こういった複数ネットワークを入力にするモデルはA co-regularized multi-view spectral clustering model (CMSC)、 A multi-view non-negative matrix factorization model(MultiNMF)等があるがそれらともまたちょっと違っていて、ちょっとSOMっぽい(?)。

辞書共有などは特段しているわけではないがFuture work。

CMSC: Kumar, Abhishek, Piyush Rai, and Hal Daume. "Co-regularized multi-view spectral clustering." Advances in neural information processing systems. 2011.
MultiNMF: Liu, Jialu, et al. "Multi-view clustering via joint nonnegative matrix factorization." Proceedings of the 2013 SIAM International Conference on Data Mining. Society for Industrial and Applied Mathematics, 2013.

 

Representation Learning of Large-Scale Knowledge Graphs via Entity Feature Combinations

論文: Representation Learning of Large-Scale Knowledge Graphs via Entity Feature Combinations

Knowledge Graphに対する手法でTranslation-baseなモデルではTransE, TramsH, TransR, TransDがある。

TransE: h+r=t
TransH: h-w_{r}^{T}hw_{r}+r=t-w_{r}^{T}tw_{r}
TransR: hM_{r}+r=tM_{r}
TransD: h+h_{p}^{T}hr_{p}+r=t+t_{p}^{T}tr_{p}
となってる訳だけど、このバイアスになってる  r でentityとrelation featuresを同時に表現したい。
そこにプラスとマイナスのcombinationを入れてやってScoreでマージするCombinEを提案。SOTA。

TransE: Bordes, Antoine, et al. "Translating embeddings for modeling multi-relational data." Advances in neural information processing systems. 2013.
TransH: Wang, Zhen, et al. "Knowledge Graph Embedding by Translating on Hyperplanes." AAAI. 2014.
TransR: Y. Lin, Z. Liu, M. Sun, Y. Liu, and X. Zhu. Learning entity and relation embeddings for knowledge graph completion. In Proceedings of the Twenty-Ninth AAAI Conference on Artificial Intelligence, January 25-30, 2015, Austin, Texas, USA., pages 2181–2187, 2015.
TransD: Ji, Guoliang, et al. "Knowledge Graph Embedding via Dynamic Mapping Matrix." ACL (1). 2015.

  

Learning Edge Representations via Low-Rank Asymmetric Projections

論文: Learning Edge Representations via Low-Rank Asymmetric Projections

Googleの人。
Node Embeddingを2つつくって組み合わせDeep Walkの深いverを提案。

f:id:vaaaaaanquish:20171119212309p:plain:w350

コードが公開してあるから使ってくれよなって
GitHub - google/asymproj_edge_dnn


 

- おわりに -

総評は1日目のメモに結構書いたけどDeepやオレオレフレームワークな話とGraph Embeddingが多め。

最後もうしんどくなって来てメモも適当になっていた。
4日間人の話を聞くだけというのはしんどい。

シンガポールは雨と蒸し暑さがすごい!」と聞いていたのだけど、行き帰りに雨降ったのはは1日だけだったし、しんどくなる程の暑さでもなかった。


バスやタクシー、地下鉄だけでなく、貸し自転車や貸し電動キックボードが街中にあり、サラリーマンが朝電動キックボードで通勤していたりする姿があって先進的だった。

食べ物も悪くないし、100m歩けばマクドナルドがあるし、サブウェイ、スタバ、ユニクロ、無印などがあるので不自由しなさそう。物価は1.5倍くらいだけど、中華とか安いお店が沢山ある。

まあでも2度はいいかなシンガポール