旅好きの気ままなお話

旅のこと映画、統計、会計、プログラミングなど、気の向くままに語ります

スクレイピングで文字化けを防ぐ方法

下記が使用するライブラリ(chardet)です。

pypi.org

chardetは文字コードを検出するライブラリで検出して取得したデータにdecodeをすると文字化けを解消できます。

sampleは日経のページです。

import urllib3
import chardet

url = "http://www.nikkei.com/"
http = urllib3.PoolManager()
r = http.request('GET', 'http://www.nikkei.com/')
r.data
guess = chardet.detect(r.data)

unicode_data = r.data.decode(guess['encoding'])

node.jsのバージョン管理をnvmでしてみる

環境はmacで行っています

node.jsのインストール

brew install node

nvmのインストール

nvmはrbenvのようなnode.jsのバージョン管理ツールです。

  • nvmをインストールする
    curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash

nvm公式

  • 設定を読み込む
    echo "source ~/.nvm/nvm.sh" >> ~/.bash_profile && source ~/.bash_profile
# nvmのバージョン確認
nvm --version

# install可能なnode.js確認
nvm ls-remote

# v10.5.0のインストール
nvm install v10.5.0

# インストールされたバージョンか確認
node -v

# npmのバージョンを確認
npm -v

バージョンを切り替える

# テストのため他のバージョンも読み込んでみる
$ nvm install v10.4.1

# バージョンを確かめる
$ node -v
v10.4.1

# バージョンをv10.5.0に変更する
$ nvm use v10.5.0

railsにvue-test-utilsを入れてみる

前提

  • webpackは使わない。
  • node.jsを入れている。
  • npmを使用出来る

※ webpackを使わない理由は対象をrails5だけに絞っていないからです。

必要なものをinstall

npm install --save-dev jest @vue/test-utils vue-jest babel-jest jest-serializer-vue vue-cli babel-preset-es2015

各設定ファイルを編集する

./package.json

{
  "name": "new_minkabu_pc",
  "version": "1.0.0",
  "description": "[![Build Status](https://travis-ci.com/minkabu/minkabu_pc.svg?token=A1r56DPr9tpa3qzgAWM1&branch=master)](https://travis-ci.com/minkabu/minkabu_pc) [![Maintainability](https://api.codeclimate.com/v1/badges/643434d3559be5ad03e3/maintainability)](https://codeclimate.com/repos/599d159c257148029c000746/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/643434d3559be5ad03e3/test_coverage)](https://codeclimate.com/repos/599d159c257148029c000746/test_coverage)",
  "main": "index.js",
  "directories": {
    "doc": "doc",
    "lib": "lib",
    "test": "test"
  },
  "scripts": {
    "unit": "jest --config test/unit/jest.conf.js --coverage",
    "test": "npm run unit"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/minkabu/minkabu_pc.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/minkabu/minkabu_pc/issues"
  },
  "homepage": "https://github.com/minkabu/minkabu_pc#readme",
  "devDependencies": {
    "@vue/test-utils": "^1.0.0-beta.19",
    "babel-jest": "^23.0.1",
    "babel-preset-es2015": "^6.24.1",
    "jest": "^23.1.0",
    "jest-serializer-vue": "^2.0.2",
    "vue": "^2.5.16",
    "vue-cli": "^2.9.6",
    "vue-jest": "^2.6.0"
  }
}

./test/unit/jest.conf.js

const path = require('path');

module.exports = {
  rootDir: path.resolve(__dirname, '../../'),
  moduleFileExtensions: [
    'js',
    'json',
    'vue'
  ],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  transform: {
    '^.+\\.js$': '<rootDir>/node_modules/babel-jest',
    '.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
  },
  testPathIgnorePatterns: [
    '<rootDir>/test/e2e'
  ],
  snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
  setupFiles: ['<rootDir>/test/unit/setup'],
  mapCoverage: true,
  coverageDirectory: '<rootDir>/test/unit/coverage',
  collectCoverageFrom: [
    'src/**/*.{js,vue}',
    '!src/main.js',
    '!src/router/index.js',
    '!**/node_modules/**'
  ]
};

./.babelrc

{
  "presets": ["es2015"]
}

sampleのテストファイルを用意する

./app/assets/javascripts/App.vue

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

./app/assets/javascripts/lib.js

export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

./app/assets/javascripts/tests/App.test.js

import * as lib from '../lib';
describe('Counter', () => {

  it('run test !!!!!!!!!', () => {
    expect(1).toBe(1)
  })

  it('hoge_test', () =>  {
    expect(lib.square(11)).toBe(121)
  })
})

流してみる

npm test もしくは jest で流れます。

npm testで流れる理由はpackage.jsonに記載しているからです。

vue.jsにeslintを設定した話(vscode使っています)

eslintとvue.js用のeslintプラグインをinstallする

今回はグローバルにインストールします。
npm i -g eslint eslint-plugin-vue
※上記はnpmですが、yarnでも大丈夫です。

vscodeに読み込ませるnode_moduleを設定

vscodeの"基本設定=>設定"のUser Settingsのjsonファイルを開いてください。 次に、自分の好きなパスのnode_moduleを設定してください。(今回はglobalのを読み込ませています。)

"eslint.nodePath": "/Users/[ユーザー名]/node_modules",
"eslint.enable": true,

.eslintrc.jsonを設置する

.eslintrcをプロジェクト直下に配置します。

.
├── .git
├── .gitignore
├── .eslintrc.json # <=ここに入れる 
├── Gemfile
├── Gemfile.lock
├── README.md
├── Rakefile
├── app
├── bin
├── config
├── config.ru
├── db
├── lib
├── log
├── node_modules
├── package.json
├── public
├── storage
├── test
├── tmp
├── vendor
└── yarn.lock

内容はとりあえず下記で大丈夫です。(カスタマイズは各々が行ってください)
.eslintrc.json

{
  "extends": [
    "eslint:recommended",
    "plugin:vue/recommended"
  ]
}

上記で設定は完了です。

補足

下記プラグインについての補足です。
https://github.com/vuejs/eslint-plugin-vue

それぞれ、vue style guidの規約でどこまで反映するかを表しています。
"plugin:vue/recommended"を設定しておけばとりあえず、全て反映してくれるので、特にこだわりがなければ"plugin:vue/recommended"でよいかと思います。

  • plugin:vue/base - Settings and rules to enable correct ESLint parsing
  • plugin:vue/essential - Above, plus rules to prevent errors or unintended behavior
  • plugin:vue/strongly-recommended - Above, plus rules to considerably improve code readability and/or dev experience
  • plugin:vue/recommended - Above, plus rules to enforce subjective community defaults to ensure consistency

wavesで自作コインを作る方法

waves platformでアカウントを作る

waves platformは各種仮想通貨の取引とウォレットです。

アカウント作成は下記urlから出来ます
https://wavesplatform.com

コイン作成費用

作成には1wavesかかるので1wavesをウォレットの中に入れておきましょう。

wavesを入れる

wavesの購入は現在の日本の取引所ではできません。 ですので、海外取引所のbinanceでwavesを購入しwavesウォレットに送金するか、日本の取引所でビットコインイーサリアムを購入し、wavesウォレットに送金し、wavesウォレット内の取引所でwavesを購入しましょう。

コインを作成する

下記画面より作成します。 f:id:tabilike:20180609164233p:plain

  • Name of your Asset
    自分の通貨の名称を入力します

  • Description
    自分の通貨の説明を入れます。これは後で変更することができません。

  • Total tokens
    自分の通貨の総発行量を決めます。

  • Reissuable
    後でトークンの追加発行が出来るかを設定します。

  • Decimals
    通貨の小数点の単位を設定出来ます。(最高は8です)

上記を全て入力するとGenerateを押下します。

押下してYour transaction is on the way!の文言が出れば成功です。

作られたコインはどうなる?

全発行量、自分のウォレットに保持されます。 ただ、保持されるだけなので、それだけでは価値は0円になります。

f:id:tabilike:20180609164350p:plain

コインを売りに出す

すぐに売りに出すことが出来ます。
発行したばかりなのと全量自分で持っているためチャートはでていません。。。 売る時の手数料はたったの0.03wavesなので手数料はほとんど気にすることなく売れます。

f:id:tabilike:20180609164303p:plain

まとめ

wavesでは気軽に10分ほどでコインを作成出来てとっても便利です。コインを作ったら人に送ってみたりしてコミュニティ内の通貨や社内通貨などにも使ってみたり出来そうです。何より発行手数料が1wavesですのでほとんどコストもかからず、利用できちゃいます。 というわけで、世の中の人がもっとwavesを使うようになったらおもしろくなるんじゃないかと思っています。

ちなみに

自分の作ったコインはjourneyという名称です。 欲しいという方は連絡をくれれば適当に配りたいと思います(笑)

vue.jsのデリミタ(delimiter)を変更する方法 sampleとしてjinja2を使用

フロントエンドのフレームワークと既存のテンプレートエンジンのデリミタ(delimiter)って被ってしまった。。。

ちなみにデリミタ(delimiter)とは、"フィールド区切り文字"のことです。 具体的には railsのerbの<% hogehoge %>とか jinja2の{{ hogehoge }}とか bladeの{{ hogehoge }}とかです。

erbだと<% %>の中にrubyのコードが書けます。 これをデリミタといいます。

さて、 vue.jsのデリミタも実はjinja2やbladeと同じく{{ }}なんです。

ですので、jinja2とvue.jsをそのまま使用するとコンフリクトが生じてしまうのです。

そこで、解決策としてデリミタを変更するという方法があります。(ここからはjinja2をsampleに書きます。)

jinja2のデリミタかvueのデリミタどちらかを変更すればよいのです。

jinja2のデリミタを変更するのはフレームワークに依存してしまうケースがあるので、完結に変更するにはvue.jsがおすすめです。

下記コードは{{ }}から[[ ]]にデリミタを変更しています。

hoge.js

new Vue({
  el: '.js-component01',
  delimiters: ['[[', ']]'], //ここにデリミタの変更を記述
  data: {
    text: 'hogehoge'
  }
});

python側ではbottleを使用しています。

run.py

from bottle import route, run
from bottle import TEMPLATE_PATH, jinja2_template as template

@route('/top')
def main():
    return template('top', hoge = "pythonの結果")

run(host='localhost', port=8080, debug=True, reloader=True)

top.html

<div class="js-component01">
  <p>[[hoge]]</p>
</div>
<div>
  {{hoge}}
</div>

テンプレートでは同じ変数hogeでもvueで設定したものとpythonで設定したもので、異なる値が表示されるようになっています。

ちなみにデリミタを変更せずに行うと、python側が優先されます。

rubyでマークルツリーを書いてみた

ブロックチェーンの勉強をしていてマークルツリーがどんなものかをrubyで書いてみました。 (まだ、勉強したてなので間違えているかもしれません、その際はご教授ください)

マークルツリーについてはわかりやすい記事があるので他のを参考にするといいです。

以下がソースです。
make_merkle_tree(data_list)のdata_listは配列です。

ソース

require "digest/md5"

def make_merkle_tree(data_list)
  loop do
    hash_list = data_list.map {|data| Digest::MD5.hexdigest(data) }
    hash_set_list = make_set(hash_list)
    data_list = integrate_hash(hash_set_list)
    break if data_list.size == 1
  end
  data_list.first
end

def make_set(hash_list)
  hash_list.each_slice(2).to_a
end

def integrate_hash(hash_set_list)
  hash_set_list.inject([]) do |integrated_data_list, hash_set|
    hash_set << hash_set.first if hash_set.size < 2
    integrated_data_list << "#{hash_set[0]}#{hash_set[1]}"
  end
end

実際に動かしてみました。
data_listのなかがビットコインでいうトランザクション(取引)データです。
取引データが
["a","b","c","d","e"] とあったら。
全ての取引は
"dfbd34a5b6634d7ccd0aa26a4dec2eccfb8a3688c2f3cc709e72181bd8074cc3"
で全て表現できているということを表しています。

もし、["a","b","c","d","e"]が ["a","b","c","f","e"]のように書換えられてしまうと、 異なるハッシュ値を返してしまいます。

これはどういうことかというと、ビットコインの生成するための計算ではタイムスタンプやナンスなどとこのトランザクションの結果をまとめてハッシュ化しており、取引データが改竄されると、計算が合わなくなり、改竄が発覚します。

なので、ブロックチェーンのデータの改竄は難しくなっているのです。 この他にも、改竄対策にはデータのコンセンサスの問題などもあるのですが、今回はマークルツリーの実装の話なので、置いておきます。

実行

[9] pry(main)> make_merkle_tree(["a"])
=> "0cc175b9c0f1b6a831c399e2697726610cc175b9c0f1b6a831c399e269772661"
[10] pry(main)> make_merkle_tree(["a","b"])
=> "0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f"
[11] pry(main)> make_merkle_tree(["a","b","c","d"])
=> "3bc22fb7aaebe9c8c5d7de312b876bb81ee715fcc373a83611d163d9d4ea02a3"
[12] pry(main)> make_merkle_tree(["a","b","c","d","e"])
=> "dfbd34a5b6634d7ccd0aa26a4dec2eccfb8a3688c2f3cc709e72181bd8074cc3"