OmniAICreator/Qiita-1.07M huggingface dataset:
asyncな世界のawait

### 経緯
```
 B2008: ajaxの非同期な通信によりjavascriptへの転換が始まる。c,java系の冗長な命名からの脱却も後押し。
 2008 : jQueryがxhrを上手くラッピングする。
 2009 : node.jsがサーバサイドで良好なパフォーマンスが出ることがわかる。
 2010 : コールバック地獄が判明、脱却を模索。
--- yieldなどのプロトタイプ的解決策が出てくるが、汎化しない。 ---
 2014 : thenableな世界が一つの解決策であることがわかる。モジュールがthen化しはじめる。
 2016 : シーケンシャルになったが、ネスト地獄が判明。promiseコードの冗長化も問題になる。
 2017 : asyncな世界であることを条件に、記述を省略できるawaitが実装される。
```
### 結局
記述の簡略化が最大の効能のようで、

```js
let a=(async function(root){
 /*on the async*/
 let texta =await fetch('https://gnjo.github.io/use.js').then(d=>d.text())
 let textb =await fetch('https://gnjo.github.io/use.css').then(d=>d.text())
 let textc =await fetch('https://gnjo.github.io/index.html').then(d=>d.text())
 return {js:texta,css:textb,html:textc}
})(this)
;
console.log(a); //promise! not returner
a.then(d=>{
/*outer is then*/
console.log(d) //{js:texta,css:textb,html:textc}
});

```
直感的に考えてしまう「aに最終値が入る」のとは、違う。
asyncな世界でネストが深くなるのが最も無意味だろう。yieldな世界はまだ。
【css】アニメーションする円形レーダー

位置情報を地図上に表示する際に作成したものを記載します！

<p data-height="600" data-theme-id="0" data-slug-hash="OvmjWV" data-default-tab="css,result" data-user="sjnya" data-embed-version="2" data-pen-title="OvmjWV" class="codepen">See the Pen <a href="https://codepen.io/sjnya/pen/OvmjWV/">OvmjWV</a> by sjnya (<a href="https://codepen.io/sjnya">@sjnya</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


```css
.point {
  width: 40px;
  height: 40px;
  background: rgba(25, 118, 210, 0.4);
  border-radius: 50%;
  animation: blink 1s ease-in-out infinite none;
}
@keyframes blink {
  0% {
    box-shadow: 0 0 0 0 rgba(25, 118, 210, 0.4);
  }
  100% {
    box-shadow: 0 0 0 8px rgba(187, 222, 251, 0.3);
  }
}
```
brew upgradeに--cleanupオプションをつける

## 2019-02-03 追記

```brew upgrade```の```--cleanup```というオプションはなくなったようです。

----

[brew(1) – The missing package manager for macOS](https://docs.brew.sh/Manpage)を読んでいたところ、以下のような記述を見つけた。

>- upgrade [install-options] [--cleanup] [--fetch-HEAD] [--ignore-pinned] [formulae]: Upgrade outdated, unpinned brews (with existing install options).
>
> Options for the install command are also valid here.
> 
> If --cleanup is specified or HOMEBREW_UPGRADE_CLEANUP is set then remove previously installed formula version(s).

また、以下のような記述もあった

> - HOMEBREW_NO_AUTO_UPDATE: If set, Homebrew will not auto-update before running brew install, brew upgrade or brew tap.

つまり、普通にしていれば、```brew install```とか```brew upgrade```とか```brew tap```の時には、```auto-update```されるということだ。

つまり、これまで```brew update && brew upgrade && brew cleanup```とやっていたけれど、ただ```brew upgrade --cleanup```するだけで良いらしい。

たまには、マニュアルを読んで見るもんだ。
rails 昇順、降順の並び替え

データを昇順、降順に並び替えたいとき、どうやるんだっけ？とできそうでできない、かゆい感じだったので、まとめてみた。

```ruby
@user = User.all.order(id: "DESC") ## idの降順
@user = User.all.order(bith_day: "ASC") ## 生年月日の昇順(デフォルトがASCになっているので通常この書き方はない)

@user = User.all.order(:id) ##　昇順or降順を指定しない場合(デフォルトは)昇順
```
jsdoで、なでしこ　その２

#概要

jsdoで、なでしこ、やってみた。
plugin作ってみた。

#サンプルコード

```
「さくら」と表示
さくら作成
さくらMML = 「ccggAAggffeeddccggffeeddggffeeddccggAAggffeeddcc」
さくらPLAY

```

#成果物

http://jsdo.it/ohisama1/KwIX

以上。
TreasureDataで日付計算(Hive)

## 概要
TreasureDataのクエリでWhere条件の期間を動的に取得したくて、日付の計算を調べて見た結果をメモしておく。

## 日付計算クエリ

```sql
SELECT
  -- 今日
  TD_TIME_FORMAT(
    TD_DATE_TRUNC('day', TD_SCHEDULED_TIME(), 'JST'),
    'yyyy-MM-dd HH:mm:ss',
    'JST'
  ) as today,
  -- 昨日
  TD_TIME_FORMAT(
    TD_DATE_TRUNC('day', TD_TIME_ADD(TD_SCHEDULED_TIME(), '-1d', 'JST'), 'JST'),
    'yyyy-MM-dd HH:mm:ss',
    'JST'
  ) as yesterday,
  -- 今月1日
  TD_TIME_FORMAT(
    TD_DATE_TRUNC('month', TD_SCHEDULED_TIME(), 'JST'),
    'yyyy-MM-dd HH:mm:ss',
    'JST'
  ),
  -- 先月1日
  TD_TIME_FORMAT(
    TD_DATE_TRUNC(
      'month',
      TD_TIME_ADD(TD_DATE_TRUNC('month', TD_SCHEDULED_TIME(), 'JST'), '-1d', 'JST'),
      'JST'
    ),
    'yyyy-MM-dd HH:mm:ss',
    'JST'
  ) as pre_month,
  -- 2ヶ月前の1日
  TD_TIME_FORMAT(
    TD_DATE_TRUNC(
      'day',
      TD_TIME_PARSE(
        ADD_MONTHS(TD_TIME_FORMAT(TD_SCHEDULED_TIME(), 'yyyy-MM-01', 'JST'), -2),
        'JST'
      ),
      'JST'
    ),
    'yyyy-MM-dd HH:mm:ss',
    'JST'
  ) as pre_2month,
  -- 3ヶ月前の1日
  TD_TIME_FORMAT(
    TD_DATE_TRUNC(
      'day',
      TD_TIME_PARSE(
        ADD_MONTHS(TD_TIME_FORMAT(TD_SCHEDULED_TIME(), 'yyyy-MM-01', 'JST'), -3),
        'JST'
      ),
      'JST'
    ),
    'yyyy-MM-dd HH:mm:ss',
    'JST'
  ) as pre_3month,
  -- 半年前の1日
  TD_TIME_FORMAT(
    TD_DATE_TRUNC(
      'day',
      TD_TIME_PARSE(
        ADD_MONTHS(TD_TIME_FORMAT(TD_SCHEDULED_TIME(), 'yyyy-MM-01', 'JST'), -6),
        'JST'
      ),
      'JST'
    ),
    'yyyy-MM-dd HH:mm:ss',
    'JST'
  ) as pre_6month,
  -- 1年前
  TD_TIME_FORMAT(
    TD_DATE_TRUNC('day', TD_TIME_ADD(TD_SCHEDULED_TIME(), '-365d', 'JST'), 'JST'),
    'yyyy-MM-dd HH:mm:ss',
    'JST'
  ) as pre_year
;
```

## 参考サイト
* [TreasureDataで前月から日毎で集計したい場合のクエリ](https://qiita.com/toru-takahashi/items/87518822542b50411d29)
* [TreasureDataで前月とか前々月とか指定したい](https://qiita.com/ken11_/items/1d352178e1e572513d1e)
rippleの脆弱性ドキュメント

運用時に参考になるので載せておきます

# Partial Payment

https://ripple.com/files/GB-2014-06.pdf

# Potential Rippling

https://ripple.com/files/GB-2015-04.pdf

# Reliable Transaction Submission

https://ripple.com/files/GB-2015-01.pdf
[Ruby] rbenv install --listで "dyld: Library not loaded: " というエラーの解決方法

### 環境
Mac OS X 10.13 (Hight Sierra)
rbenv 1.1.1-6-g2d7cefe

### エラーの内容

```
$ rbenv install --list Available versions: dyld: Library not loaded: /usr/local/opt/mpfr/lib/libmpfr.4.dylib
Referenced from: /usr/local/bin/awk   Reason: image not found
/Users/username/.anyenv/envs/rbenv/plugins/ruby-build/bin/ruby-build: 1165 行: 54305 終了                  sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z.\1/; s/$/.z/; G; s/\n/ /'      54307                       | LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n
```

rbenvはawkを利用しているようで、それが依存解決できてないようだ。

### 解決方法

```
$ brew upgrade gawk
```

でgawkをアップデートしたところ、解決。

参考：
https://github.com/atomantic/dotfiles/issues/23
Buffaloの無線LAN APのCPU使用率をZabbixに記録する

# 環境

* 無線AP: Buffalo社製 WAPS-APG600H
* Zabbix 3.4.7

# Zabbix設定

## 外部チェックスクリプト

Zabbixサーバに以下の外部チェックスクリプトを配置し、
`chmod +x baffalo_ap_cpuload.sh`で実行権限を付与。
管理ユーザ名とパスワードは環境に合わせて書き換えてください。

~~~bash:baffalo_ap_cpuload.sh
#!/bin/bash

HOST=$1
USER=(管理ユーザ名)
PASS=(パスワード)

wget --http-user=${USER} --http-password=${PASS} http://${HOST}/cpu_load -O - 2>/dev/null \
 | tr '\n' ' ' | tr ':' ' ' | awk '{print 100 * ($4 - $2) / ($3 - $1)}'
wget --http-user=${USER} --http-password=${PASS} http://${HOST}/logout.html -O - 1>/dev/null 2>&1
~~~

このスクリプトでは以下のことをやっている。

* APのWeb管理画面の「CPUモニター」でajaxで取得されるURL(`cpu_load`)に`wget`でアクセスして取得
* `awk`を使って管理画面のJavaScriptと同じ計算でCPU使用率を求める
* 最後に`logout.html`にアクセスしてログアウト(これをしないと他の端末からWeb管理画面にアクセスできなくなる)

ちなみに、`cpu_load`にアクセスすると、以下のようなテキストが返ってくる。

~~~
392992993:6957133
392991917:6957005
392990844:6956976
392989772:6956959
392988697:6956938
392987624:6956920
392986551:6956905
392985477:6956891
392984405:6956873
392983330:6956859
392982256:6956843
392981183:6956823
~~~

単位はわからないが、各行のコロンの左側がシステム時刻、右側がCPU使用時間を表していると思われる。

## Item登録

Zabbixの管理画面から「Configuration」「Templates」で無線LANのAP用のテンプレートを選択し、「Item」「Create Item」からItemを作成する。

* Type: `External check`
* Key: `baffalo_ap_cpuload.sh["{HOST.CONN}"]`
* Type of information: `Numeric (float)`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197772/5135602a-01a9-f914-f026-d88bf931573f.png)

## Graph登録

上記で追加したItemを「Create Graph」からGraphにする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197772/6a3e8861-e1af-b3a5-c5fc-c5c541a4f1dd.png)

# 結果

1時間ほど取得した結果はこんな感じ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197772/52a38493-9cf5-5d23-f7c1-29ca68b4d97f.png)
Insta360 Studio が出力した 360度 JPEG 画像に正しい EXIF タイムスタンプを付与する

Insta360 Studio で 360度画像を JPEG に出力した際、ファイル名に日付情報がついてくるが EXIF 画像にはその情報が埋め込まれない。

このままでは Google Photos などで画像が正しい順番に並び替えられないので、EXIF 情報を付与する。

# exiftool のインストール

事前に homebrew が使える状態にする

```bash
brew install exiftool
```

# EXIFの埋め込み

```bash
exiftool  "-datetimeoriginal<filename" /path/to/IMG_*.jpg
```

元のファイルは必要ないので消す。

```bash
rm -rf /path/to/IMG_*.jpg_original
```
cssセンター寄せとfloatに関して

cssにてセンター寄せを行うには

```
margin： 0 auto;
```

と表記するだけ


floatに関してはhtmlの平面上から浮き上がっているので、
次に配置されている要素が下に潜り込んでしまうのです。

それを解除してくれるのが、clearプロパティです。

```
clear:both;
```

floatを指定した要素の次の要素にclearプロパティを指定することが大切！！
phpのincludeとinclude_onceが並んでいると気になる

過去に作成したwebサイトの保守作業を行った。
includeとinclude_onceが並んでいるところが気になった。
以下の通り、自作の共通部品はincludeしており、Googleアナリティクスのアクセス解析用の部品はinclude_onceしている。
統一した方がきれいなのかな？と考え直してみた。が、どちらが正しいのか自信がなく、そっとしておくことにした。

```index.php
<?php
    include 'common/header.php';
    include_once 'common/analyticstracking.php'; 
?>
    <br>
    <div class="row">
        <div class="medium-7 columns">
            <img class="thumbnail" src="img/top_img.jpg">
        </div>
        <div class="medium-5 large-5 columns">
            <h3 class="title">見出し</h3>
            <p>本文
```

phpリファレンスより抜粋
>include：指定されたファイルを読み込み、評価します。
>include_once：指定したファイルを読み込み評価します。ファイルからのコードが既に読み込まれている場合は、再度読み込まれない（略）スクリプトの実行時に同じファイ ルが複数回読み込まれ、評価される可能性がある場合に、関数の再定義や変数値の再代入といった問題を回避するために一回だけ読み込ませるために使用します

共通部品の方については、将来に改修が発生し複数回の読み込みが必要となる可能性がある。その場合にinclude_onceと書いてあったら、改修箇所がひとつ増えてしまう。
とはいえ、headerという名前の通り画面上部でしか使わないと予想できる部品だ。

GoogleAnalyticsの方については、間違って2回記述してしまったとすればバグと判断できるので、こちらはinclude_onceでよさそう。

合ってるでしょうか？
RubyでBasicObjectからhello, world!を出力する

数字が作れればどうとでもなる

```rb
bo = BasicObject.new
zero = bo.__id__ ^ bo.__id__
one  = zero.succ
space    = (one << one << one << one << one << one).chr
exclam   = ((one << one << one << one << one << one) ^ one).chr
dquote   = ((one << one << one << one << one << one) ^ (one << one)).chr
conma    = ((one << one << one << one << one << one) ^ (one << one << one << one) ^ (one << one << one)).chr
minus    = ((one << one << one << one << one << one) ^ (one << one << one << one) ^ (one << one << one) ^ one).chr
a = (one.to_s + zero.to_s + zero.to_s).to_i - one - one - one
b = a.succ
c = b.succ
d = c.succ
e = d.succ
f = e.succ
g = f.succ
h = g.succ
i = h.succ
j = i.succ
k = j.succ
l = k.succ
m = l.succ
n = m.succ
o = n.succ
p = o.succ
q = p.succ
r = q.succ
s = r.succ
t = s.succ
u = t.succ
v = u.succ
w = v.succ
x = w.succ
y = x.succ
z = y.succ
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = a.chr, b.chr, c.chr, d.chr, e.chr, f.chr, g.chr, h.chr, i.chr, j.chr, k.chr, l.chr, m.chr, n.chr, o.chr, p.chr, q.chr, r.chr, s.chr, t.chr, u.chr, v.chr, w.chr, x.chr, y.chr, z.chr

zero.instance_eval(p + u + t + s + space + dquote + h + e + l + l + o + conma + space + w + o + r + l + d + exclam + dquote)
```
【メモ】Youtube API Data (v3)のクオータについて


## この文章は自分用のメモです

[Youtube API Data v3クオータドキュメント](https://developers.google.com/youtube/v3/getting-started?hl=ja#quota)
YoutubeのAPI利用時にはリクエストとは別の概念の利用制限がある。
それが、クオータと呼ばれるQueryっぽい感じの単位。
別にユニットと呼ばれる単位もある。
Googleのコンソールから利用申請をしてAPIキーを取得すると今現在（2018/03/22)1,000,000ユニット/user/day与えられる。これは利用申請で拡張することができるみたい。


> 各リソースの ID を取得するだけの単純な読み取り操作の場合、コストは約 1 ユニットです。
> ~~~
> videos.list リクエストのコストは約 21 クォータ ユニットになります。

こんな感じのドキュメントがあるので実際どうなのかを検証してみた。

```python:検索ワード(ほげふが)にマッチする動画をアップロード順で最新50件の情報を取得するスクリプト

from googleapiclient.discovery import build
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=develop_key)

# 検索文字にマッチするidを取得
id_response = youtube.search().list(
    q='ほげふが',
    part="id",
    fields="items(id(videoId))",
    safeSearch="strict",
    order="date",
    type='video',
    maxResults=50
).execute()

# responseからidを取り出す
video_id = 'id_responseからvideo_idを取り出す'

# idからYoutubeの詳細な情報(タイトルや説明文、viewCountなど)を取得
videos_response = youtube.videos().list(
    part='id,snippet,statistics,contentDetails',
    id=video_id
).execute()

```

実際にコードを書いてリクエストを実行してみた。
[Googleコンソール](https://console.cloud.google.com/apis/api/youtube.googleapis.com/quotas
)で確認してみたら、上記コードだけで **109ユニット** 使用していた。
ちなみに内訳は

|API  |利用ユニット数  |
|---|---|
|youtube.search().list  |101  |
|youtube.videos().list  |8  |

もしかしたら、環境や検索ワードによって違うかもしれないのであくまで参考までに。

### 感想
ユニットの対応表が欲しい。
あと、GoogleAPIのドキュメントはいつ読んでも天才向けに書かれているなと思う。一般人には読み解くのにかなり時間がかかってキツイ。
エクストリームリーディングいいよエクストリームリーディング

![eXtrame Reading-logo.png](https://qiita-image-store.s3.amazonaws.com/0/138414/798037b3-8ee8-6f9f-e424-fbb691e0c664.png)


## TL;DR

技術書とかの輪読会でなんども挫折したけど、
エクストリームリーディングだと**挫折せず最後まで読めた**し、**深い理解**が得られた。
エクストリームリーディングいいよエクストリームリーディング。

## エクストリームリーディングって何？

http://d.hatena.ne.jp/umedamochio/20050114/p4 参照

> * 日本語だと５ページ単位、英語なら２ページ単位くらいを全員が黙々と読みます。  
単位が節ごとなど、本の著者が設定した単位であるほうが好ましいです。  
読み始める前に、ここまで読みましょうと合意をとります。
> * 読み終わった人は、「終わった」と宣言します。早く読み終わった人は、次を読んだり、自分なりに内容をまとめたりしておきます。

> * 重要な文の切り出し
> 各人が重要だと思う文を切り出して、その意義を議論する。
> * まとめ
> 各節ごとの趣旨をまとめる。
> 前後関係や本全体の趣旨に対する位置づけをまとめる。

## なんでやってみようと思ったのか。

* ひとりだとなかなか読まない。 
* 輪読会ってなんか尻切れになることが多い
* 輪読会って講師担当回の負担が重くて気軽に参加しづらい。参加者集めづらい。

## やってみたらどうだったか

* 負担感
    * 講師負担がないからか、本当に**参加者を集めやすかった**。
    * 予習がないので、負担感がなく気楽に続けられた。
    * 事前準備も負担感がないので、輪読会にありがちな  
「**ちょっと今週パス**」が起こりにくかった。  
（繁忙期とかトラブル発生とかでパスはあった。）
    * 以上の事から**尻切れが一度もなかった**。
* 必要なスキル
    * 少ない。予定を調整して、その場で読書できるスキルがあれば十分  
(輪読会は、講師役に資料作成能力・プレゼン能力が求められる)
* 理解度
    * ちょっとずつ読んで、ちょっとずつ議論するので、
曖昧な箇所が曖昧なままにならない。
    * みんなで議論するので、**複眼的な視点**が得られて理解が深まる。  
ひとり読書の**精読以上の理解**が得られる。
* 時間
    * とはいえ、読み切るのに輪読会以上に時間がかかる。  
技術書なら、4，5ヶ月かかる。自己啓発系でも2，3ヶ月かかる。  
感覚的には、**輪読会の倍近いの時間がかかる**。
* 適応
    * 難しい本ほどいいかも知れない
    * 資格試験の合格点を取るためのテキスト読込には向いてない

## こういうときにエクストリームリーディングいいよ

* 時間が掛かってもしっかり理解したい本があるとき
* 周りに詳しい人がいないが、それでも読みたい・読まないといけない本があるとき
* 輪読会だと参加者が集めづらいとき
* 参加者がみんな忙しいとき

## 逆にこういうのは向いてないよ

* いついつまでに読み終わらないといけない等の締め切りが決まっている
* 試験勉強のような一定の知識の記憶を目的とした読書

## エクストリームリーディングと輪読の違い

| - | エクストリームリーディング | 輪読 | 
|-----------|------------|------------|
| 講師負担 | なし（講師という概念がない） | 難しい本ほど重い | 
| 参加者負担 | ほとんどない | 予習が必要だと、難しい本ほど重い |
| 継続性 | 負担がほぼないので、最後まで継続しやすい | 講師役の都合でスキップが連続すると終わる可能性がある。<br>難しい本だと特に可能性が高い。 | 
| 理解度 | 深い。<br>ちょっとずつ読みながら、議論しながらなので、<br>不明点を曖昧なままにすることもなく、<br>また、いろいろな人の観点を共有するので、複眼的に内容を理解できる。| 講師役による。<br>講師役がよく理解できていて、説明力も高いと非常に理解度が高くなる。<br>逆もありえる。|
| 掛かる時間 | かなり長い | 長い<br>エクストリームリーディングほどではないが | 

## エクストリームリーディングの効果を最大化するコツ

* 人数を3名以上6名以下にする。
    * 少なすぎると、議論が深まらない
    * 多すぎると、議論が終わらない
* 1単位毎にひとり、必ず1回以上発言するよう水を向ける。
    * 経験の少ない人などは、発言を控えがちですが、異なる視点こそが理解を深めることに繋がります。
    * 私は「○○さんどうですか？わからなかったところ、気になったところ、刺さったところとかありますか？」と聞いています。
* メンバーの中に、異なるバックグラウンドを持った人をあえて、混ぜる
    * 同一部署の人間だけでなく、他部署の人間も混ぜるとか
    * 若手の3人に、あえてベテランを混ぜるとか、その逆とか
    * これも異なる視点を手に入れるためのコツです。
* 一気にやらない
    * 負担の少なさが身上ですので、2時間以上ぶっ通しでやったり、10日連続実施とかやらない
    * むしろ、気合い入れて一気にやれるなら、輪読会のほうがいいかもしれない
投稿の際にきちんとデータを送る

params.permitにてフィルターをかける値をチェックする

```
 def tweet_params
    params.permit(:text,:image,)この引数の間違いが多い
```

表示ビューのインプット項目をチェックする。

```
 <textarea placeholder="text" name="problem" </textarea>
```

nameが違うなどがよくあるので要チェック
HTTPメソッドに関して

HTTPメソッドのpostとgetは使い分けが必要

getは静的なメソッドでただページを表示する時などに使用

単にウェブサイトを閲覧する際など

postはデータの登録などのデータのやり取りの際に使用

情報の登録などの際、サーバーに情報を送信するなど。
新規登録ができない device機能

「新規登録画面で入力する情報を、
それぞれf.〇〇_field :カラム名という形で指定する」ということを理解する。

「存在しないカラムをf.text_fieldに指定していた」ことがエラーの主な原因です。

修正前は、f.text_field :nameとなっていました。
nameというカラム名なんてないのでエラーが発生してしまう

これをしっかりと存在するカラム名f.text_field :nicknameに変更すること
ログアウトできない

ログアウトする際にエラーが出る原因は記述不足が原因。

必ず、HTTPメソッドのチェックを行うこと。


```
<%= link_to "ログアウト", destroy_user_session_path %>
```
上記はHTTPメソッドが入力されていないためにエラーが発生

```
<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
```

エラーを正すには上記のように入力してあげると修正される。
必ずHTTPメソッドをチェックして入力すルコと。
Docker ノウハウ

# コマンド 
##基本コマンド
$ docker --version
$ docker ps
$ docker images
$ docker cp

## 発展系
・イメージの取得
$ docker pull alpine

・イメージを使ってコマンドをうつ
$ docker run alpine pwd
/
$ docker run alpine echo "hello from alpine"
hello from alpine

・コンテナ内でLinuxのコマンドを打つ
$ docker run -it alpine bin/sh
/ # ls
bin    dev    etc    home   lib    media  mnt    proc   root   run    sbin   srv    sys    tmp    usr    var

・Dockerのコンテナで動作中のシェルへの接続
$ docker exec -it コンテナ名 /bin/bash
コンテナ名は、docker ps で表示される　NAMES　の値を指定。

・コンテナ内でviが使えない
 apt-get update
 apt-get install vim
でイストール可能。

・コンテナ内のファイルをホストにコピーする
docker cp　でコピー可能。
$ sudo docker cp 341ee8d45895:/var/hyperledger/production/ledgersData /home/XXXXXXX/test4python

# 注意
　クジラのアイコン起動させていないと、daemon動いていないよ？というエラーがでる。
ログイン画面が表示されない

ログイン機能が表示されない原因として

devise_forの表記位置が挙げられる。

gemでdeviceをインストールすると自動でルーティングに記載されるが
この際に記述位置を間違えるとエラーとなる。

必ず１番上にdevice_forの記載がなければならない
RHEL6.9にZabbixをオフラインインストールする。

#背景
オフライン環境のサーバに対し、zabbixを導入したいと思います。
あとでもう少しちゃんと書きます…

#環境
■導入対象サーバ
OS:RHEL6.9
Zabbix:3.0.0
MySQL:5.1
php:5.6(zabbix 3系は5.6以上必須)
httpd:2.2

■ローカルリポジトリ構築サーバ
OS:RHEL-6.9_HVM-20180118-x86_64-1-Hourly2-GP2


#導入手順

###ローカルリポジトリ構築
・AWSにてRHEL6.9を構築し、ローカルリポジトリを作成する。
https://qiita.com/Sa2Knight/items/bec1c24d78719c01a705

・ダウンロードオプションを付けつつ、上で作成したローカルリポジトリにrpmを追加していく。
以下リンクの「Apache、MySQLの起動」直前まで実施。
https://qiita.com/mken/items/0e2de86ddc96c4c3ddce

・Zabbixのソースをダウンロードしておく。置く場所は/root/MyRepoで良い。
上リンクの「Zabbix-3.0.0ソースの取得」を実施。

・ローカルリポジトリをtarでまとめ、repo.tarとかにしてローカルPCに保存。
`tar -cvf repo.tar /root/MyRepo`

・ローカルPCからオフライン環境のRHELサーバにローカルリポジトリを転送。

・ローカルリポジトリを展開し、/root/MyRepoを構築する。
（構築するというか展開したMyRepoをmvコマンドで/root/配下に配置する。）

・yumがローカルリポジトリを参照するように/etc/yum.repos.d/MyRepo.repoを作成。

・MyRepo内にあるzabbix-3.0.0.tar.gzを/usr/local/src配下に移動。


###Zabbix-Server導入
・あとは以下リンクに従いインストールを進めていく。
https://qiita.com/mken/items/0e2de86ddc96c4c3ddce

・最後zabbixにアクセスした際にphpのエラーが出るはずなので、/etc/php.iniを編集する。
`always_populate_raw_post_data = -1`
をコメントインする。

###Zabbix-Agent導入
・server導入で`--enable-agent`を付けているので、Server側は既にAgent導入済。
`vi /usr/local/etc/zabbix_agentd.conf`
で以下の通り編集。

```bash:/usr/local/etc/zabbix_agentd.conf
Server=(Zabbix server IP)
ServerActive=(Zabbix server IP)
ListenIP=0.0.0.0
```

・Zabbix-agentの起動
`/usr/local/sbin/zabbix_agentd`

・Zabbixにアクセス。
https://<IPアドレス>/zabbix


ガイドに沿って入力を進めて行きます。
Finish後、IDとパスワードを聞かれます。初期パスは以下の通り。

```
ID:Admin
Pass:zabbix
```

====
VMの監視を導入。

https://go-journey.club/archives/6010
bashのコマンド置換で複数行を処理したい

# bashのコマンド置換で複数行を処理したい

## 3行まとめ

- bash（POSIXシェル）のコマンド置換を使うと、コマンド出力をコマンドとして実行させられて便利
- 入れ子にできるため、$()がおすすめ
- 出力が複数行の場合は、while readなどで1行ずつ取り出して$()に流す


## コマンド置換の例
※確認環境はRed Hat Enterprise Linux Workstation release 6.8 (Santiago)です。

　bashのコマンド置換を使うと、コマンド出力をコマンドとして実行させることができます。
　以下例を見てみましょう。通常、echoの後に文字列を続けて入力するとその文字列がそのまま返ってきます。

``` bash
$ touch hoge
$ ls -la hoge
-rw-rw-r--. 1 testuser testuser 0  3月 22 11:07 2018 hoge
$ echo chmod 666 hoge
chmod 666 hoge
```

　次のように、この文字列を$()でくくってあげると、くくられた文字列をコマンドとして解釈・実行させることができます。これがコマンド置換になります。

``` bash
$ touch hoge
$ ls -la hoge
-rw-rw-r--. 1 testuser testuser 0  3月 22 11:07 2018 hoge
$ echo $(chmod 666 hoge)

$ ls -la hoge
-rw-rw-rw-. 1 testuser testuser 0  3月 22 11:07 2018 hoge
```

　実現方法としては、以下2通りあるのですが、$()で実現する方をお勧めします。

- \`コマンド\`
- $(コマンド)

 $()を使うメリットとしては以下があります。

- 入れ子にできる


## コマンド出力が複数行に渡る場合

　シェルの出力結果をコマンド置換したい場合は、$(./test.sh)などとします。出力が1行しかない場合は何も考えなくてもよいのですが、複数行に渡る場合工夫が必要です。

　次のようなシェルをコマンド置換するケースを考えてみましょう。

```bash:test.sh
#!/bin/sh

TARGET="hoge"

echo "chmod 700 ${TARGET}"
echo "date"
```

　そのまま実行すると以下のように表示されます。

```bash
$ ./test.sh 
chmod 700 hoge
date
```

　コマンド置換してみると、dateまで含めてchmodの引数として処理されてしまっています。うまくないです。

```bash
$ $(./test.sh)
chmod: cannot access `date': そのようなファイルやディレクトリはありません
```

　for でコマンドの結果を取り出して$()に渡してみると、こうなりました。

```bash
$ for v in $(./test.sh); do echo $($v); done
chmod: missing operand
詳しくは `chmod --help' を実行して下さい.

コマンドが見つかりません。 

コマンドが見つかりません。 

2018年 3月 22日 木曜日 14:26:36 JST
```

　コマンド置換せずに出力させてみると、空白で分割されてしまっているようです。（IFSを設定してあげればうまくいくかもしれない）

```bash
$ for v in $(./test.sh); do echo $v; done
chmod
700
hoge
date
```

　while readで1行ずつ取り出して$()に渡してあげると、うまくいきました。

```bash
$ ./test.sh | while read f; do $(echo $f); done
2018年  3月 22日 木曜日 14:29:02 JST
$ ls -la hoge
-rwx------. 1 testuser testuser 0  3月 22 11:07 2018 hoge
```

 while readで取り出される値を1つずつ見てみると、1行ずつ取り出されていますね。

```bash
$ ./test.sh | while read f; do echo $f; done
chmod 700 hoge
date
```

 コマンド置換の際、改行文字の取り扱いには注意ですね。ヘルプより抜粋ですが、以下のような動きになります。
- 末尾の改行文字が削除される
- 文字列の途中にある改行文字は削除されませんが、単語分割の際に削除されることがある

　改行を残したければ、"$(コマンド)"というような記載になります。[^pl]



## 参考
- [スクリプトやコマンドの実行結果をコマンドとして実行するメモ(バッククオート``や$( )を使おう)](http://tweeeety.hateblo.jp/entry/2015/01/08/221519)
- [【bash】行ごとに処理する \- Qiita](https://qiita.com/kazu56/items/83340a2e284298b9e237)
- [Shell Command Language](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_03)
- [bash Tips \- コマンド置換と算術式展開、パラメータ展開 \- Qiita](https://qiita.com/mashumashu/items/bbc3a79bc779fe8c4f99)

[^pl]: [シェルスクリプトで実行したコマンドの結果の改行をそのままにする](http://please-sleep.cou929.nu/get-command-result-with-newline.html)
【AWS】AWSコンソールの便利な機能

Tips的なお話です。（既にご存知の方はスルーしてください。）

AWSマネジメントコンソールの画面上部にあるダッシュボードには、
使用頻度の高いサービスを固定しておくことができ、無駄な操作を減らすことができます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/239026/5a95039b-d45f-065d-c481-f16ae796b499.png)

##手順
①画面上部の「押しピン（画鋲）ボタン」をクリック。
（AWSサービスの一覧が表示されます）

②ダッシュボードに固定したいサービスを選択し、ドラッグして上部に持ってきます。

## おすすめ
個人的なおすすめは、下記の4つです。
「**VPC、EC2、S3、IAM**」

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/239026/b7e74598-9e66-7ad7-1247-d8c4126a5d68.png)

「使用頻度の高さ」+「サービス名の短さ」から鑑みて、これがベストかと。
（ちなみに、AWSトレーニングに参加した際の講師の方も上記4つを設定されていました。）
biqquery で日付跨いで select したい

日付別にテーブルを作ってデータを入れている場合に、
1日分集計したいけど、1日の切り替わりが 0時じゃ無い時とかに...

```SELECT * FROM
(TABLE_DATE_RANGE([prefix]_,TIMESTAMP('[Y-m-d]'), TIMESTAMP('[Y-m-d]')))
where
createdAt >= DATE_ADD(TIMESTAMP("[Y-m-d H:i:s]"), -9, "HOUR") and
createdAt <= DATE_ADD(TIMESTAMP("[Y-m-d H:i:s]"), -9, "HOUR");```

* TABLE_DATE_RANGE
    * 第二引数に開始年月日、第三引数に終了年月日を入れて範囲を設定。
        * タイムスタンプに変換する必要があるため、TIMESTAMP 通してます。
    * 第一引数は、テーブル名にあたります。
    * `hoge_2018-3-23 〜 hoge_2018-3-24`みたいなテーブル指定になります...
* createdAt について
    * DATE_ADD を通し -9時間しているのは、bigquery は UTC で insert されるためです。
    * 時間指定自体は日本時間のが分かりやすいのでそれで指定し 9時間の差分を DATE_ADD で埋めています
    * JST は UTC の +9時間のため、データが入るとき -9時間されているので、DATE_ADD では -9時間で指定してます。
データベースのアソシエーションの不一致によるエラー

データベースのアソシエーションを組む上で
必ずアソシエーションを構築するデータベース同士のデータは一致させなければならない。

例えば
AテーブルとBテーブルがあるとする

Aテーブルにはツイートが、Bテーブルには登録情報がレコードされている。

Aテーブルには写真が６枚 idがそれぞれ１〜６まで振られている
Bテーブルはユーザーの登録情報が１人分入っているとすると

エラーが発生する。

なぜならアソシエーションする際はデータベースの項目を一致させないといけない
Aは６人分のidなのにBは１人しかない。 これがエラーの原因

回避するにはAの６人分のidを全て１人に統一すること。

必ずデータベース同士の項目を一致させないといけないのが肝
GitHubなどで見かける、LGTM/WIP/IMHOみたいな英語の略語集

みなさんもGitHubとは仲良くお付き合いしているかと思います。
PR時こんなコメントを残してあげたら現場の雰囲気も更に良くなるかも！
特にLGTMのときはGIFなんかを貼ると更にGOOD！

## OKコメントや指摘コメント時に多く見かける
### GOTCHA
***
#### I've Got You
やったぜ！

### LGTM
***
#### Looks Good To Me
言わずと知れたマージトリガー

### IMO
***
#### In My Opinion
私個人の意見なんですけど

### IMHO
***
#### In My Humble Opinion
私なんかがごめんね、私個人の意見なんですけど

### WIP
***
#### Work In Progress
今やってる

### WFM
***
#### Works For Me
私のところでは動いている


## 柔らかに波風立てずに
### NP
***
#### No Problem
全然大丈夫だから気にしないで

### AFAIK
***
#### As Far As I Know
私が知る限りでは

### FYI
***
#### For Your Information
ご参考までに

## To Be ～系
### TBD
***
#### To Be Determined
後で決めるよ

### TBA
***
#### To Be Advised
後で連絡するよ

### TBW
***
#### To Be Written
後で書くよ

## 波風を立てる
### TIA
***
#### Thanks In Advance
私はやらない、頼んだ

### ASAP
***
#### As Soon As Possible
早くしてくれ

### TLDR
***
#### Too Long, Didn't Read
長いから読んでない

## 使い方にはご注意を！
### FYA
***
#### For Your Action
返信くれ

## 番外
### XD
***
#### 横向きはっちゃけ笑顔
照れた時や嬉しいときにどうぞ

### TGIF
***
#### Thank God, It's Friday
やった、金曜日だぜ(デカくなり過ぎたBranchなどがマージされたら使ってみましょう)

### 感想
***
現場の雰囲気は大事！
renderによるエラー

renderメソッドにpatialオプションをつけた場合

その後に指定するファイル名の先頭に「＿」アンダーバーからスタートする。

```
<%= render partial:"tweet" ,locals:{tweet:tweet} %>
```

上記の場合、partial: **"tweet"**がファイル名となるため

ファイル名は**_tweet.html.erb**としないとエラーになる。
Railsのエラー　~before_actionによるエラー~

before_actionを使用する際に、オプション(only,except)を使用せずに定義した場合

全てのメソッドの実行前に
before-actiionの定義しているメソッドが定義されるので

もしもbefore-actionに
redirect_toメソッドがかかっていると何も処理をすることができない

もしも、メソッドを指定してbefore-actionを使う際は
オプションで

```
before_action :move_to_index
```

上記では全てのメソッドの実行前に処理がなされるのでエラー発生の原因に

```
before_action :move_to_index, except: :メソッド名
```

上記だと指定したメソッド以外にmove_to_indexを適応

```
before_action :move_to_index, only: :メソッド名
```
上記だと指定したメソッドだけにmove_to_indexを適応
Let's Encryptで無料SSL証明書を取得する

## 目的
- ステージング環境のGCPのVMインスタンスにSSL証明書を設定してhttps通信したい。
- やり方を忘れないための忘却録として。更新時の作業のメモに。

## 取得前に確認すること
- まずドメイン名を取得していること。
- そのドメイン名をDNS登録してIPアドレスへ名前解決している事
- 期限切れ時近くにくるメールの受信用メールアドレスを決める。

## Let's EncryptのクライアントソフトCertbotをインストール
- 証明書の取得はCertbotというソフトからコマンド操作をする事で取得できるので、まずインストール

```console
# yum install epel-release
# yum install certbot python-certbot-apache
```

- インストールされて使えるかはヘルプ表示で確認

```console
# certbot -h

-------------------------------------------------------------------------------

  certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...
以下省略
```

## 80,443ポートを証明書の認証確認の為に開放する
- ステージング、開発環境等のサーバで、外部からのポートが閉じている場合は認証が失敗します。
- 認証に必要なので、一時的に開ける操作をします。
- GCPのVMの場合はVMインスタンス→対象のサーバ選択→編集→ファイアウォールHTTP トラフィックを許可するにチェック→HTTPS トラフィックを許可するにチェック→保存　でポートを開けます。
- ポートを閉じる場合はHTTP、HTTPSトラフィックを許可するにチェックを外す→保存　

## 証明書取得コマンドを叩く
- certonly : 証明書のみを取得
- --webroot : httpdが動いていて、無停止で取得したい場合に指定
- -w : ルートディレクトリを指定します
- -d : ドメイン名を指定

```console
# certbot certonly --webroot -w /home/appuser/public_html/ -d hoge-staging.example.com
```
1. 以下会話形式に進みます
   1. 連絡用のメールアドレスを入力 : 
   1. 規約への同意 : Y
   1.  メーリングリストへの登録 : N (今回不要だった)
   1. 以上入力するとエラーが起きなければ発行される。

## 証明書の確認
- デフォルトで /etc/letsencrypt/live/以下に証明書が保存されます。

```
# ll /etc/letsencrypt/live/hoge-staging.example.com/
total 4
lrwxrwxrwx 1 root root  58 Mar 22 11:26 cert.pem -> ../../archive/hoge-staging.example.com/cert1.pem
lrwxrwxrwx 1 root root  59 Mar 22 11:26 chain.pem -> ../../archive/hoge-staging.example.com/chain1.pem
lrwxrwxrwx 1 root root  63 Mar 22 11:26 fullchain.pem -> ../../archive/hoge-staging.example.com/fullchain1.pem
lrwxrwxrwx 1 root root  61 Mar 22 11:26 privkey.pem -> ../../archive/hoge-staging.example.com/privkey1.pem
```

## Apacheに証明書を設定する
- httpd 2.4に証明書を設定するには/etc/httpd/conf.d/ssl.confを以下のように編集します

```
DocumentRoot "/home/appuser/public_html"
SSLCertificateFile /etc/letsencrypt/live/hoge-staging.example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/hoge-staging.example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/hoge-staging.example.com/chain.pem
```

- httpdを再起動して起動確認

```console
# service httpd restart
# service httpd status
```

## 証明書を更新したい時
- Let's Encryptの証明書は有効期限が90日です。
- 更新はrenewコマンドで行います。更新日の30日前になると更新処理が実行されます。
- このコマンドをclontabに登録して自動化するなど、更新作業を自動化する事ができます。

```console
# certbot renew
```

## 終わりに、感想、課題など
- 更新の自動化時に当然ポートを外部に開放していないと認証失敗するので、更新時には開放している必要があります。閉じたサーバ等ではなにかしら工夫が必要とおもいます。
- 認証のために80と443を開けないといけない。一時的でも開けたくない時もある。
- それを差し置いても、取得、更新がコード化できる所が良いところなのかな。

    自分の[技術ブログ](https://blog-c.cloudlance-motio.work/)ではフリーランス界隈の情報や最新のIT情報の発信していますので、よろしくお願いします。
gcloud kubectl コマンドを Dockerコンテナ経由で使う

## 前置き

GCPのCLIである``gcloud``を使用する場合、手元のMacまたはPCにCloud SDKをインストールする必要があります。
しかしこの手のツールやミドルウェアをインストールすると依存関係やら、バージョンアップ時になにかが壊れたりとか、トラブルに遭遇することが(気持ち的に)多く、あまりインストールしたくありません。😭

なので``gcloud``そしてGKEで使う``kubectl``コマンドをコンテナに押し込めて使おうと思います。
1コマンドでglcoudを起動でき、ローカルのDocker imageにもアクセスできる環境を目指します。😤

いくつもコマンド叩かなきゃいけないようなら、ローカルにgcloud直接インストールしたほうがマシに思えてしまうし、ローカルのDocker imageにアクセスできないと、せっかくローカルでビルドしてあるDockerイメージを GCPのContainer Registryにpushできなくなっちゃいまからね〜。

Ubuntu 17.10でためしていますが、Macでもいけるはず..です。問題があればぜひご一報を🙏


## 本題

### 使用イメージ

googleオフィシャルな、``google/cloud-sdk:alpine`` を使います。

レジストリはこちら。
https://hub.docker.com/r/google/cloud-sdk/


latestタグの方はdebianベースで全部入りなんで、苦労したくなければそっちを使ったほうがいいかもしれません。しかしサイズ1.5G😮もあるので、やめとくことにしました。軽さは大事。


### Dockerfile

alpineベースのイメージはgcloud以外kubectlすら入っていない硬派タイプなので、Dockerfileを書いて最低限、kubectlだけは入れておく必要があります。
インタラクティブに作業するためのイメージなので、ENTRYPOINTにはbashを指定しておきます。
日々のタイピング量節約。

```Dockerfile:Dockerfile
FROM  google/cloud-sdk:alpine
MAINTAINER xxxxx <xxxxx@xxxxx.jp>

WORKDIR /root/

RUN apk update  \
    && apk upgrade  \
    && gcloud components install kubectl \
    && apk add docker --no-cache

ENTRYPOINT bash
```

これだとビルドしたイメージも600MBくらいですみます😊


### docker-compose.yaml

このイメージをビルドして、適切なオプション渡してコンテナ起動してもいいんですが、オプションが結構多いので、``docker-compose.yaml``も書きます。

```docker-compose.yaml
version: '3'
services:
  gcloud:
    build: .
    volumes:
      - ./work/:/root
      - ./config:/root/.config/gcloud
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - CLOUDSDK_CONFIG=/root/.config/gcloud
      - PROJECT_ID=xxxxx
```

volumesとenvironmentがポイント。

まず、volumesの方から

- ``./work:/root`` workディレクトリを作業ディレクトリにする設定
    ここで作業することになるので、ふさわしい場所をマウントすると良いです。対象プロジェクトのディレクトリとか。

- ``./config:/root/.config/gcloud`` gcloudの設定を永続化するためにローカルに書き出す場所
    これをやっておかないと、毎回GCPにログインするハメになります。
公式なgoogle/cloud-sdkのDockerファイルを見ると
``VOLUME ["/root/.config"]``
という記述があります。要するに設定ディレクトリをexportしているわけです。
このSDKの使い方を見ると
> Once you authenticate successfully, credentials are preserved in the volume of the gcloud-config container.

というわけで、gcloud-config コンテナを立ててそのvolumeを共有しろ的なことが書いてあります。
credentialsを共有するためだけにコンテナを立てたくないし、永続化してほしいので、exportしているその先をさらにdocker-composeのvolumesでマウントしてやります。これでgcloud-config用のコンテナは必要なくなりました。😀

- ``/var/run/docker.sock:/var/run/docker.sock``
  これでホスト側で動いているdocker プロセスにコンテナ側から接続します。
  これだけでイメージが共有できる。素晴らしい。


続いて envrionment。

- ``CLOUDSDK_CONFIG=/root/.config/gcloud`` デフォルト値なんですが念の為指定

- ``PROJECT_ID=xxxxx`` なにかと入用になるので、環境変数にGKEで発行したPROJECT_IDを指定しておきます。


### 使い方

こんなディレクトリ構成に配置。

```
+ Dockerfile
+ docker-compose.yml
+ config/
+ work/
```

おもむろに実行

```sh
docker-compose run gcloud
```

コンテナがビルドされ、コーヒー一杯飲み終える頃にはbashが起動します☕

gcloudコマンドを初期化

```sh
gcloud init
```

これでローカルにcloud-sdkをインストールしたのとほぼ変わらない使用感を実現できるはずです。


なお、これらのコードを、以下のリポジトリにあげています。

https://github.com/furu8ma/google-cloud-sdk

タイピング量削減のため、docker-composeのラッパーシェル``gcloud.sh``もつけております。

これがあれば、gcloudコマンドを使用したい時は

```sh
./gcloud.sh
```

ですみます。
便利使っていただければと🌴
phpwordでテンプレートを読み込んだものをループする

#遭遇したケース
phpで帳票を出力する事があり、WORD出力指定。
phpwordを使って出力。
ただ帳票出力なので表が細かい。
数百人分一括出力が必要。（1人1ページ、各名前や住所、数字等を変数で出力）

#挫折した方法
- 丁寧に1行1行出力していく→表の細かさで挫折
- XMLで\<w:body>内を抜き出してループで連結し、ヘッダとフッタをくっつけて出力→うまく保存されず
- なにかライブラリ内にそういう機能ないのか？！→見つからず

#採用した方式
人単位でループするたびにテンプレート読み込み、テンプレートに設置した変数にsetValueしていく。
ループ最後にユニークIDで人数分のファイルを出力。
その後全ループ終了後（ファイル出力終了後）にファイルを連結してダウンロードさせる。
docxの連結はDocxMergeというライブラリを使用。
https://github.com/krustnic/DocxMerge

ここでは個別にファイルを出力する方法は割愛します。
phpwordをcomposerで導入した人はそのままcomposerでインストールしてください。
個別に設定する方はダウンロードしてrequireすれば多分大丈夫です。

#Merge Exampleがちょっと不親切なので・・
```
require "vendor/autoload.php";
use DocxMerge\DocxMerge;

$dm = new DocxMerge();
$dm->merge( [
    "templates/TplPage1.docx",
    "templates/TplPage2.docx"
], "/tmp/result.docx" );
```
こんなサンプルがありますが、まあなんとなく、最初に連結するファイルを指定して、最後に連結完了後のファイル名を指定しているんだろうな、とわかると思います。
まあ正しいのですが・・最初の連結対象ファイルは配列でした。
なので文字列を生成するのではなく、ループ中にファイル名を含むパスを生成してください。

```
var_dump($ids);
array(4) {
  [0]=>
  string(17) "/path/to/001.docx"
  [1]=>
  string(17) "/path/to/002.docx"
  [2]=>
  string(17) "/path/to/003.docx"
  [3]=>
  string(17) "/path/to/004.docx"
}
```
こんな配列を作って、

```
$dm = new DocxMerge();
$dm->merge([$ids], '/path/to/result.docx');
```
をすれは完了かと思いましたが、ライブラリがエラー吐いてきます。
copyの値が配列だよとかなんとか。
ソースを見る限り、配列になっているようには思えなかったのですが、
DocxMerge.phpの
public function merge( \$docxFilesArray, \$outDocxFilePath ) {
の下でvar_dump($docxFilesArray)してみると、

```
array(1) {
  [0]=>
  array(4) {
    [0]=>
    string(17) "/path/to/001.docx"
    [1]=>
    string(17) "/path/to/002.docx"
    [2]=>
    string(17) "/path/to/003.docx"
    [3]=>
    string(17) "/path/to/004.docx"
  }
}
```
何故か配列が変わっています。
なぜ配列が変わっている！と調べるもの面倒だったので、2箇所修正したら動きました。

DocxMerge.php: 30

```
if ( !copy( $docxFilesArray[0], $outDocxFilePath ) ) {
↓
if ( !copy( $docxFilesArray[0][0], $outDocxFilePath ) ) {
```

DocxMerge.php: 36-37

```
for( $i=1; $i<count( $docxFilesArray ); $i++ ) {
  $docx->addFile( $docxFilesArray[$i], "part".$i.".docx", "rId10".$i );
↓
for( $i=1; $i<count( $docxFilesArray[0] ); $i++ ) {
  $docx->addFile( $docxFilesArray[0][$i], "part".$i.".docx", "rId10".$i );
```
これで連結成功しました。

#連結してみると、ディレクトリ内に大量のゴミが・・
自分でゴミは片付けましょう。

```
$gomi = /path/to/*.tmp';
foreach (glob($gomi) as $val) {
   unlink($val);
}
```
PDOでLOBを入れようとしてMySQL server has gone away.

# PDOExceptionが出た
1. `SQLSTATE[HY000]: General error: 2006 MySQL server has gone away`
1. PHP側のエラーは`Error while sending QUERY packet.`
1. 場所は比較的大きなサイズのLOBを突っ込むクエリの`execute()`の場所
1. でもPHPの`memory_limit`(=128MB)に収まる程度だし、`max_execution_time`(=30秒)に収まる程度
1. MySQLのログには何も出てない

# 調べたこと
- `wait_timeout`の値が小さい？
 - 設定もいじってないし、`mysql -uhoge -p -e "show variables like '%timeout%'"`してもデフォルトの`28800`秒になっている。
 - `execute()`の直前に`$pdo->query("SELECT 1")`とか実行してみたら普通に実行できた。

- `max_allowed_packet`の値が小さい？
 - 設定を変更して大きくしてある。`mysql -uhoge -p -e "show variables like '%allowed%'"`しても設定通りになっている。

- クエリの前に接続を閉じてる？
 - 上でも書いたとおり直前に実行したクエリは通る。

- LOBが大きいから？
 - 小さなLOBにするとエラーが出ない

:thinking: :thinking: :thinking: :thinking: 

# 原因
**`setAttribute(PDO::ATTR_EMULATE_PREPARES, true);`**としていたことっぽい？？？
エミュレーションをオフにしたら治った。

## クエリをダンプしてみた
```PHP
$pdo = new PDO();
$pdo->beginTransaction();

$pdo->query("SELECT 1");
$stmt = $pdo->prepare("INSERT INTO foo(file) values (?)");
$stmt->bindValue(1,LOB,PDO::PARAM_LOB);
$stmt->execute();

$pdo->commit();
```

- エミュレーションON、大きなLOB(25MB)

```
Connect   hoge@localhost as anonymous on po
Query     START TRANSACTION
Query     SELECT 1
Prepare   INSERT INTO foo (file) VALUES (?)
Execute   INSERT INTO foo (file) VALUES (LOB)
```

エミュレーションONなのに静的プレースホルダのような動きをしている。
QuitもCOMMITもしていない。Connectが消えているので、本当に`server has gone away`なことがわかる。

- エミュレーションON、小さなLOB(1文字)

```
Connect   hoge@localhost as anonymous on po
Query     START TRANSACTION
Query     SELECT 1
Query     INSERT INTO foo (file) VALUES (LOB)
Query     COMMIT
Quit
```

正常な動作

- エミュレーションOFF、大きなLOB(25MB)

```
Connect   hoge@localhost as anonymous on po
Query     START TRANSACTION
Prepare   INSERT INTO foo (file) VALUES (?)
Prepare   SELECT 1
Execute   SELECT 1
Execute   INSERT INTO foo (file) VALUES (LOB)
Query     COMMIT
Quit
```

正常な動作

## まとめると
`PDO::ATTR_EMULATE_PREPARES`が`TRUE`のときにLOBをinsertしようとするとconnectionが消える

:thinking: :thinking: :thinking: :thinking: 


そんなこと聞いたこともないし、調べても出てこないし、原因はこれ以外のところ……？でもfalseにしたら治ったし……謎

# 環境
- CentOS Linux release 7.4.1708 (Core)
- PHP 7.1.15
- mysql  Ver 15.1 Distrib 10.2.13-MariaDB, for Linux (x86_64) using readline 5.1

# 結論
:angel:よくわからない:angel:
spyderでpipを使うとThe Python package manager (pip) can only be used from outside of IPython.と表示される

環境:
MacOS 10.13.2
Spyder 3.2.3
python 3.6

```terminal:ipConsole
$ pip install --upgrade pip
```

spyder の内蔵コンソールでpipを使おうとすると下記エラーが出力される。

```terminal:ipConsole

The Python package manager (pip) can only be used from outside of IPython.
Please reissue the `pip` command in a separate terminal or command prompt.

See the Python documentation for more informations on how to install packages:

    https://docs.python.org/3/installing/
```

これの暫定的な解決方法は、下記の通り。

```terminal:ipConsole
$ !pip install --upgrade pip
```

引用
[how to run pip install outside of the IPython shell [duplicate]-stackoverflow
](https://stackoverflow.com/questions/47370041/how-to-run-pip-install-outside-of-the-ipython-shell)
Salesforceの権限セット/FLSのチェックを一括でやるHack

Chromeのデベロッパーツール > ConsoleからJavaScript実行で一括設定してしまう。

# フルアクセス
```
Array.prototype.forEach.call(
  document.getElementsByTagName("input"), 
  function(i) { if (i.type == 'checkbox' && i.disabled == false) i.checked = true; }
);
```

# 読み取りのみ
```
Array.prototype.forEach.call(
  document.getElementsByTagName("input"),
  function(i) { if (i.type == 'checkbox' && i.disabled == false && i.id.indexOf('fls_read_ck') > 0) i.checked = true; }
);
```

とか。なんで「すべて選択」とか無いんだろうこの画面。
Salesforce Test.loadDataでORA-20008エラーが出たら

# 概要

Salesforceで**ORA-xxxxx**が出た時は恐怖のどん底に突き落とされた経験をした人は多いかと思います
ORA-xxxxxシリーズが出たら、まずSalesforceでハンドリングできていないエラーなので、すぐに対処できない
ググっても普通のOracleのエラー対処法しか出てこないし、内容も的外れたものばっかりだったりするので、正直お手上げ状態になることが多いです

そんな中で本日Test.loadDataで**System.SObjectException: common.exception.SfdcSqlException: ORA-20008**が出たので、その対処法を紹介したいと思います

# 原因

Test.loadDataに読み込ませているCSVデータの参照項目の**参照先のデータが投入されていない**ことが原因
自己参照の場合は、分割してロードすれば問題ないです

```text:data.csv
ID, Name, ref__myself__c
"1", "name1", ""
"2", "name2", "2"
```

↓(分割)

```text:data1.csv
ID, Name, ref__myself__c
"1", "name1", ""
```

```text:data2.csv
ID, Name, ref__myself__c
"2", "name2", "2"
```


※あくまでも一因かもしれない


# 対処法

- 事前に参照先のデータを投入する
- 対象の項目を空白にする（もしくは削除）
【MMDモデルの動きをNeuronに対応】A字型のモデルをT字スタンスに変換させる方法

##はじめに
![kizunaai_A_neuron_gif.gif](https://qiita-image-store.s3.amazonaws.com/0/242611/d76d6f68-5e9c-ee51-4557-f35f67b3d243.gif)

「Neuronで3Dモデルを動かしたい、でも腕の動きがなんだかおかしい」
ということに気づいた方もいるかと思います.

それは**Neuronにデフォルトで入っているモデルがT字型になっているから**です。
従って、T字形のモデルに合わせてモーションキャプチャするNeuronに対してA字型のモデルで動かすと腕がおかしくなってしまうわけですね。

ということは、**Unity側のモデルもT字型に合わせる**、もしくは**Neuron型のモデルをA字型に変更する([参考](https://qiita.com/aimino/items/55e8ec706fa18581b0a1))**必要がでてきます。
(モデルのスタンスを一致させればいいということ)

今回は、**Unity側に取り込んだA字型の3DモデルをT字型に変換する方法**を紹介します。

ここでは(@aimino)さんの記事を参考にさせていただきました。
https://qiita.com/aimino/items/a80785ec655ab5d129a4
##完成イメージ
Before

![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/67d65c1d-f8e9-0ba2-c96f-c69b5694b440.png)

↓
After
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/69222aab-f758-07ae-10e0-e06df4abf44f.png)

##用意するもの

- MMDモデル(今回は[KizunaAiモデル](http://kizunaai.com/download-page/)を使用)
- [PMXエディタ](http://kkhk22.seesaa.net/category/14045227-1.html)
- [Unity](https://unity3d.com/jp/get-unity/download)

ここではMMDモデルをUnityでインポート済みである前提で進めていきます。
なお、T字スタンスに変えるだけであればMMDモデルのファイル、PMXエディタだけで構いません。

##モデルをPMXエディタで開く
まずはPMXエディタをダウンロードしましょう。
http://kkhk22.seesaa.net/category/14045227-1.html

pmxデータがあるので、 こちらをpmxエディタで開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/64250f06-b78c-65fe-b4e5-48b3cc5ebdd0.png)



するとこのような画面になっているかと思います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/dcd5de6d-8daf-21c0-407a-d656c9e4e623.png)

次にTransformViewを開きます。

表示>一番下にあるTransformViewを開きましょう。
![PmxView 2018_03_22 14_54_24.png](https://qiita-image-store.s3.amazonaws.com/0/242611/af492c3e-fb35-4bf4-54c0-94367b547492.png)

この画面に変わります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/c0507edc-9162-328c-353b-1722854b9a9e.png)

以下の画面のように骨を選択した状態にすれば準備完了。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/b13351ec-e834-53da-6c8b-8738c9dfbd46.png)


##骨格を調整して保存
後は骨格を調整するだけです。
腕の関節あたりを持ち上げてT字になるように調整しましょう。
![kizunaai_mpx2_gif.gif](https://qiita-image-store.s3.amazonaws.com/0/242611/7dcad7f4-d155-d792-5b0d-7e0ffb2a9a7b.gif)

細かいところは各自調整してもらえばと思います。

T字スタンスになったら、**現在の形状で保存**を選択して好きな場所に保存。
![TransformView 2018_03_22 16_15_27.png](https://qiita-image-store.s3.amazonaws.com/0/242611/68bdbc9c-b6bb-3fa0-bbcc-74a97460c413.png)


ここからはMMDモデルをUnity上で使うfbxデータに変換すれば、Unity側でT字スタンスのモデルを扱うことができます。

##T字スタンスのMMDモデルを実際にUnity上で使えるようにする

先程作成したpmxデータを自分のUnityプロジェクトに保存すると新しく追加されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/0f2e1bab-9603-9534-09f9-431422c139e6.png)

後はMMD4Mecanimを使ってpmxデータをfbxデータに変換していきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/3a0677c9-4784-d5b5-14b0-05edf5246dec.png)

するとfbxデータのT字スタンスができるのでドロップすれば、完了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/aecfabab-6405-8b0a-d19f-f988f11e388e.png)

お疲れ様でした。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242611/456d154d-9761-908a-5b24-bbb8c28512d9.png)


MMD4mecanimについてもまとめたので参考にしていただければ。
(https://qiita.com/ngron/items/cdd3248c7ff96a1bc5b0)
AtCoder に登録したら解くべき精選過去問 10 問をPython3で解いてみた

#はじめに
どーも、最近競プロをはじめた新人です。
@drkenさんの記事[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/cympfh/items/b860ecb5f5415b15f3c9#_reference-ed0a9eabc29a068454c8)に取り上げられている問題10問をPython3で解いてみました.AtCoderの入門として、非常に素晴らしい記事なので、興味のある方はぜひチェックしてください.
問題の詳細と一般的な解法は元の記事を参照してください.

###第1問 [ABC 086 A - Product](https://beta.atcoder.jp/contests/abc086/tasks/abc086_a)
```py
a, b = map(int, input().split())
if a*b % 2 == 0:
    print("Even")
else:
    print("Odd")
```
簡単なif-elseで解きました.


###第2問 [ABC 081 A - Placing Marbles](https://beta.atcoder.jp/contests/abc081/tasks/abc081_b)
```py
print(input().count("1"))
```
stringのcountを使えば楽.

###第3問 [ABC 081 B - Shift Only](https://beta.atcoder.jp/contests/abc081/tasks/abc081_b)
```py
N = input()
A = list(map(int, input().split()))
cnt = 0
while all(a%2==0 for a in A):
    A = [a/2 for a in A]
    cnt += 1
print(cnt)
```
内包表記を使いました.

###第4問 [ABC 087 B - Coins](https://beta.atcoder.jp/contests/abc087/tasks/abc087_b)
```py
A = int(input())
B = int(input())
C = int(input())
X = int(input())
res=0
for  i in range(A + 1):
    for j in range(B + 1):
        for k in range(C + 1):
            if 500*i + 100*j + 50*k == X:
                res += 1
print(res)
```
三重ループなので内包表記より全探索を使いました.

###第5問 [ABC 083 B - Some Sums](https://beta.atcoder.jp/contests/abc083/tasks/abc083_b)
```py
N, A, B = map(int, input().split())
res = 0
for i in range(N+1):
    if A <= sum([int(s) for s in str(i)]) <= B:
        res += i
print(res)
```
intとstringの相互変換を活用しました.

###第6問 [ABC 088 B - Card Game for Two](https://beta.atcoder.jp/contests/abc088/tasks/abc088_b)
```py
N = int(input())
l = list(map(int, input().split()))
l.sort(reverse=True)
print(sum(l[0::2]) - sum(l[1::2]))
```
sort来ましたね.

###第7問 [ABC 085 B - Kagami Mochi](https://beta.atcoder.jp/contests/abc085/tasks/abc085_b)
```py
N = int(input())
l = sorted([input() for _ in range(N)])
print(len(set(l)))
```
sortとsetの連携です.


###第8問 [ABC 085 C - Otoshidama](https://beta.atcoder.jp/contests/abc085/tasks/abc085_c)
```py
N, Y = map(int, input().split())
res = (-1, -1, -1)
for x in range(N + 1):
    for y in range(N + 1 - x):
        if N - x - y >= 0 and 10000*x + 5000*y + 1000*(N - x - y) == Y:
            res = (x, y, N - x - y)
print(res[0], res[1], res[2])
```
二重ループの例ですが、この解答はあまり好きではありません.

###第9問 [ABC 049 C - Daydream](https://beta.atcoder.jp/contests/abc049/tasks/arc065_a)
```py
given = ["dreamer", "dream", "eraser", "erase"]
S = input()
while len(S) > 0:
    judge = [S.endswith(i) for i in given]
    if any(judge):
        target = given[judge.index(True)]
        S = S[:-len(target)]
        if len(S) == 0:
            print("YES")
            break
    else:
        print("NO")
        break
```
ちょっと難しいですね、DPを使ったら楽かもしれません.

###第10問 [ABC 086 C -Traveling](https://beta.atcoder.jp/contests/abc086/tasks/arc089_a)
```py
N = int(input())
for _ in range(N):
    t, x, y = map(int, input().split())
    if x + y > t or (t + x + y)%2 != 0:
        print("No")
        quit()
print("Yes")
```
元記事の解説を参照しました.主に偶数と奇数の性質を使いました.


#終わりに
入門なので、それほど複雑なコードではありません.他の言語と比べて,Pythonが遅いと言われますが、それほど大した問題ではないと思います.速度の方で気になる方もご心配なくPythonを使っていただければ大丈夫だと思います.
Archlinux_困った時の対処法


##症状1
```
sudo pacman -Syu
```
で

```
エラー: ファイル /var/lib/pacman/sync/archlinuxfr.db を開けませんでした: Unrecognized archive format
```

##解決方法1

```
sudo rm -R /var/lib/pacman/sync/
```
参照元：
https://bbs.archlinux.org/viewtopic.php?id=135310

----

##症状2

```
sudo pacman -Syu
```
で"パッケージの衝突でアップデートに失敗"したとき

##解決方法2

衝突したファイルをリネーム

参照元：
https://free-of-x.com/?p=996

----

##症状3

```
pacman -Syyu  もしくは  yaourt -S ***
```
でパッケージをインストールしようとしたら

```
"libalpm.so.10: cannot open shared object file"
みたいなエラーが出て，インストールできないとき
```

##解決方法3
package-queryをgitから落としてきて，再ビルドしてあげる．

```
git clone https://aur.archlinux.org/package-query.git
cd aur** //落としてきたやつ
makepkg -i 
```
以上

参照元：
http://norikakip.hatenadiary.jp/entry/2018/05/31/182349
https://is.gd/rM3gC6

----
##症状4

GW-900Dのドライバをインストールしようと、dkmsコマンドを実行すると、
/lib/modules/(uname -r)/build
がなくて進まない。

https://github.com/gordboy/rtl8812au-5.6.4.2

##解決方法4

```
sudo pacman -S linux-headers-(uname -r)
```
でインストールすると、
/lib/modules/(uname -r)/build
ができるので、makeできるようになる。
GAE/Go google cloud sdk 194.0.0 で `goapp cannot import name goroots` エラーが出る場合の対処法

こんにちは @wezardnet です。自分だけ発生する現象かもなので備忘として残しておきたいと思います :sweat:

以前にも似たよう現象が起きて困ったことになっていたのですが、この時は以下の情報により解決することができました。

* [google cloud sdkを190.0.1にバージョンアップしたら `goapp cannot import name goroots` のエラーが発生した](https://qiita.com/ryutah/items/abfcb903ae70d30e2f60)
* [Google Cloud SDK 190.0.1 で goapp がImportErrorでコケる #29](https://github.com/gcpug/nouhau/issues/29)

# 現象
今回は SDK 194.0.0 にアプデしたら、次のようなエラーが出るという、「またかよ！」っていう現象ですｗ

```terminal
Traceback (most recent call last):
  File "${GCLOUD_SDK_ROOT}/platform/google_appengine/goapp", line 40, in <module>
    from google.appengine.tools.devappserver2.go import goroots
ImportError: cannot import name goroots
```

# 対処法
`${GCLOUD_SDK_ROOT}/platform/google_appengine/google/appengine/tools/devappserver2/go` に SDK 190.0.1 の対応で作成した `goroots.py` をコピーして配置すれば OK です。
Python Fakerのインストールでこけた！！

すごく単純で恥ずかしい話なので、あまりQiita向けじゃないけど、
記録として残しておきます。

# なんでさね！！

`
[vagrant@milky-vagrant fake-factory-0.5.3]$ pip install faker
Collecting faker
  Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7f706fadd4a8>: Failed to establish a new connection: [Errno -2] Der Name oder der Dienst ist nicht bekannt',)': /simple/faker/
  Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7f706faddc88>: Failed to establish a new connection: [Errno -2] Der Name oder der Dienst ist nicht bekannt',)': /simple/faker/
`

インストールしようとしたらこんなエラーがまっきっきな字で表示されしまいました。
ふぁー！なんてこったい！！
調べると、Proxyだーなんだという記述。
仕方ないので、スマホでテザリングして落とせまし…たとはいかず、
途中まで進んだもののやっぱり赤字で
`
Exception:
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/usr/lib/python3.6/site-packages/pip/commands/install.py", line 342, in run
    prefix=options.prefix_path,
  File "/usr/lib/python3.6/site-packages/pip/req/req_set.py", line 784, in install
    **kwargs
  File "/usr/lib/python3.6/site-packages/pip/req/req_install.py", line 851, in install
    self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
  File "/usr/lib/python3.6/site-packages/pip/req/req_install.py", line 1064, in move_wheel_files
    isolated=self.isolated,
  File "/usr/lib/python3.6/site-packages/pip/wheel.py", line 345, in move_wheel_files
    clobber(source, lib_dir, True)
  File "/usr/lib/python3.6/site-packages/pip/wheel.py", line 316, in clobber
    ensure_dir(destdir)
  File "/usr/lib/python3.6/site-packages/pip/utils/__init__.py", line 83, in ensure_dir
    os.makedirs(path)
  File "/usr/lib64/python3.6/os.py", line 220, in makedirs
    mkdir(name, mode)
PermissionError: [Errno 13] Keine Berechtigung: '/usr/lib/python3.6/site-packages/text_unidecode'
`

なんてかわいくない表示が…
調べてみると、Stackflowにて素敵な回答。
[“PermissionError: [Errno 13] Permission denied: '/usr/lib/python3.5/site-packages'” installing Django](https://stackoverflow.com/questions/39950254/permissionerror-errno-13-permission-denied-usr-lib-python3-5-site-package)

>1
You must have root privileges when installing modules to the system python. Use sudo. – MisterMiyagi Oct 10 '16 at 1:55

>1
おいおい、rootでインストールしないといけないぜ？sudo使えよ

なるほど。

`sudo pip3 install Faker`

で無事解決。
覚書として投稿。(こんな初歩の初歩なんてクソの役にも立たないと思いますが…)
Debian8(jessie)でScrapyを動くようにし、エンジニアが垂涎しそうなスクレイピングをしてみる

# はじめに
### 相変わらず
必要なんだか不要なんだかわからないものも入ってるんですが、
とりあえず動けばOKってスタンスでやってますので、
真似するときは火傷に気をつけてネ♥

# Scrapyを使う
## 環境を作る

### 現状を確認

```Bash
> python -V
Python 2.7.9
> python3 -V
Python 3.4.2
```

色々あるでしょうけど動けばOKなので、
PythonのVersionはデフォルトでやってみます。

### 前準備

では、便利なez_setupとpipをインストール

その前にpythonの開発に必要なものを入れます。
順番が逆だと、

```bash
Command "/usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-6I01ux/Twisted/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-Imo90a-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-6I01ux/Twisted/
```
みたいなエラーが出ちゃいます。
最初からPythonが入ってるのに必要なものがあると言うことは知らず、
エラーでちょっと混乱しました。（笑）

```bash
> apt -y install zlib1g-dev libssl-dev libreadline-dev libsqlite3-dev libbz2-dev libncurses5-dev libgdbm-dev liblzma-dev tk-dev zlibc

> wget https://bootstrap.pypa.io/ez_setup.py -O - | python
> easy_install pip
> pip install pyopenssl --upgrade
```

### Scrapyをインストール

```bash
> pip install scrapy
```

これで準備はおわり。たぶん。

## チュートリアル通りで実行

まずはチュートリアル通り

```python:myspider.py
import scrapy

class BlogSpider(scrapy.Spider):
    name = 'blogspider'
    start_urls = ['https://blog.scrapinghub.com']

    def parse(self, response):
        for title in response.css('h2.entry-title'):
            yield {'title': title.css('a ::text').extract_first()}

        for next_page in response.css('div.prev-post > a'):
            yield response.follow(next_page, self.parse)
```

実行

```bash
> scrapy runspider myspider.py
```
ERRORが下記の場合は、コマンド ``pip install pyopenssl --upgrade``が実行されてないっぽいです。

```bash
'module' object has no attribute 'OP_SINGLE_ECDH_USE'
```

## エンジニア垂涎のアノサイトをスクレイピング

アノサイトって、会社員は職場で見ると目をつけられそうなやつです。

・・・そう、

みんなだいすきな・・・・


あれデス。

それはまた次回。

気になったらフォローでもしておいてください（笑）

# あとがき
Python楽しくなってきた！