SeleniumとPhantomJSの環境構築

Docker上にUbuntuの構築

$ docker pull ubuntu:16.04
$ docker run -it ubuntu:16.04

Python3とSeleniumのインストール

 apt-get update
 apt-get install -y python3 python3-pip
 pip3 install selenium
 pip3 install beautifulsoup4

PhantomJSのインストール

apt-get install -y wget libfontconfig
mkdir -p /home/root/src && cd $_
wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
tar jxvf phantomjs-2.1.1-linux-x86_64.tar.bz2
cd phantomjs-2.1.1-linux-x86_64/bin/
cp phantomjs /usr/local/bin/

日本語フォントが表示されるようにする

apt-get install -y fonts-migmix
cat <<EOF > /etc/fonts/local.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
	<match target="pattern">
		<test qual="any" name="family">
			<string>serif</string>
		</test>
		<edit name="family" mode="assign" binding="strong">
			<string>MigMix 2P</string>
		</edit>
	</match>
</fontconfig>
EOF

Dockerをコミットしておく

exit
docker ps -a
docker commit (コンテナID) ubuntu-phantomjs

コンテナ起動

$ docker run -it -v $HOME(ホストのパス):$HOME(コンテナのパス) \
> -e LANG=ja_JP.UTF-8 \
> -e PYTHONIOENCODING=utf_8 \
> ubuntu-phantomjs /bin/bash

動作確認

seleniumu-capture.py

from selenium import webdriver

url = "http://www.aozora.gr.jp/cards/000081/files/46268_23911.html"

#PhantomJSのドライバを得る
browser = webdriver.PhantomJS()
#暗黙的な待機を最大3秒行う
browser.implicitly_wait(3)
#URLを読み込む
browser.get(url)
#画面をキャプチャしてファイルに保存
browser.save_screenshot("Website.png")
#ブラウザを終了
browser.quit()
cd $HOME(コンテナのパス)
python3 selenium-capture.py 

実行結果

Website.pngが出来上がる

pythonとかdocker

作業の覚書

python

  • emacsでpythonが自動補完できるように設定
$ sudo easy_install pip
$ sudo pip install virtualenv
    • init.el追記
(require 'python-mode)
(setq auto-mode-alist (cons '("\\.py\\'" . python-mode) auto-mode-alist))

(require 'jedi)
(add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:complete-on-dot t)
  • macにdockerをインストール
  • dockerにPython3とanacondaの環境を整備
$ docker pull continuumio/miniconda3
$ docker run -i -t continuumio/miniconda3 /bin/bash
$ docker ps -a
$ docker commit ef08836ef1b2 mlearn:init
$ docker images
$ docker run -i -t mlearn:init /bin/bash
$ docker run -i -t -v {ホストOSのカレントディレクトリ}:/home mlearn:init /bin/bash

サーバーサイド(node.js)

  • Expressのhelmetモジュールの動作確認

Expressのセキュリティ設定

helmetモジュールでHTTPに於ける脆弱性となるヘッダを取り除く

対応前の確認

  • プロジェクトの生成とExpressに必要なnpmパッケージのインストール
$ express express-helmet
$ cd express-helmet/
$ npm install
  • サーバーの起動
$ DEBUG=express-hlmet:* PORT=8000 npm start

デベロッパーツール→Network→再読込み→localhost選択→Headersタブを見ると、
X-Powered-By:Expressと書かれており、このWebサービスがExpressで開発されていることが分かってしまう。
もしExpressに脆弱性があるとわかったときに攻撃対象にされる危険性がある。
このためX-Powered-Byというヘッダは送信しないほうが安全。

helmetのインストール

$ npm install helmet --save

app.jsの修正

  • モジュールの読み込みとappオブジェクトのuse関数でhelmetを使うようにする
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
+var helmet = require('helmet');

var index = require('./routes/index');
+var users = require('./routes/users');

対応後の確認

  • サーバー起動
$ DEBUG=express-hlmet:* PORT=8000 npm start

デベロッパーツール→Network→再読込み→localhost選択→Headersタブ
X-Powered-By:Expressが消える

まとめ

フレームワークによって自分で実装しなくて済む

node.jsのフレームワークを導入する

ジェネレーターのインストール&必要なファイルの作成

$ npm install -g express-generator
/home/ubuntu/.nodebrew/node/v4.7.0/bin/express -> /home/ubuntu/.nodebrew/node/v4.7.0/lib/node_modules/express-generator/bin/express-cli.js
+ express-generator@4.15.5
added 6 packages in 0.99s
$ cd workspace/$ express express-study

  warning: the default view engine will not be jade in future releases
  warning: use `--view=jade' or `--help' for additional options


   create : express-study
   create : express-study/package.json
   create : express-study/app.js
   create : express-study/public
   create : express-study/routes
   create : express-study/routes/index.js
   create : express-study/routes/users.js
   create : express-study/views
   create : express-study/views/index.jade
   create : express-study/views/layout.jade
   create : express-study/views/error.jade
   create : express-study/bin
   create : express-study/bin/www
   create : express-study/public/javascripts
   create : express-study/public/images
   create : express-study/public/stylesheets
   create : express-study/public/stylesheets/style.css

   install dependencies:
     $ cd express-study && npm install

   run the app:
     $ DEBUG=express-study:* npm start

npmモジュールのインストール

cd express-study
npm install

起動

$ DEBUG=express-study:* PORT=8000 npm start

> express-study@0.0.0 start /home/ubuntu/workspace/express-study
> node ./bin/www

  express-study:server Listening on port 8000 +0ms
  • 「npm スクリプト名」 というコマンドでpackage.jsonで設定されたコマンドが実行される。package.jsonにはこんな箇所がある。
"scripts": {
    "start": "node ./bin/www"
  },

アクセスしてみると雛形ページが表示される

http://localhost:8000/

f:id:sattamassagana:20180204201655p:plain

試しにExpressのdebugモジュールの機能を使ってみる

  • app.jsの先頭に追加する
'use strict';

const debug = require('debug');//debugモジュールを読み込む
const debugInfo = debug('app:info');//module:infoという設定のロガーdebugInfoを用意
setInterval(() => {//1000msごとに関数を実行する
    debugInfo('some information');
}, 1000);

const debugError = debug('app:error');//別の設定のロガーdebugErrorを用意
setInterval(() => {
    debugError('error!');
}, 2000);
  • 実行(複数ログ出力するにはカンマで繋げてコマンドを実行する)
$ DEBUG=express-study:*,app:* PORT=8000 npm start

> express-study@0.0.0 start /home/ubuntu/workspace/express-study
> node ./bin/www

  express-study:server Listening on port 8000 +0ms
  app:info some information +907ms
  app:error error! +997ms
  app:info some information +9ms
  app:info some information +1s
  app:error error! +990ms
  app:info some information +13ms
  app:info some information +1s
  app:error error! +987ms
  app:info some information +14ms
  app:info some information +1s
  app:error error! +985ms
  app:info some information +17ms
  app:info some information +1s
  app:error error! +982ms
  app:info some information +23ms
  app:info some information +1s
  app:error error! +978ms
  app:info some information +25ms

Emacsでタグジャンプできるようにする

インストールなど

  • GLOBALというのが必要
  • GLOBALの対応言語を増やすのにPygmentsというのが必要
  • macなら以下で済む
$ brew install global --with-exuberant-ctags --with-pygments
$ export GTAGSLABEL=pygments

任意の場所でgtag実行

/usr/local/var/www/htdocs $ gtags

確認

  • 例えばcreateDatの定義箇所
/usr/local/var/www/htdocs $ global -ax -t createDat
createDat	/usr/local/var/www/htdocs/typing.js	43
  • 例えばcreateDatを使っている箇所
/usr/local/var/www/htdocs $ global -ax -r createDat
createDat         104 /usr/local/var/www/htdocs/typing.js     createDat();

できてるようだ

Emacs側

  • helm-gtagsパッケージ のインストール
  • init.elに追記
;;Emacsからgtagsを使えるようにする
;; customize
(custom-set-variables
 '(helm-gtags-path-style 'relative)
 '(helm-gtags-ignore-case t)
 '(helm-gtags-auto-update t))
;; key bindings
(eval-after-load "helm-gtags"
  '(progn
     (define-key helm-gtags-mode-map (kbd "M-t") 'helm-gtags-find-tag)
     (define-key helm-gtags-mode-map (kbd "M-r") 'helm-gtags-find-rtag)
     (define-key helm-gtags-mode-map (kbd "M-s") 'helm-gtags-find-symbol)
     (define-key helm-gtags-mode-map (kbd "C-c <") 'helm-gtags-previous-history)
     (define-key helm-gtags-mode-map (kbd "C-c >") 'helm-gtags-next-history)
     (define-key helm-gtags-mode-map (kbd "M-,") 'helm-gtags-pop-stack)))

使う時

  • ファイルを開く
  • M-x helm-gtags-modeする
  • 関数などにカーソルを合わせる
  • M-tやM-rで
Find Reference: (default "なんとかかんとか")

と聞かれるのでEnterするとジャンプする

iTuenes 12.7にアップグレードしたら起動しなくなったのでiTunes12.6にダウングレードして起動できるようにする

環境

  • MacBook Pro(13-inch, 2017)
  • iTunesライブラリはNAS(I-O DATA HDL2-AAシリーズ)で管理

現象

アップデートの表示が出ていたのでアップデートしたところ、iTunesがフリーズして一向に起動しない。
iTunes再起動やOS再起動しても解決しないのでiTunes12.6にダウングレードする。

iTunes12.6にダウングレードする方法

現在のiTunes(12.7)を一旦削除してiTunes12.6をインストールしたいところだが、iTunesはゴミ箱に入れようとしても「“iTunes.app”はmacOSで必要なため、変更または削除できません。」とメッセージが表示される。
f:id:sattamassagana:20170923113100p:plain
このため、ターミナルからiTunesを削除する必要がある。

  • ターミナルを起動する。
  • Aplicationsフォルダに移動するため、ターミナルに次のように入力し、return
cd /Applications/
  • 次のコマンドを入力し、iTunesを削除する。
sudo rm -rf iTunes.app/


残りはFinderからの作業になる。

  • Finderから ~/Music/iTunes/ フォルダに移動し、“iTunes Library.itl”というファイルをデスクトップか、わかり易い場所にコピーしておく(バックアップのため)。
  • “Previous iTunes Libraries”フォルダの中から最も最近の日付が書かれたiTunesライブラリファイルを見つける。iTunesを12.7にアップグレードする前なので例えば“iTunes Library 2017-09-12.itl”などという名前になっているはず。
  • 見つけた“iTunes Library 2017-09-12.itl”を~/Music/iTunes/ フォルダにコピーする。
  • 次に“iTunes Library 2017-09-12.itl”を“iTunes Library.itl”に「名前を変更」する。
  • アップルサポートにアクセスし、“iTunes 12.6.2”をダウンロード、インストールする。

アップル - サポート - ダウンロード

  • これでiTunes12.6にダウングレードし起動できるようになった。

JUnitチュートリアル

アジャイルソフトウェア開発の奥義 第2版

アジャイルソフトウェア開発の奥義 第2版

  • 作者: ロバート・C・マーチン,Robert C. Martin,瀬谷啓介
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2008/07/01
  • メディア: 単行本
  • 購入: 18人 クリック: 586回
  • この商品を含むブログ (71件) を見る

内容

JUnitとは何なのか、JUnitでユニットテストの実行をしてみる。

環境

JDK8
Eclipse(Neon)
macOS

プロジェクトの準備

ファイル
→新規
→Javaプロジェクト
→junit-tutorialを作成

通常はテストコードとプロダクションコードは別のソースフォルダに配置する。
このため、テストコードを作成するためのソースフォルダ「test」を作成する。

f:id:sattamassagana:20170225221829p:plain

プロジェクトのコンテキストメニューから
→ビルドパス
→新規ソースフォルダを選択
→フォルダ名を「test」にする

テスト対象クラスの作成

■テストクラス
テストプログラムを記述するクラス
■テスト対象クラス
テストされるクラス
下記のようなクラスを作成する。これがテスト対象クラス。
Calculator.java

package junit.tutorial;

public class Calculator {
public int multiply(int x, int y){
	return x * y;
}
public int divide(int x, int y){
	return x / y;
			}
}

テストクラスの作成

パッケージエクスプローラーで右クリック
→新規
→JUit
→JUnit Test Case
ソースフォルダをjunit-tutorial/testにする
テスト元クラスをjunit.tutorial.Calculatorにする

下記のようなクラスが作成される。これがテストクラス。
CalculatorTest.java

package junit.tutorial;

import static org.junit.Assert.*;

import org.junit.Test;

public class CalculatorTest {

	@Test
	public void test() {
		fail("Not yet implemented");
	}

}

テストの実行

この段階ではまだテストが実装されていないが、一旦実行してみる。
CalculatorTestのコンテキストメニューから実行-JUnitテストを選択する。
f:id:sattamassagana:20170226205003p:plain
1件のテストを実行し、1件が失敗したことを確認できる。

乗算メソッドのテストコードを書く

テストメソッドを作成するときは、はじめにそのテストで何を検証したいのかを検証する。
ここでは「テスト対象クラスのmultiplyメソッドで乗算結果が取得できる」ことを検証する。

  • JUnitのルールに注意する
    • テストクラスはpublicクラスとする
    • テストメソッドはorg.junit.Testアノテーションを付与したpublicメソッドとする
    • テストメソッドは戻り値がvoidであり、引数を持たない
    • テストメソッドのthrows句は自由に定義できる
    • テストクラスにはいくつでもテストメソッドを定義できる
    • テストメソッド名は、そのテストの概要がわかる名前にする

まずは「3と4を引数としてmultiplyメソッドを実行し、取得された値が12である」ことを検証する。

CalculatorTest.java

package junit.tutorial;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;

public class CalculatorTest {

//	@Test
//	public void test() {
//		fail("Not yet implemented");
//	}

	// テストコードの追加
	@Test
	public void multiplyTest() {
		Calculator calc = new Calculator();
		int expected = 12;
		int actual = calc.multiply(3, 4);
		//JUnitではorg.junit.AssertクラスのassertThatメソッドを使って
		//「あるテスト対象クラスのメソッドを実行したときに、戻り値などで取得した
		//実際の値と、期待される値が一致する/しないはずである」という宣言で構成される(アサーション)
               //assertThatはAssertクラスに定義sれたstaticメソッド。1つめの引数が実測値、2つめの引数が期待値。
		assertThat(actual, is(expected));
	}

}

実行する
f:id:sattamassagana:20170226212110p:plain
実行1、エラー0、失敗0となった。
また、グリーンバーになっている。
これで「3と4を引数としてmultiplyメソッドを実行し、取得された値が12である」ことが確認できた。

2つめのテストを追加する

テストが失敗した場合の動作を確認してみる。
CalculatorTest.java

package junit.tutorial;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;

public class CalculatorTest {
	@Test
	public void multiplyTest() {
		Calculator calc = new Calculator();
		int expected = 12;
		int actual = calc.multiply(3, 4);
		assertThat(actual, is(expected));
	}
  //テストコード追加その2
	@Test
	public void multiplyTest5x7equals35() {
		Calculator calc = new Calculator();
		int expected = 12;//35が正しい期待値
		int actual = calc.multiply(5, 7);
		assertThat(actual, is(expected));
	}

}

これを実行するとテストが失敗する。
AssertionErrorに「期待値が<12>なのに<35>でした。」とのメッセージ。
f:id:sattamassagana:20170304174806p:plain
Failure Traceにはテスト失敗時のスタックトレースが表示されており、行を
ダブルクリックすることでそのクラスのソース箇所に移動できる。
今回はテストコードの方に不具合があるため、これを修正して再度実行する。
CalculatorTest.java

package junit.tutorial;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;

public class CalculatorTest {
	@Test
	public void multiplyTest() {
		Calculator calc = new Calculator();
		int expected = 12;
		int actual = calc.multiply(3, 4);
		assertThat(actual, is(expected));
	}

	@Test
	public void multiplyTest5x7equals35() {
		Calculator calc = new Calculator();
		int expected = 35;//テストコードを修正
		int actual = calc.multiply(5, 7);
		assertThat(actual, is(expected));
	}

}

f:id:sattamassagana:20170304173950p:plain
2つともグリーン。

windows10 + emacs + oracleでの文字化け

環境

emacsインストール済み
windows10インストール済み
oracle12cインストール済み

問題

emacsからM-x sql-oracleしてsql-plusをバッファに表示させると文字化けしている

対策

oracleのキャラクタセットを確認
sql-plusから
select * from NLS_DATABASE_PARAMETERS;
NLS_CHARACTERSET を確認するとJA16SJISTILDEとなっていた。これはoracleのインストール時に決めるもので後から変えられないらしい。
この場合は環境変数NLS_LANGにJAPANESE_JAPAN.JA16SJISTILDEを設定する必要がある。
システム環境変数の編集→詳細設定タブ→環境変数→システム環境変数で新規→変数名にNLS_LANG、変数値にJAPANESE_JAPAN.JA16SJISTILDE
を設定しOK→OK→OK→windows再起動

結果

emacsからM-x sql-oracle、文字化けしていない。しかし、今度はコマンドプロンプトの方が文字化けしている。

断念

・コマンドプロンプトからsqlplus使わない

JVMのソースコードを読むための準備

JDK/JRE/JVM

JVMとは

Javaバイトコードとして定義された命令セットを実行するスタック型の仮想マシン(Java Virtual Machine) 。JRE(Java Runtime Environment)に入っている。

JREとは

Java実行環境。JVMやAPIが入っている。

JDKとは

Java開発キット(Java Development Kit)。JREが入っている。

具体的に何が入っているのか確かめる

ソースコードを取得する

OpenJDKはMercurialというソースコード管理システムで管理されている。Mercurialをインストールする(ubuntu)

パッケージのダウンロード

sudo apt-get install mercurial

ソースコードを取得するにはターミナルから下記を実行(jdk8)

hg clone http://hg.openjdk.java.net/jdk8/jdk8

するとjdk8というフォルダがhome以下にできる

この時点でフォルダの中を見てみると、makefileや.cファイルの存在を確認できる。まだ.javaファイルはない。
ターミナルからjdk8の中に入り、get_source.shを実行するとソースコードを全て取得できる。

JavaScript スタイルシートを操作する②

<link rel="stylesheet" type="text/css" href="style.css"/>
<script type="text/javascript">
 //className.html
 //外部スタイルシートで定義されたスタイル(スタイルクラス)にアクセスするには
 //classNameプロバティを使用する。
 function changeStyle(elem, clazz){
     //指定要素に対して、スタイルクラスclazzを適用する
     elem.className = clazz;
 }
</script>

<div onmouseover="changeStyle(this, 'highlight')"
     onmouseout="changeStyle(this, 'normal')">
    マウスを乗せると色が変わります。</div>
/*style.css*/
.Highlight{
    Background-color: Pink;
}
.normal{
    Background-color: White;
}

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

JavaScript スタイルシートの操作①

<script type="text/javascript">
 //JavaScriptからスタイルシートを操作①
 
 //インラインスタイルにアクセスする。<div>タグにマウスポインタを載せたタイミングで背景色をピンクに、外したタイミングで下の白色に切り替える。
 function changeStyle(elem, color){
     elem.style.backgroundColor = color;
 }
</script>

<div onmouseover="changeStyle(this, 'Pink')"
     onmouseout="changeStyle(this, 'White')">
    マウスを乗せると色が変わります。</div>

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

JavaScript 新規にノードを追加する

<script type="text/javascript">
 //新規にノードを追加する
 
 //フォームに入力した内容を下にページ下部に対応するリンクを追加する
 //追加ボタンをクリックしたタイミングで実行されるadd関数
 function add(f){
     //<a>タグを生成
     var anchor = document.createElement('a');
     //<a>タグのhref属性を設定
     anchor.href = f.url.value;
     //テキストノードを生成し、<a>タグの直下に追加
     var name = document.createTextNode(f.name.value);
     anchor.appendChild(name);
     //<br>タグを生成
     var br = document.createElement('br');
     //<div id="list">を取得
     var list = document.getElementById('list');
     //<div>タグ直下に<a>,<br>タグの順番で追加
     list.appendChild(anchor);
     list.appendChild(br);
 }
</script>

<form>
    <label>サイト名:<br />
        <input type="text" name="name" size="30"/></label><br />
        <label>URL:<br />
            <input type="text" name="url" size="50"/></label><br />
            <input type="button" value="追加" onclick="add(this.form)"/>
</form>
<div id="list"></div>

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

JavaScript ウィンドウサイズやスクロール位置を操作する

<html>
    <head>
        <body>
<!-- moveByメソッド、resizeByメソッドはChromeでは未対応 -->
 <input type="button" value="scrollTo" onclick="window.scrollTo(0,200)"/>
 <input type="button" value="moveBy" onclick="moveBy(100,100)"/>
 <input type="button" value="resizeBy" onclick="window.resizeBy(50,50)"/>
 1<br>
 1<br>
 1<br>
 1<br>
 1<br>
 1<br>
 1<br>
 1 <br>
 1<br>
 1<br>
 
        </body>
    </head>
</html>

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

JavaScript タイマー機能の実装

<script>
 //タイマー機能の実装
 //タイマーIDを格納するためのグローバル変数
 var timer;
 //ページロード時にタイマー処理を登録
 window.onload = function(){
     timer = window.setInterval(
         //現在の時刻を<div id='result'>タグに表示(1000ミリ秒ごとに更新)
         function(){
             var dat = new Date();
             document.getElementById('result').innerHTML = dat.toLocaleTimeString();
         },1000
     );
 };
</script>

<!-- ボタンクリック時にタイマー処理を中止 -->
<input type="button" value="タイマー停止" onclick="clearInterval(timer)"/>
<div id="result"></div>

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで