tohokuaikiのチラシの裏

技術的ネタとか。

はてなスターAPIを使ってはてなブックマークコメントについた★の数を得る

はてなスター取得APIというのがある。

はてなスター取得 API - Hatena Developer Center

これで、はてなブックマークのコメントについた★の数を得ようとする。

例えば、https://anond.hatelabo.jp/20180518171957 に付けた私のブックマークの★の数はこの記事を執筆時点で91個。

このブックマークのURLは、http://b.hatena.ne.jp/entry/364742428/comment/tohokuaiki でカノニカルだと思われる。

なので、先ほどのAPIに従って、
http://b.hatena.ne.jp/entry/364742428/comment/tohokuaiki
をくっつけて
http://s.hatena.com/entry.json?uri=http%3A%2F%2Fb.hatena.ne.jp%2Fentry%2F364742428%2Fcomment%2Ftohokuaiki
で取得できるのかな?と思ったらだめだった。

正解は
http://b.hatena.ne.jp/tohokuaiki/20180525#bookmark-364742428
をくっつけて
http://s.hatena.com/entry.json?uri=http%3A%2F%2Fb.hatena.ne.jp%2Ftohokuaiki%2F20180525%23bookmark-364742428
なのである。なんだよ、このアンカー入りのURLでパーマリンク設定するのって…。

WordPressで特定の投稿タイプで特定の部分だけ自動整形のPタグを消す (wpautopを動作させない)

filterの削除・追加とショートコードを使う

custom_posttype投稿タイプの場合。

<?php
    /* 特定の投稿タイプはautopをしない */
    remove_filter('the_content','wpautop');
    add_filter('the_content' , function($content){
        $post_type = get_post_type();
        if ($post_type != 'custom_posttype'){
            $content = wpautop($content);
        }
        return $content;
    });
    add_shortcode('wpautop', function($attr, $content){
        $post_type = get_post_type();
        if ($post_type == 'custom_posttype'){
            $content = wpautop($content);
        }
        return $content;
    });

で、本文では、

この部分はautopが効く。

[wpautop]
この部分は、そのまま出る。
この部分は、そのまま出る。
[/wpautop]

という感じ。

ApacheのProxyをかます途中でBasic認証を入れてConfluenceにアクセスさせようとしたら失敗した件

よくある1サーバーでConfluenceを複数稼働させたい場合のリバースProxy設定ですね。

こんな感じ。
f:id:tohokuaiki:20180416182940p:plain

あるいは、iptablesで無駄にポートを開けたくない場合とか。

で、内輪向けのConfluenceなんで、Basic認証をかければゼロデイアタックとかも多少は防げるんじゃないかって思ってBasic認証つけたかったんです。

Basic認証は通るけど、ConfluenceでAuthエラー

余裕じゃん・・と思ってこんな感じでProxy設定にBasic認証の設定をかけたわけです。

<VirtualHost *:80>
    <Location />
        Order deny,allow
        Allow from all
        AuthType Basic
        AuthName "Authentication"
        AuthUserFile /etc/apache2/htpasswd
        Require valid-user
    </Location>
    ProxyTimeout 8000
    ProxyRequests Off
    ProxyPreserveHost On
    SetEnv force-proxy-request-1.0 1
    SetEnv proxy-nokeepalive 1
    ProxyPass / http://localhost:8090/ retry=1 acquire=3000 timeout=600 Keepalive=On
    ProxyPassReverse / http://localhost:8090/
</VirtualHost>

すると、こんなエラーが出る。
f:id:tohokuaiki:20180416183247p:plain

HTTPステータス 401 - Basic Authentication Failure - Reason : AUTHENTICATION_DENIED
type ステータスレポート
メッセージ Basic Authentication Failure - Reason : AUTHENTICATION_DENIED
説明 This request requires HTTP authentication.
Apache Tomcat/8.0.50

なんでTomcat側でエラーが出るんだ????

と思い、Tomcat使ってるのはConfluenceなのでこちら側を疑う。Confluenceで一旦ログイン後に、ApacheBasic認証をつけるとこのエラーは出ない。

ということは、Confluenceは

  1. COOKIEによる認証を試みる
  2. COOKIE認証に失敗した場合、Basic認証のAuthorization ヘッダから認証を試みる

となっているのではないか???

余計なことしてほしくないなぁ…と思い、そのAuthenticateをしているだろうプラグインを探す。
f:id:tohokuaiki:20180416182401p:plain

なんとなくこいつっぽいなーって思い、「無効」にしたが全然だめだった。

Confファイルを探すもなんか見つからない…。

ということで、Apache側で設定

だったら、Proxyする際にAuthenticationヘッダを送らなければいいんじゃんって思って、Apacheにmod_headersを導入

# a2enmod headers

した後に、apache.conf(debianなんでsites-enables内だけど)を書き換えて

    RequestHeader unset Authorization

を追加。

すると問題なくConfluence側がBasic認証をやめてくれた。

Confluence、REST and os_authTypeとか読むとquery stringsにos_authType=basicって入れないとBasic認証ヘッダをスルーしてくれそうなんだけどな。ま、いいや。。

PHPで制御文字を取り除く

ほかのプログラミング言語はたくさんあったのだけどPHPが無い。

Strip control codes and extended characters from a string - Rosetta Code

こんな感じかな。

<?php
function stripCtrlCode($string)
{
    $ctrl_code = array(
        "00", // NULl(ヌル)
        "01", // Start Of Heading(ヘッダ開始)
        "02", // Start of TeXt(テキスト開始)
        "03", // End of TeXt(テキスト終了)
        "04", // End Of Transmission(転送終了)
        "05", // ENQuiry(問合せ)
        "06", // ACKnowledge(肯定応答)
        "07", // BELl(ベル)
        "08", // Back Space(後退)
        /*    "09", // Horizontal Tabulation(水平タブ) */
        /*    "0A", // Line Feed(改行)*/
        "0B", // Vertical Tabulation(垂直タブ)
        "0C", // Form Feed(改ページ)
        /*    "0D", // Carriage Return(復帰)*/
        "0E", // Shift Out(シフトアウト)
        "0F", // Shift In(シフトイン)
        "10", // Data Link Escape(伝送制御拡張)
        "11", // Device Control 1(装置制御1)
        "12", // Device Control 2(装置制御2)
        "13", // Device Control 3(装置制御3)
        "14", // Device Control 4(装置制御4)
        "15", // Negative AcKnowledge(否定応答)
        "16", // SYNchronous idle(同期信号)
        "17", // End of Transmission Block(転送ブロック終了)
        "18", // CANcel(取消)
        "19", // End of Medium(媒体終端)
        "1A", // SUBstitute(置換)
        "1B", // ESCape(拡張)
        "1C", // File Separator(ファイル分離)
        "1D", // Group Separator(グループ分離)
        "1E", // Record Separator(レコード分離)
        "1F", // Unit Separator(ユニット分離)
        );

    $code_array = array();
    foreach ($ctrl_code as $code){
        $code_array[] = hex2bin($code);
    }

    return str_replace($code_array, "", $string);
}

って作った後に軽くググったら

制御文字を取り除く方法(改行コードは保持) - Qiita

<?php
return preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $string); 

ってあって、なんだか ( ´_ゝ`)って表情になった。

polyglotで英語の構文解析をする

日本語だと、MeCabとか入れておけば大体大丈夫で日本語での検索も捗るんだけど、英語って言われると…となってしまったので

lab.astamuse.co.jp

を参考にCentOS7で解析してみる。

インストール

とりあえず環境

$ more /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

実行

python-numpyが必要らしい。・・・んだけど、yum listしてみると、python27-numpyしかない。

しかし、んー、27ってついてるけど・・・・

[itoh@localhost ~]$ which python2.7
/bin/python2.7
[itoh@localhost ~]$ which python
/bin/python
[itoh@localhost ~]$ ls -l /bin/python
lrwxrwxrwx 1 root root 7 Jan 26 11:05 /bin/python -> python2
[itoh@localhost ~]$ ls -l /bin/python2
lrwxrwxrwx 1 root root 9 Jan 26 11:05 /bin/python2 -> python2.7

まぁ、大丈夫そうだろう。

pipもpip2.7がいいのかな~?と思ってインストールしたけど diff /bin/pip /bin/pip2.7 したら違いがなかった。

# yum install python27-numpy
# yum install -y libicu-devel
# yum install -y pip2.7
# yum install python-devel
# pip2.7 install --upgrade pip
# pip2.7 install polyglot

Installing collected packages: PyICU, pycld2, morfessor, numpy, wheel, polyglot
  Running setup.py install for PyICU ... done
  Running setup.py install for pycld2 ... done
  Running setup.py install for morfessor ... done
  Running setup.py install for polyglot ... done
Successfully installed PyICU-2.0.3 morfessor-2.0.4 numpy-1.14.2 polyglot-16.7.4 pycld2-0.31 wheel-0.30.0

となったので問題ないんだろう。

モデルファイルのインストール

$ polyglot download embeddings2.en pos2.en

で、自分のホームディレクトリにpolyglot_dataディレクトリを作成してこれがモデルファイルらしい。

で、何をしたかったかというと、

PDFから抜き出したテキストファイルを字句解析したかったのだ。

ところが、pdftotextで抜き出したテキストをpolyglotで解析しようとすると、

pycld2.error: input contains invalid UTF-8 around byte 5302 (of 39198)

UTF-8じゃないのが入ってる」と言われてしまう。

じゃあ、Python上でPDFを抜き出してそれを渡そうと思い、textractをインストールすることにした。

#pip2.7 install textract

     #include <pulse/pulseaudio.h>
    compilation terminated.
    error: command 'gcc' failed with exit status 1

と怒られた。

pulseaudio-libs-devel が必要なのかな?

# yum install pulseaudio-libs-devel

してから再度実行するとインストールできたっぽい。

しかし、結局同じ結果に。うーん。

制御コードを除く

ということで、制御コードを除く処理を加えてみた。 PHPで制御文字を取り除く - tohokuaikiのチラシの裏

したら、問題なくパースしてくれた。オッケー。

nginxから使う

php-fpmとnginxから使ってみると、nginxからみたpolyglot_dataが無いって言われるのでエラーになる。

エラーが出るところを解析する。自分の環境では、/usr/lib/python2.7/site-packages/polyglot/load.py を無理やり編集。

  if not path.isdir(p):
    if downloader.status(package_id) != downloader.INSTALLED:
      raise ValueError("This resource is available in the index "
                       "but not downloaded, yet. Try to run\n\n"
                       "polyglot download {}".format(package_id))

とあるのを

  if not path.isdir(p):
    if downloader.status(package_id) != downloader.INSTALLED:
      raise ValueError("This resource is available in the index "
                       "but not downloaded, yet. Try to run\n\n"
                       "polyglot download {}".path.join(p, os.listdir(p)[0]))

として、エラーを見る。

すると、/var/opt/rh/rh-nginx112/lib/nginx/polyglot_data/embeddings2/en が無いって言われてるっぽいんで、

# ln -s /home/tohokuaiki/polyglot_data /var/opt/rh/rh-nginx112/lib/nginx/

としてやった。もうほんと、とりあえずって感じ。そうすると動いた。