かれ4

かれこれ4個目のブログ

chsh: Macで標準以外のシェルを使おうとした時に出る non-standard shell

Macに最初から入っている下記のシェル以外をログインシェルにしようとしたら

$ chsh -s /usr/local/bin/bash
Changing shell for {USER}.
Password for {USER}:
chsh: /usr/local/bin/bash: non-standard shell

non-standard shell と言われ、変更出来ない。

/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

/etc/shellsに追加してあげれば良い。

$ cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

$ cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/usr/local/bin/bash

/etc/shellsの末尾に追加したいシェルのパスを追加すればOK

Parallels Desktop Pro 13 に 「リカバリからディスクイメージを作成できません。」と言われインストールできない場合の解決方法

Parallels Desktop Pro 13をHigh Sierra(10.13.2)にインストールし、 その上にさらにHigh Sierra(10.13.2)をインストールしようとすると

f:id:tottokug:20171230184523p:plain

のようなエラーが出ました。

新しいMacではリカバリ用のパーティションはなく、インターネット越しにイメージをダウンロードするようになっているからのようです。

というわけで、リカバリ用のパーティションではなく、インストールディスクを作成し、ParallelsにHigh Sierraをインストールしていきます。

もし、黒い画面を使いたくない人は、ページ最後の方にある”別の方法”というところまで読み飛ばしてください。

High Sierra のダウンロード

特に難しいことはありません。 App Storeからダウンロードします。 f:id:tottokug:20171230191457p:plain

イメージの作成

ダウンロードが終わったら、空のディスクイメージを作って、マウントしておきます。

$ hdiutil create -o /tmp/HighSierra.cdr -size 5200m -layout SPUD -fs HFS+J
created: /tmp/HighSierra.cdr.dmg
$ hdiutil attach /tmp/HighSierra.cdr.dmg -noverify -mountpoint /Volumes/installdisk
/dev/disk5              Apple_partition_scheme
/dev/disk5s1            Apple_partition_map
/dev/disk5s2            Apple_HFS                       /Volumes/installdisk

/Volumes/installdiskにマウントしてあります。 

ディスクへの書き込み

$ sudo /Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/installdisk
Ready to start.
To continue we need to erase the volume at /Volumes/installdisk.
If you wish to continue type (Y) then press return: Y
Erasing Disk: 0%... 10%... 20%... 30%...100%...
Copying installer files to disk...
Copy complete.
Making disk bootable...
Copying boot files...
Copy complete.
Done.

この段階で、 /tmp/HighSierra.cdr.dmgというファイルが出来ています。

インストール

もし、Parallels Desktopがすでに起動している状態であれば、

f:id:tottokug:20171230201249p:plain

このような通知が来ます。

あとはウィザードに従っていけば無事にParallels Desktop の環境にHigh Sierraがインストール出来ます。

f:id:tottokug:20171230201618p:plain


別の方法

あとで気づいたのですが、 App StoreからHigh Sierraをダウンロードしてあると、 f:id:tottokug:20171230201922p:plain

DVD/イメージからインストールを選ぶと次の画面で上記作業が自動的に行われます。

f:id:tottokug:20171230202118p:plain あとはそのままParallelsのウィザードに従えばインストール完了です。

Mac+Google日本語入力で入力ソースの切り替えのタイムラグによるストレスを解消する。

Macで入力ソースの切り替え時、切り替えが一瞬遅れ、 その一瞬のタイムラグが、英字を打っているはずなのに日本語になっていたり、 日本語を打っている気持ちなのに、英字が入力されていたりとかなりストレスを感じていました。

解決する方法として、2つの設定を

切り替えのショートカットの変更

f:id:tottokug:20171219123229p:plain

まず、「前の入力ソース」を使わずに、「入力メニューの次のソースを選択」を使うようにします。

入力ソースの統一

Google日本語入力なら、Google 日本語入力だけにすることで、だいぶ早くなります。 f:id:tottokug:20171219123352p:plain

ただし、「ABC」を削除しようとしても、ーボタンがグレーアウトされ、押せない状態になってしまっています。 f:id:tottokug:20171219130817p:plain

一旦、以下のように「日本語」を追加すると、グレーアウトが解除され、「ABC」削除できるようになります。 f:id:tottokug:20171219131006p:plain f:id:tottokug:20171219130835p:plain

この時の注意点は先にABCから削除するということ。 「ABC」を削除してから、「日本語」を削除すれば、無事にGoogle 日本語入力だけが残るようになります。

f:id:tottokug:20171219131221p:plain

Google 日本語入力だけになりました。

これで、入力ソース切替時のタイムラグもなくなり、ストレスもだいぶ減ります。

ページからコンテンツだけを抜き出すためのシンプルで簡単な方法。

はじめに

Scrapingをするときに、全てを手作業で取り出す。
1サイトであれば、それで良いでしょう。
しかし、100サイト、10,000サイト、1,000サイトといわゆる不特定サイトをスクレイピングする場合、 大変な作業量となります。

最初は楽しいのですが、だんだんと飽きてきますし、100サイトを超えてくると1サイトスクレイピングしようとしている間に、 前にやったサイトのマークアップが変わっていたり、苦痛を伴い始めます。

前置きが長くなりましたが、 クローラー/Webスクレイピング Advent Calendar 2017の9日目です。

世の中どこもかしこも、AI、AIと騒いでいるんだから、スクレイピングなんてAIにやらせとけばいいじゃない とも思いますが、

それは2014年のアドベントカレンダーでもう書いているので、 今日は逆にライトなやつ。簡単に実装できるやつを。

2014年の投稿はこちら blog.tottokug.com

コンテンツだけを抜き出したい

ブログやメディアのコンテンツなどからテキストを収集することはよくありますが、 その際に苦労するのが、コンテンツ以外のサイドバーや、ヘッダ、フッタのような部分を除外していくことです。 これらの部分には、複数のページで同一の内容が記載されていることも多く、扱いにくい単語の集合ができてしまうというのです。

これに対して、古くからアプローチ方法があります。 HTML::ExtractContentのような広く(?)知られたライブラリもあります。

詳しくはこれら記事を参照してもらうとして、、 blog.takuros.net Webページの本文抽出 (nakatani @ cybozu labs)

こんなようなことをもっと簡易に実装する方法を考えたいと思います。

今はHTMLのタグも増え、section/article/header/footerなんかもありますので、 当時よりはやりやすい可能性があります。

Evernote Web Clipper

今回やりたいことは 実装として、Evernote Web Clipperが近いです。 evernote.com

これは、記事を選択とするとある程度の精度で自動的に記事らしきところを選択してくれるという私もCmd+eをショートカットキーに登録しているくらい愛用しているブラウザのExtensionです。

実際に見ているページをクリップするときには下のような状態になり、自動的にコンテンツ部分が選択されています。

f:id:tottokug:20171209175854p:plain

そして、上下で選択範囲を広げたり、左右のカーソルキーで選択範囲を移動させたりできるスグレモノです。

このソースコードはブラウザのExtensionなので、簡単に見ることができますが、Licenseがよくわからないので、心の中にとどめておくことにします。

自作 簡易版コンテンツ抽出ロジック

この記事内では、HTMLはツリー構造のグラフと見ており、タグのことをノードと呼びますが、 HTML的に言うと、それはタグのことだと思ってください。

コンテンツ抽出を簡単に行うために、3つの指標を用いて各タグをスコアリングし、 スコアが一番大きかったノードをコンテンツとしています。

  1. HTMLを0として、タグの階層の深さタグの階層の深さ。(以下 d)
  2. ノードの配下に含まれる、テキスト量(文字数)。(以下 l)
  3. 子ノードの数。(以下 c)

例えば、とあるページのHTML構造がこのようなものだったとします。

ノードは[タグ名:含まれるテキストの文字数]という形で表記しています。

f:id:tottokug:20171209224551p:plain

このようなページがあったときに、下図の白い線、白い文字の部分を抜き出したいのです。

f:id:tottokug:20171209230235p:plain

このような構造になっているため、親のノードは子ノードよりも必ずテキスト量は多くなります。 なので、深さとテキスト量のバランスの良いところを導き出そうとしています。

動作原理

動作原理は、ざっくりというと、前述の3つの数字を使いスコアを出すことで、どのノードが一番スコアが高いのかを割り出し、 一番高いスコアをつけたところを、コンテンツとみなすようにしています。

そして、スコア(S)の付け方は

S=\sqrt[\frac{3}{4}]{l}\frac{d}{\sqrt{2c}}

このような数式で表します、 もし、同じテキスト量であった場合、深さが深くなるほど、Scoreは高くなります。
逆に、同じ深さだったとしたら、テキスト量が多いほうがScoreは高くなります。
また、自身に子供がたくさんいる場合は、Scoreは低くなります。
これらのバランスを適当に取ったものが、先程の数式です。 このスコアに対し、ノード名がSECTIONだったら、1.5倍とかやるとなお良いかと思います。

HTMLから始まり、各子ノードに対し、幅優先探索でScoreを比較しながらScoreが最高のノードを探せば なんとなくコンテンツっぽいところが抜き出せるようになっています。

最後に

この部分だけソース公開します。

チューニングして、やってみたらもっといい感じに取れるようになったとか、 あれば、PullRequestください。

Trimmer/Trimmer.java at master · tottokug/Trimmer · GitHub

HttpClientの部分とHtmlParserの部分はライセンスがうにゃむにゃなので、公開しませんが、 下記のような感じで使うと、

package com.tottokug;

import org.w3c.dom.Node;

public class App {
  // 引数はURLが来ます。
  public static void main(String[] args) {
    for (String u : args) {
      // HttpClientという、Htmlとってくる。
      String body = HttpClient.fetch(u);
      // 汚いHTMLきれいにしたりした後に、 org.w3c.dom.Nodeにして返す
      Node d = HtmlParser.parse(body);
      // 公開したTrimmer.javaが最強のノードを取り出す。
      Node n = Trimmer.trim(d);
      System.out.println("******************************************************************************");
      System.out.println("TAG = " + n.getNodeName());
      System.out.println("CONTENTS = " + n.getTextContent().replaceAll("([\n|\\s])+", "$1"));
    }
  }
}

適当にmainメソッド書いて実行すると、こんな感じで取得できます。

$ java com.tottokug.App  "https://qiita.com/advent-calendar/2017/crawler"

******************************************************************************
TAG = DIV
CONTENTS = Advent Calendar2017クローラー/Webスクレイピング Advent Calendar 2017 24 67 247 Subscribeクローラー/スクレイピングに関する話題ならなんでも誰でも OK な Advent Calendar です。
Webからどうやって情報を集めるか、いろいろな方法を共有しましょう。
例
言語別のクローラー/スクレイピング方法
ノンプログラムで使えるサービス
やっぱりExcel最高!!
情報収集に関する注意点(著作権法、岡崎図書館事件)
クローラー/スクレイピング本について
過去のやつ
2016年: https://qiita.com/advent-calendar/2016/crawler
2015年: http://qiita.com/advent-calendar/2015/crawler
2014年: http://qiita.com/advent-calendar/2014/crawler
Category: Web TechnologiesOwner: takurosTweetToot Calendar Sponsor PRSunMonTueWedThuFriSat26272829301 yyanoWgetしてスクレイピングする2 watameScrapyを使ったスクレイピング3 KaminoHirokiおまえもスクレイピングしてやろうかー!! ~PHP7でWebサイトのデータぶっこ抜いてMarkdown化したお話~4 KentFujiijsサイトをスクレイピングするなら、seleniumよりsplash!5 Azunyan1111【毎秒1万リクエスト!?】Go言語で始める爆速Webスクレイピング【Golang】6 wordijpPhantomJSを使うわけ7 paperlefthand日本学生支援機構奨学金の返済状況を取得8 numa08kotlin.js とか puppeteer とかOverwrite9 tottokug@githubノOverwrite10 rhoboroscrapydの話でも11 lldev2クローラー開発エッセンス12 mojibakeoPHP with Goutte で攻める実用的なクローラアプリケーション構成みたいな13 igaraHeadless Chromeで画像収集するお話14 Pctg-x8Rustの方と合わせでHeadless Chromeを使った記事を書きます15 miseyuなんか書きますよー16 massa142 2017年度版 tseを使って未投稿があるQiita Advent Calendarをさらす17 yamachaaaanなんか書く [1]クローリングハックの書評18 sakamossanスクレイピングしてRSSにする19 binnmti読んだ漫画を登録するサイトを作っているので、出版社各社をスクレイピングしています20 Notch44なんか拾ってきて解析かけます21 ys_tydy何か書きます!22 taptappunGoogle画像検索をハックして、大量の画像を簡単に集められるようにした話23 takuya_1stなんかかく24 jesushill何か書きます!25 yyano横串を縦串にしてみる()262728293012 / 1 yyanoWgetしてスクレイピングする12 / 2 watameScrapyを使ったスクレイピング12 / 3 KaminoHirokiおまえもスクレイピングしてやろうかー!! ~PHP7でWebサイトのデータぶっこ抜いてMarkdown化したお話~12 / 4 KentFujiijsサイトをスクレイピングするなら、seleniumよりsplash!12 / 5 Azunyan1111【毎秒1万リクエスト!?】Go言語で始める爆速Webスクレイピング【Golang】12 / 6 wordijpPhantomJSを使うわけ12 / 7 paperlefthand日本学生支援機構奨学金の返済状況を取得12 / 8 numa08kotlin.js とか puppeteer とかOverwrite12 / 9 tottokug@githubノOverwrite12 / 10 rhoboroscrapydの話でも12 / 11 lldev2クローラー開発エッセンス12 / 12 mojibakeoPHP with Goutte で攻める実用的なクローラアプリケーション構成みたいな12 / 13 igaraHeadless Chromeで画像収集するお話12 / 14 Pctg-x8Rustの方と合わせでHeadless Chromeを使った記事を書きます12 / 15 miseyuなんか書きますよー12 / 16 massa142 2017年度版 tseを使って未投稿があるQiita Advent Calendarをさらす12 / 17 yamachaaaanなんか書く [1]クローリングハックの書評12 / 18 sakamossanスクレイピングしてRSSにする12 / 19 binnmti読んだ漫画を登録するサイトを作っているので、出版社各社をスクレイピングしています12 / 20 Notch44なんか拾ってきて解析かけます12 / 21 ys_tydy何か書きます!12 / 22 taptappunGoogle画像検索をハックして、大量の画像を簡単に集められるようにした話12 / 23 takuya_1stなんかかく12 / 24 jesushill何か書きます!12 / 25 yyano横串を縦串にしてみる(仮)

こんな感じで抜け出せるので、遊んでみてください。

先程の数式だけだと、 ソースコードが貼ってあるページなんかだと、その部分だけが抜き出される可能性が高かったりとまだまだ課題はありますが、 一般的なニュースサイトやメディアだときれいに抜けたりするので、お試しください。

Fall Creators Updateが来る前に古いUbuntuをアンインストール

Fall Creators UpdateでLinux Subsystem for Windowsはストアからインストールできるようになります。

今まで使っていたUbuntuの環境がどうなるかわかりませんが、いったんなかったことにして、今日から心機一転ストアからインストールしたものに変えたいと思います。

そのために昔コマンドプロンプトbash と打ってインストールしたUbuntuをアンインストールしたいと思います。 時々なんかまっさらにしたいときってありますよね。そんな気分です。

アンインストール方法はシンプルで コマンドプロンプト

lxrun /uninstall /full

と打てば完全に削除されるようです。 lxrunのオプションは

>lxrun /help
LX サブシステムの管理操作を実行します

使用法:
    /install - サブシステムをインストールします
        オプションの引数:
            /y - ユーザーにサブシステム ユーザーの許可または作成を求めません
    /uninstall - サブシステムをアンインストールします
        オプションの引数:
            /full - 完全アンインストールを実行します
            /y - ユーザーに確認を求めません
    /setdefaultuser - bash を起動するサブシステム ユーザーを構成します。ユーザーが存在しない場合は作成されます。
        オプションの引数:
            username - ユーザー名を指定します
            /y - ユーザー名が指定された場合、パスワードの作成を求めません
    /update - サブシステムのパッケージのインデックスを更新します

もう使うことはないかもしれませんが installするときもこのコマンドからいけるようです。

Javaで鍵長256bitのAESを使う

Javaで鍵長256bit のAESを使おうとすると、

java.security.InvalidKeyException: Illegal key size or default parameters

こんなExceptionが出て、うまくいかない。

Java SE - Downloads | Oracle Technology Network | Oracle 上記ページから Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE 8 をダウンロードしてきて /{jreディレクトリ}/lib/securityの中に以下の2つのファイルを放り込む。 - local_policy.jar - US_export_policy.jar

簡単に出来ることではあるけれど、PaaSを使う場合にどうしたものかとなってしまう。 そんな時にリフレクションを使って、 以下のようなコードをAESを使う前に一度だけ実行しておけばOK。

try {
    Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
    field.setAccessible(true);

    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, false);
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException | IllegalArgumentException
                | IllegalAccessException ex) {
    ex.printStackTrace(System.err);
}