OmniAICreator/Qiita-1.07M huggingface dataset:
AWSネットワーク周り基礎知識まとめ

## はじめに
AWSのネットワーク周りの知識があやふやなことが判明したため復習。間違ってたらご指摘お願いします。

## ネットワーク
### VPC
- AWS内の利用者専用の仮想プライベートネットワーク
- リージョンの中に作成する
- CIDRブロックは/16〜/28の範囲で作成できる    
(例：`10.0.0.0/16`)
- 可能な限り大きなサイズ(/16)で作成する
    - アドレス不足を防ぐため

### サブネット
- VPCをさらに小さなネットワークに区切った単位
- CIDRブロックは/16〜/28の範囲で作成できる
    - VPCよりも小さな範囲を指定する  
(例：`10.0.1.0/24`)
- インターネットと通信するサブネット（パブリックサブネット）、通信しないサブネット（プライベートサブネット）など、役割・ルーティングによって分割する
- 同一の役割を持ったサブネット、リソース群を複数のAZに作成することで、耐障害性の向上に繋がる（マルチAZ）


### ルートテーブル
- パケットが次にどこに向かうか、転送先を決める
- 通信経路（送信先とターゲット）を設定する
    - 送信先：パケットに指定された宛先IP
    - ターゲット：実際の転送先
- １つのサブネットに割り当てられるルートテーブルは１つ
- １つのルートテーブルを複数のサブネットで共有することができる
- ターゲットが`local`の場合はそのネットワーク内を意味する  

(例)パケットの宛先IPが`10.1.0.0/16`の範囲内の場合は`local`に通信を転送する
(`10.1.0.0/16`の範囲外を指している場合、転送先が存在しないため通信は破棄される）
<img width="605" alt="スクリーンショット 2019-11-09 21.16.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191739/6306b7d4-9c46-a0fc-5ce8-0bf5f5cee0b1.png">


### インターネットゲートウェイ
- VPCとインターネットを接続するためのゲートウェイ  

(例)サブネットをインターネットと通信できるようにする（＝パブリックサブネットにする）場合は全ての通信(`0.0.0.0/0`)をインターネットゲートウェイ(`igw-`)に向けるようにルートテーブルを設定する
<img width="602" alt="スクリーンショット 2019-11-09 20.47.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191739/488b14d5-caa5-7201-78fe-8c9a408ed850.png">


### 仮想プライベートゲートウェイ
- VPCとVPN、Direct Connectを接続するためのゲートウェイ

### NATゲートウェイ
- インターネットから通信されたくないインスタンスがインターネットと通信することを実現する（データベースのアップデート、サーバーをプライベートサブネットに置きたい場合など）
- インターネットからの通信は、リクエストした戻りの通信のみ許可する
- パブリックサブネットに配置し、ElasticIPを割り当てる
- リソースのプライベートIPをNATゲートウェイのパブリックIPに変換することでインターネットとの通信を実現する

## セキュリティ
### セキュリティグループ
- インスタンスに適用される(EC2、RDSなど)
- 一つのインスタンスに少なくとも一つのセキュリティグループを紐づける
- デフォルトではインバウンドの通信は全て拒否
- どの通信を許可するかを指定する
- ソース（＝送信元）にはIPアドレスの他に、セキュリティグループを指定することもできる
    - セキュリティグループを指定した場合、送信元のリソースがそのセキュリティグループに紐づいていたら通信を許可する
- ステートフルでセッションを見ているため戻りの通信の許可は不要  

*-例-*  
下図の場合、`0.0.0.0/0`（全ての通信）からのHTTPおよびHTTPS通信を許可している
<img width="795" alt="スクリーンショット 2019-11-09 21.43.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191739/76d21d66-1513-28f1-290d-0359936a6560.png">
下の図の場合、HTTP通信で送信元が`sg-`のIDのセキュリティグループと紐づいている場合に通信を許可する
<img width="771" alt="スクリーンショット 2019-11-09 21.47.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191739/790dafa7-d480-7d88-1fd1-c5daf05dc852.png">





### ネットワークACL
- サブネット単位で適用される
- デフォルトでは全て許可
- ステートレスなので、戻りの通信も明示的に許可する必要がある

## その他

### リージョン、AZ、VPC、サブネットの関係
リージョンをさらに小さく区切った単位がAZ（アベイラビリティゾーン）
VPCをさらに小さく区切った単位がサブネット
VPCはリージョンの中に作成する
サブネットはAZの中に作成する（AZをまたぐことはできない）
*-例-*
![名称未設定ファイル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191739/7dd531a2-5215-39b9-9653-3a1e354ea516.png)


### パブリックサブネットの通信
パブリックサブネットのリソースもプライベートIPアドレスを持っている
VPC内で通信するときはプライベートIPを使っている
インターネットと通信するときはパブリックIPを使っている

## さいごに
ネットワークむずかしい(・ω・｀)
【mac】XAMPP7.3.11環境構築_config.inc.phpの編集＆上書き保存方法

### ＜＜更新日：：2019年11月9日＞＞

config.inc.phpを上書き保存できない問題
---

phpmyadmin よりdatabase権限でパスワードを設定したのち、config.inc.phpのAuthentication typeを変更したい。

```config.inc.php
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = '';
,
,
,
```

ここで初見殺しが発生する。

上書き保存をしようとすると　`Unable to save Permission denied ` となり変更が保存できないケースだ。



解決策
---
結論からいうと、root@debian権限で編集すればOK。
以下、解決策の手順を示す。

1.XAMPP.appから Open Terminalをクリック
![Screenshot 2019-11-09 21.32.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394058/e57f3175-bcc2-120e-d489-680eefe4bc2e.png)


2.開いたterminalにて、Debian用パッケージ管理システムをupdateして、nanoエディタをインストールする

```
root@debian: apt-get update
root@debian: apt-get install nano
```

　　

3.root@debianでterminalが開くので、phpmyadminフォルダに移動。
※XAMPPなのにLAMPPフォルダ内に存在するが気にしない。

```
root@debian:~# cd ../opt/lampp/phpmyadmin
```
　　


4.nano エディタをconfig.inc.phpを開く。

```
root@debian:/opt/lampp/phpmyadmin# nano config.inc.php
```

　　
5. Authentication type のパスワードを変更する。
編集後は、control+x -> Y -> Enter で上書き保存が完了。
※auth_typeをcookieにするとID,password入力になる。 

```config.inc.php
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie';　
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = '{設定したパスワード}';
```

   

最後に
---
壁にぶつかってる人は、おそらくFinderからterminalを開いて`../xampp/volumes/root/phpmyadmin`にてconfig.inc.phpを編集していることが推測される。

macでのXWAMPP環境は、そもそも仮想環境下で動作するのだから起点となる設定ファイルは、`root@debian`権限で行われなくてはならない。

質問サイトでもその前提が説明されていないので、イマイチ質問者と回答者が噛み合っていない事例が多々あった。
　　

質問・不明点・間違いなどがあればご連絡ください。
【Rails】エスケープ処理をControllerで行いたい（XSS対策）


```sample.rb
ERB::Util.h("<form> </form>")
#=> "&lt;form&gt; &lt;/form&gt;"

ERB::Util.html_escape("<form> </form>")
#=> "&lt;form&gt; &lt;/form&gt;"
```
上記の2つは全く同じ動きをします。

##参考
[module ERB::Util](https://docs.ruby-lang.org/ja/latest/class/ERB=3a=3aUtil.html#M_H)
[RailsエンジニアのためのXSS入門](https://qiita.com/toduq/items/b88716bad35865ef2dc9)
初心者によるプログラミング学習ログ 155日目

# 100日チャレンジの155日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

155日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>155日目<br><br>progateのjavascript講座改変アウトプット<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://twitter.com/hashtag/javascript?src=hash&amp;ref_src=twsrc%5Etfw">#javascript</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1192916054441201665?ref_src=twsrc%5Etfw">November 8, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

# 学習したことの一部

```practice.js

//メソッド:インスタンスの動作のようなもの
class Book {
    constructor(title, subtitle, number) {
      this.title = title;
      this.number = number;
      this.subtitle = subtitle;
    }
    
    // booktitle()メソッド追加
    booktitle() {
      console.log("プログラミング本");
    }

    // titlename()メソッド追加
  　titlename() {

      //booktitle()メソッド呼び出し
      this.booktitle();

    　console.log(`題名は${this.title}です`);
    　console.log(`サブタイトルは${this.subtitle}です`);
    　console.log(`巻数は${this.number}巻です`);
   }
  }
  
  const book = new Book("javascript", "初心者向け", 1);
  
  console.log(`タイトル: ${book.title}`);
  console.log(`サブタイトル: ${book.subtitle}`);
  console.log(`ナンバー: ${book.number}`);
  
  
  // bookに対してbooktitleメソッド呼び出し
  //book.booktitle();

// Bookクラスの継承: Novel
class Novel extends Book {
    //getNovelbook()メソッド追加
    getNovelbook() {
        return this.title + this.subtitle;
    }

}
   const novel = new Novel('ruby', '中級者向け', 4);

novel.titlename();

  // title()メソッド呼び出し
  book.titlename();
  
//定数novelsを定義:定数novelに対してgetNovelbookメソッド呼び出し
 const novels = novel.getNovelbook();
 
console.log(`本のタイトルは、${novels}です`);


```
go-redisでSADDした時の挙動

```go
package main
  
import (
        "fmt"
        "time"
        "strconv"
        "github.com/go-redis/redis"
)

func getRedisClient() (*redis.Client) {
        client := redis.NewClient(&redis.Options{
                Addr:     "localhost:6379",
                Password: "", // no password set
                DB:       0,  // use default DB
        })
        return client
}

func main() {
        rc := getRedisClient()
        ts := strconv.Itoa(int(time.Now().Unix()))
        key := "set:"+ts
        ret := rc.SAdd(key, "hoge")
        fmt.Printf("ret1:%v,%v\n", ret.Err(), ret.Val())
        ret = rc.SAdd(key, "hoge")
        fmt.Printf("ret1:%v,%v\n", ret.Err(), ret.Val())
}
```

```sh
$ go run main.go
ret1:<nil>,1
ret1:<nil>,0
```
```sh
127.0.0.1:6379> smembers "set:1573302581"
1) "hoge"
```

* 重複して入れようとしても特にエラーにはならない（当然ではありますが、、
mampでフルパスを書かずにmysqlコマンドを実行する方法

mysqlについて
デフォルトの状態だとmysqlに関する操作をしようと思った際、下記のようにフルパスを指定しなければならない。

```
/Applications/MAMP/Library/bin/mysql -u root -p
```

これでは面倒なのでmysql -u root -pだけでmysqlを起動できるようにしたい。
そのためには「パスを通す」必要がある。

1.パスを通すためにまず下記のコマンドで.bash_profileを編集する。

```
vi ~/.bash_profile
```

※ ~/はホームディレクトリを表している。.bash_profileはホームディレクトリ直下にある。
※.bash_profileがない場合は上記のコマンドで新規作成できる。

2.viエディタが開いたらiキーを押しインサート(書き込み)モードにして下記を入力する。

```
export PATH=$PATH:/Applications/MAMP/Library/bin
```

※環境変数PATHに/Applications/MAMP/Library/binを追加するという意味の記述。
※環境変数というPC固有の値があり、PCの設定などを記録している。
※上記の記述をする事でターミナルからmysqlコマンドを入力した際、
 PCが/Applications/MAMP/Library/binの中を参照するようになりコマンドが実行可能になる。

3.Escキーを押したのちに:wqを入力しエンターキーを押す。
  そうする事で上記の編集内容を保存してviエディタが終了する。

4.下記のコマンドを実行して設定を更新する。

```
source ~/.bash_profile
```


5.下記のコマンドを実行すれば現在設定されているパスを確認できる。

```
printenv PATH
```

結果例

```
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/sampletarou/.composer/vendor/bin:/usr/local/pgsql/bin/:/Applications/MAMP/Library/bin
```

それぞれのパスは:で区切られている。
先ほど入力した/Applications/MAMP/Library/binが追加されていれば設定完了。
下記のようにフルパスを書かずにmysqlコマンドが実行出来る。

```
mysql -u root -p
```
Bundlerの1系と2系って何が違うの？

Bundlerのバージョンの違いについて、本家の[Bundler 2.0のリリースアナウンス](https://bundler.io/blog/2019/01/03/announcing-bundler-2.html)をもとに簡単に調査してみた。

# Bundler2系の変更リスト

- Ruby2.3より前のバージョンのサポートを廃止
- RubyGem3.0.0より前のバージョンのサポートを廃止
  - [こっち](https://bundler.io/guides/bundler_2_upgrade.html)だとRubyGems2.5.0以上でなければならないと書いてある...どっちだ？
- githubからgemのソースを取得する際に`https`でアクセスするように(1系は`http`だった模様)
- Errorとwarningが`STDERR`に出力されるように
- Bundlerバージョンの自動切り替え
  - `bundle install`実行の際、アプリのGemfile.lockに書かれたBundlerのバージョン(`bundle install`した時に記録される。`BUNDLED WITH`セクションに書かれる)に基づいて自動で適切なBundlerのバージョンに切り替える。アプリ内ディレクトリで`bundler -v`を実行した時はこのバージョンが表示される。

Gemfile.lockに書かれたBundlerのバージョンは例えば以下のような感じ

```
$ grep -A 1 "BUNDLED WITH" Gemfile.lock
BUNDLED WITH
   1.17.1
```

# 以下変更に関連する補足など

### Bundler1系でインストールしたアプリを2系に上げたい時

Bundlerのバージョンを上げて`bundle install`しても、BundlerはGemfile.lockに書かれたBundlerのバージョンでインストールしようとする。
そんな時、アプリのBundlerのバージョンを上げたい場合は、2系をインストールした上で下記を実行する。

※実行前にコミットやバックアップをお忘れなく！

```
bundle update --bundler
```

1系から2系へのバージョンアップ時に出力される実行結果

```
$ grep -A 1 "BUNDLED WITH" Gemfile.lock
BUNDLED WITH
   1.17.3

$ bundle update --bundler
...
Bundle updated!

$ grep -A 1 "BUNDLED WITH" Gemfile.lock
BUNDLED WITH
   2.0.1
```

### なぜRubyGem3.0.0以上のバージョンでなければならないか
変更リストで挙げた「Bundler1系2系の自動切り替え」をスムーズに行うためにRubyGems3系から導入された機能を使っていることが理由らしい。

### 今後のバージョンアップについて
Bundlerのコア開発チームは1年毎にメジャーバージョンのアップデートを目指している模様。
Bundler開発チームはBundler1系で作られたアプリが動き続けるべきであるという考えのようで、上記「Bundler1系2系の自動切り替え」のような仕組みを今後のBundler3、4のリリースの際も採用する予定とのこと。
※メモ※【Laravel5.5】compact関数

`compact関数`について忘れがちなのでメモ。

Controllerからviewへ変数を受け渡す時に使うのが`compact関数`である。

では以下に例を簡単に記述

```Controller/testController.php
public finction test() {

  $test = hogehoge;

  return view('test',compact('test')); //'test'はviewに変数$testを渡す。
}
```

`'test'はviewに変数$testを渡す。` についてだが

```test.blade.php
Controllerから送られてきた変数$testは以下の様な形で記述する。
<p>{{ $test }}</p>
```

はい、以上！

他には`withメソッド`もあるけど、割愛。
Nginx sudo権限付与

# 概要
わけあってNginxユーザーにsudo実行権限付与、およびsudo実行時のパスワード入力を回避する必要があったのでメモです
(当然ですがセキュリティに充分注意すること)

# 権限付与
sudoの動作設定は`/etc/sudoer`に記述されています
**ただしviで編集で編集してはいけません、必ずsudoersファイル編集専用コマンド`visudo`コマンドを使い編集して下さい**
viで編集し記述を謝るとsudoが正常に動作しなくなる可能性がありますがvisudoコマンドの場合、構文ミス等ある場合エラーを吐いてくれます。

visudoコマンドを叩き以下を追加します
(ユーザーnginxに対しsudoで全てのコマンドを実行できるようにする場合)

```
nginx ALL=(ALL:ALL)
```

# パスワード回避
無事nginxにsudo実行権限を付与できましたが
sudo実行時にパスワードを要求されます
パスワードを表示しないようにしたい場合再度visudoでsudoerファイルを開き対象ユーザーの設定にNOPASSWDを設定します
以下一例です

```
nginx ALL=(ALL:ALL) NOPASSWD: /bin/ls
```
これはnginxユーザーが`ls`コマンドをsudo実行する際、パスワードを問いませんよ、という意味です
必要に応じて以下のように対象コマンドを記述しましょう

```
nginx ALL=(ALL:ALL) NOPASSWD: /bin/ls, /bin/cp, 
```
dbpediaの研究 その28

#概要

dbpediaが難解なので、手出してみる。
perlで、取得してみた。

#サンプルコード


```
use Encode;
use HTTP::Request::Common;
use LWP;
 
my $uri = "http://ja.dbpedia.org/sparql";
my $params = ["query" => "SELECT DISTINCT * WHERE { dbpedia-ja:デ・トマソ dbpedia-owl:abstract ?abstract .}"];
my $ua = LWP::UserAgent->new();
my $res = $ua->request(POST($uri, $params));
print $res->content;
  
  
```

#成果物

https://paiza.io/projects/ZL1LOUrXUmi6lESbqxRBuA

以上。
SikuliXのエラー対応

#SikuliXのエラー対応
SikuliXを使って1ヶ月、デバック時に躓いたエラーの対応をしたことを記録として残す

## SikuliXを実行しても画面の操作をしない
SikuliXを管理者として立ち上げていない可能性が高いです
管理者としてSikuliXを起動しましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265588/bddb736c-d2f5-eba5-22f0-7fe36526140b.png)

## ループ処理ではまったとき
"altキーとshiftキーとcキー"で止まる

参考
Sikuliの永久ループを止める方法
https://qiita.com/imtnd/items/fb2abaeed2d738599815
Pythonの便利メソッドなど

#はじめに
Pythonは広く普及しており、開発者は多い。
一番の特徴はシンプルさだと思います。
例えば、hello worldを出力するのはただ一行でできるのです。ほかの言語ではなかなかできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/2966d15e-2d7e-5ded-c621-d5fe3bc65cfe.png)

出典：https://www.benfrederickson.com/ranking-programming-languages-by-github-users/

#hello worldを出力
```python
print("hello world!")
```
#計算の便利さ
```python
print(2 * 3)  //掛け算
print(2 ** 3) //べき乗

print(22 / 7) //小数あり
print(22 // 7) //整数
```
>6
8
3.142857142857143
3

#変数値交換
Go言語と同じく、temp変数不要で直接交換できます。

```python
a = 10
b = 20
a, b = b, a
print(a)
print(b)
```

フィボナッチ数列を求める例：

```python
def fib(n):
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a + b
    print()

fib(900)
```
>0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610


#文字で連結できるjoinメソッド
```python
color = ["red", "green", "blue"]
print(" ".join(color))
```
>red green blue

指定文字列で配列のデータを簡単に連結できます。LOOPも不要で便利です。

#文字列の反転
```python
k8s = "kubernates"
print(k8s[::-1])
```
>setanrebuk

メソッドを呼ぶ必要もありません。

#配列の反転
文字列の反転よりは、配列の反転に使う場面が多いでしょう。

```python
alphas = ["a", "b", "c", "d"]
print(alphas[::-1])
```
>['d', 'c', 'b', 'a']

文字列反転の場合と同じ書き方です。

#配列の重複値の排除
```python
numbers = [4, 3, 2, 1, 1, 2, 3, 4]
print(list(set(numbers)))
```
>[1, 2, 3, 4]

#範囲比較
JAVAでは 6歳以上、18歳以下を判断したい場合、`if (6 <= age && age <= 18) {}`のように二つの計算式が必要です。
範囲判断はできません。Pythonなら、できます。

```python
age = 10
if (6 <= age <= 18) :
    print("学生です。")
```
>学生です。

一目でロジックがわかるので、便利ですね。

#for else
elseはifと一緒に使うと思うでしょうが、Pythonなら、forと一緒に使うこともできます。

```python
for i in range(5):
    print(i)
else:
    print("LOOP完了")
```
>0
1
2
3
4
LOOP完了

ちょっと違和感があるかもしれません、Pythonならではの構文です。
これだけでは使い道はあまりないように見えますが、breakと一緒に使う場面で有用性が発揮されます。
breakでloopが中止される場合に、elseの処理は実行されません。

```python
for i in range(5):
    if i > 3:
        break
    
    print(i)
else:
    print("LOOP完了")
```

>0
1
2
3

#辞書のgetでデフォルト値設定可能
```python
user = {"lastName": "田中"}
print(user.get("firstName", "〇〇"))
```
>〇〇

このような場合に，わざわざ値を取得した後、存在するかどうかの判断をする必要はないので便利です。

#辞書のキーでソート
辞書のキーでソートする処理もよくあります。

```python
user = {"userName": "田中", 
    "address3": "3",  
    "address2": "2", 
    "address1": "1" }
print(user)

print(sorted(user.items(), key = lambda x: x[1]))
```
>{'userName': '田中', 'address3': '3', 'address2': '2', 'address1': '1'}
[('address1', '1'), ('address2', '2'), ('address3', '3'), ('userName', '田中')]

sortedメソッドを使って辞書のキーでソートした配列が生成されます。
これを使う場面は少なくはないでしょう。

#enumerate関数
```python
fruits = ['バナナ', 'リンゴ', 'みかん']
print(list(enumerate(fruits)))
```
>[(0, 'バナナ'), (1, 'リンゴ'), (2, 'みかん')]
番号を付けることができます。




簡単に数種類の操作をまとめました。

Pythonではほかにもいろいろな便利メソッド、モジュールがあります。

https://www.python.org/

以上
dbpediaの研究 その27

#概要

dbpediaが難解なので、手出してみる。
phpで、取得してみた。

#サンプルコード


```
<?php
    $url = 'http://ja.dbpedia.org/sparql';
    $data = array("query" => "SELECT DISTINCT * WHERE { dbpedia-ja:デ・トマソ dbpedia-owl:abstract ?abstract .}");
    $data = http_build_query($data, "", "&");
    $header = array("Content-Type: application/x-www-form-urlencoded");
    $context = array(
        "http" => array(
            "method"  => "POST",
            "header"  => implode("\r\n", $header),
            "content" => $data
        )
    );
    $html = file_get_contents($url, false, stream_context_create($context));
    echo $html;
?>
```

#成果物

https://paiza.io/projects/6unFToTXHrVS6CqxCmtVfg?language=php

以上。
rails 発展その5　カラムの追加　単語の区切り　文字数制限

細かい知識を得たので投稿します。

## カラムの追加

```bash:ターミナル
  $ rails g migration AddIntroductionToテーブル名 追加したいカラム名:データ形式
例
  $ rails g migration AddIntroductionToItems introduction:string

  マイグレーションファイルが作成されるので

　$ rake db:migrate
```

## スネークケースとキャメルケース
プログラムが単語の区切りを認識する際、2通りの方法があります。
スネークケースは、例えば「sample_yes_no」のように「_」で単語を区切る方法です。
キャメルケースは、「SampleYesNo」のように単語の頭文字を大文字にすることで単語を区切ります。

## inputのヘルパーメソッド　text_field:maxlengthオプション
inputの文字数制限を起こすオプションです。

```html:html
<div >
    <%= f.text_field :name, autofocus: true, maxlength: "6" %>
</div>
<!--これで文字数が6文字制限になります。-->
```
空文字判定とnil判定について


nil判定と空文字判定について学習する機会があったので備忘録としてここに記す。

# 空文字判定
空文字の判定をする際に今までは

```swift
if qiita == ""
```
と上記のようにコードを書いていてこちらでも可。
だが、スマートではないのでこれより

```swift
if qiita.isEmpty
```
と書いていく所存。


# nil判定

nil判定するよりnilなんて取得するなよ！
と思う方もいると思いますが、そのあたりはご愛嬌ということで。。。

```swift

if qiita == nil
if qiita != nil
```
自分で書いていてスマートじゃないな・・・と感じるのでよりスマートな
nil判定方法があれば教えて欲しいです。

今回の閉めの言葉
**isEmptyでnil判定はできないぞ気を付けろ！**
【Nuxt.js】Nuxt本体 & 内蔵Vueバージョン確認メモ

# Nuxtバージョン確認

```bash
$ npx nuxt -v
@nuxt/cli v2.8.1
```
# Nuxt内 Vueバージョン確認
コマンドでバージョンを表示する方法は見つからなかったが、package-lock.jsonの中を見ると特定できました。
![image-20190805162200042.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136980/e20884df-c245-30a6-295d-f9c8c90fae6b.png)
【WKWebView】UserAgentの取得方法

```swift:
var webView: WKWebView? = WKWebView() 
webView.evaluateJavaScript("navigator.userAgent") { (userAgent, error) in
  // nilを代入しておかないと、errorが代入されuserAgentがnilになってしまう
  webView = nil 
  print(userAgent)
}
```
【Swift】@escaping属性のクロージャとは

# この投稿は何？
Swiftにおけるクロージャには、いくつかの属性を指定できます。
その１つに`@escaping`がありますが、これについて調査したことを覚書として投稿します。
※ [Swift Language Guide](https://docs.swift.org/swift-book/LanguageGuide/Closures.html#ID546)より

> Swiftを基礎から学ぶには
自著、工学社より発売中の「[まるごと分かるSwiftプログラミング](https://amzn.asia/d/7YPWJwl)」をお勧めします。変数、関数、フロー制御構文、データ構造はもちろん、構造体からクロージャ、エクステンション、プロトコル、クロージャまでを基礎からわかりやすく解説しています。
> また、Swiftプログラミングを基礎から動画で学びたい方には、Udemyコース「[今日からはじめるプログラミング](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwii1qTuj_2BAxV4hlYBHbj5BqEQFnoECBYQAQ&url=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fstart-programming-today%2F&usg=AOvVaw2vs4Sccq-bpfA4ZD2rCyNm&opi=89978449)」をお勧めします。

## 実行環境
- macOS X 10.15.1 Catalina
- Xcode 11.2

# クロージャをエスケープする

## クロージャをエスケープする例
エスケープクロージャのよくある例として、非同期処理をする完了ハンドラとしてのクロージャがあります。
関数に渡されたハンドラは、開始すると再び関数に戻ります。
ただし、そのクロージャがいつ呼び出されるかは決まっておらず、実際にはハンドラ完了後です。
関数の実行が完了した後にクロージャを呼び出すためには、エスケープしておく必要があります。

## `@escapeing`属性を記述する
クロージャは、関数に引数として渡されたとき「関数をエスケープ」できます。
エスケープしたクロージャは、関数に戻った後でも呼び出し可能です。
エスケープクロージャを定義するには、関数の引数宣言でクロージャに`@escaping`を記述します。
クロージャをエスケープさせるには、関数の外側で定義された変数に割り当てます。
 
````swift:クロージャをエスケープする
// 関数のスコープ外に定義した変数 
var completionHandlers: [() -> Void] = []

// 完了ハンドラとしてエスケープクロージャを受け取る関数
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    // クロージャをスコープ外の変数に割り当てる
    completionHandlers.append(completionHandler)
} 
````

`someFunctionWithEscapingClosure(_:)`関数は、クロージャを引数として受け取ります。 
受け取ったクロージャはすぐに実行せず、関数の外側で宣言された配列に追加しています。 
この関数のパラメータを`@escaping`でマークしなかった場合、コンパイルエラーが発生します。スコープの外側に割り当てているからです。

一方、次の`someFunctionWithNonescapingClosure(:)`関数は、クロージャを引数として受け取るものの、エスケープしていません。
ボディでは、受け取ったクロージャをその場で実行するだけです。

````Swift:エスケープしないクロージャを受け取る関数
func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}
````

以下のコードでは、`someFunctionWithEscapingClosure(_:)`はエスケープクロージャを受け取ります。 
対照的に、`someFunctionWithNonescapingClosure(_:)`はエスケープしないクロージャを受け取ります。
 
````Swift:インスタンスメソッドから呼び出す
class SomeClass {
    var x = 10
    func doSomething() {
        // エスケープしたクロージャなので、selfを明示してプロパティを参照
        someFunctionWithEscapingClosure { self.x = 100 }
    }
    func doAnotherSomething() {
        someFunctionWithNonescapingClosure { x = 200 }
    }
}
````
なお、`@escaping`でクロージャをマークすると、クロージャ内では自身を明示的に参照する必要があることに注意します。
このクラスのインスタンスからメソッドを実行します。

````Swift
let instance = SomeClass()
instance.doSomething()  // completionHanders配列にハンドラを追加しただけ.
print(instance.x)       // xは10のまま.

completionHandlers.first?() // 追加したハンドラが実行されて xが100になる.
print(instance.x)    // prints 100
````
`completionHandlers`配列に追加されたクロージャを呼び出すことで、`x`の値が`100`になります。

````Swift:
instance.doAnotherSomething()
print(instance.x)    // prints 200
````
一方で、エスケープしていないクロージャは、インスタンスメソッド実行時に`x`の値に`200`を割り当てています。

# こんな風に理解した
「クロージャをエスケープする」とはつまり、__元の関数との繋がりを断ち切ること__という感じに理解できるかもしれません。
「やること（クロージャ）だけを決めておいて、いつやるかは後で決める」と理解しました。
Salesforceのコードレビュー観点

# コードレビュー観点
- 仕様と実装があっているか
**例**：詳細設計書のイベントの実行部がそれぞれあるか
    つながりが変なことになってないか

- ガバナ制約について
**例**：Limit
    ForループないでSelect飛ばしてないか

- エラー処理
**例**：適切なエラー確認が行われているか
    ありえないエラーまで書いてないか

- スパゲティコード対策
**例**：同じようなコードが複数個所にないか
    不要なコード・紛らわしいコードがないか

- 可読性について
**例**：コメントがただしいか
    メソッド名・変数名
「gem update --system」と「gem update」の違い

- `gem update --system`
  - RubyGems(gemコマンド)自体のバージョンアップをする
- `gem update`
  - インストールされている各gemのバージョンアップをする
  - `gem update [GEMNAME]`で特定のgemをバージョンアップすることもできる

こういうの意外と一発でググれなくて困る...

他にもプレリリース版のgemにアップデートしたりするオプションなど色々ある模様
https://guides.rubygems.org/command-reference/#gem-update
製薬企業研究者がPythonにおける変数についてまとめてみた

# はじめに
ここでは、Python初心者向けに、「変数」について解説します。
Python3系の使用を前提とします。

# 変数の定義

変数を定義する際には「変数名 = 値」という書き方をします。
このとき、=（イコール）は左辺と右辺が「等しい」という意味ではなく、左辺と右辺を「等しくする」つまり左辺に右辺を代入するといった意味になります。
'='の前後はスペースがあってもなくても良いですが、見やすくするため半角スペースを入れるのが慣習になっています。

```python:variable_1.py
var_str = 'Hello, World!'
var_int = 123
var_bool = True
```

変数名には、半角英数字、アンダースコア（'_'）が使えます。
Python3では全角文字も使えますが、あまり使う機会はないでしょう。
変数名が2単語以上になる場合はアンダースコアでつなぐのが一般的です。 どんな値が格納されているのか、誰が見てもすぐに分かるような変数名をつけるようにします。
ただし、変数名を予約語（既にPython内部で定義されている単語）にしたり、先頭を数字にしたりしてはいけません。

```python:variable_2.py
print = 'Hello, World!' # この時点でエラーは出ないが、print関数を実行するとエラーが出る。
1num = 123 # エラーになる。
```

上記のprintの例については、少し難しい書き方をすると、printというオブジェクトが元々は関数だったのに変数に置き換えられて、関数としては実行できなくなる、というイメージになります。

下に書きますが、変数は値を更新することができます。
一方で、値を更新しないことを前提として変数（定数）を定義する場合は、変数名を全て大文字にしておくと、値の更新がない定数であることが分かりやすくなります。

```python:constant.py
CONST = '定数' # 仕様上値を更新することはできる。
```


# 変数の値の参照

変数名をprint関数の引数に指定することで、値を参照することができます。

```python:variable_3.py
var_str = 'Hello, World!'
print(var_str)

var_int = 123
print(var_int)

var_bool = True
print(var_bool)

print('var_str') # var_strと出力される。
```

変数名をクォーテーションで囲んでしまうと、変数の値ではなく、変数名そのものの文字列として出力されてしまうので、注意が必要です。


# 変数の値の更新

既に定義されている変数に対して「変数名 = 値」とすることで、変数の値を更新することができます。

```python:variable_4.py
var = 'Hello, World!'
print(var) # 定義
var = 'Hello, Python!'
print(var) # 更新
```

# まとめ

ここでは、Pythonにおける変数について解説しました。
色々な場面で使うものなので、実際にスクリプトを書きながら理解を深めると良いと思います。

# 参考資料・リンク

[プログラミング言語Pythonとは？AIや機械学習に使える？](https://pharma-engineer.com/basic-programming/python-summary/)
MacでInternetExplorerを見るときの設定【2019年版】


会社の事務作業とかでWindowsマシンじゃないとできない作業とかありますよね

特にレガシーなIEでしか動きませんというアプリを動かす時に詰まったので

備忘録として記載

### やりたいこと：MacでIEでしか見れないサイトを見たい！

### 前提条件

**OS：MacOS Mojave**

**Safariの設定**
Developのメニューはデフォルトでは表示されていないので公式サイトの情報を参考にして設定する。

[Mac の Safari で「開発」メニューのデベロッパツールを使用する - Apple サポート](https://support.apple.com/ja-jp/guide/safari/sfri20948/12.0/mac/10.14)

-----

## 設定手順

### ユーザーエージェントの変更手順

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/5b58fba8-a730-c6e2-22fb-d74784c395f3.png)
図1 Develop（開発）のメニューからOtherを選択した画面

Develop（開発）のメニューからOtherを選択

図2のように表示されていることを確認する。

Otherで表示されるデフォルト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/7c322dd7-1422-df03-845e-9b0654fafaab.png)
図2 Otherデフォルト表示画面

図2の情報を図3で示されているユーザーエージェント情報に変更する。

Other変更後表示画面されているユーザーエージェント情報
`Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/313014c7-ab6d-0d78-ab6f-12b29c090cb5.png)
図3 Other変更後表示画面

この状態でOKボタンを押して変更を反映する。

変更はすぐに適応されるため、再起動などは必要ない

## 確認方法


反映されているかを確認したい場合は以下リンクで確認できる

[確認くん](https://www.ugtop.com/spill.shtml)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/9c13cea4-44c1-6be4-c146-c5784215cdf2.png)
図4 確認くん現在のブラウザｰ表示画面

### 参考にしたリンク

[【Internet Explorer for Mac】Macでインターネットエクスプローラを使おう | スマホアプリやiPhone/Androidスマホなどの各種デバイスの使い方・最新情報を紹介するメディアです。](https://appli-world.jp/posts/4650)


#Tips/Technical_notes
Pythonのfromとかimportとか

importについてあまりにも適当に済ませてきたので、
改めて、、

ことの発端は、datetime()という関数を使いたい！という所から始まりました。

（今思うとこの関数が曲者だった・・・）

```python
import datetime
```

**しかーし！！**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518137/7d9f6016-cfb9-2798-177b-f1a303cc5c18.png)

なんでや！！！！

と思い調べてみました。

```python
from datetime import datetime

myDate = datetime(2017,1,1)
```
これならいけます！！

色んなパターンがあるみたいですが、以下を覚えておけば良さそう

**①import pandas as pd　パターン**

これはPandasモジュールを読み込み、pdという名前で使えるようにする。
Pandasモジュールの中にたくさんの関数があるのですが、(DataFrameとかね)
pd.DataFrame() という形で頭にpdを付ければ使えるようになる。

**②from sklearn.linear_model import LogisticRegressionパターン**

これは、ピンポイントで、sklearn.linear_modelというモジュールの中の、
LogisticRegressionという関数を使えるようにする。
(ほんとはサブモジュールという概念があるらしいけど割愛)
なので、単に、LogisticRegression(iroiro)という形で使える 

scikit-learnのように、そんなに色んな種類の関数をあれこれ使わない場合には、
こっちの方が適しているということでしょう。(逆もまた然り。pd.hoge)

ーーー
以下の記事がめちゃくちゃ詳しかった。
詳しすぎて何が知りたいのか見失いかけるの注意！
https://qiita.com/suzuki-hoge/items/f951d56290617df4279e

ちなみに、黒魔術

```python
from pandas import *
```
というのもあるらしい。
これをすれば、pandasモジュールの中の関数を、接頭語なしで使えるようになります！
便利！
でも、関数名が衝突して良からぬことが起きるので、やめた方が良いらしいです。そう思います。


P.S.
今回ハマるきっかけになった、datetime()は結構ややこしくて、datetimeモジュールの中にdatetimeという関数があるパターンでした。

```python
import datetime
myDate = datetime.datetime(2016,1,1)
```

```python
import datetime as dt
myDate = dt.datetime(2016,1,1)
```

これでもオッケー！
PayPalの定期支払を実装するには

PayPalの定期支払を実装するには、めんどい作業をしましたので、やったことを記録しとっけます。
あくまでも最短ルートにしますので、ご容赦ください。
基礎知識として、PayPalにはSandboxとLive（production）環境があります、事前確認してみてください。

# 定期購読の開始（購読ボタン設置）
- Product（売りたい商品）の作成
- Productに対してPlan（どういうふうに支払う）の作成
- 画面に定期支払ボタンの設定

詳細は
[Basic Integration](https://developer.paypal.com/docs/subscriptions/integrate/)をご参照ください。

# 定期購読の停止（キャンセルボタンを設置）
- 定期購読ボタンのCallbackに定期購読IDが返されるので、それを保存します。
- キャンセルボタンを設置し、定期購読IDを渡すれば、ボタンのイベント処理から[キャンセルAPI](https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_cancel)を呼び出す感じになります。

具体的に、自分でAPIを呼び出すか、[SDK](https://developer.paypal.com/docs/api/rest-sdks/)を利用して呼び出すかとなります。
言語によってキャンセルが実装されたり、されていなっかたりもありますので、適当に足りない部分を既存のSDK共通部分を利用しながら実装できたらよいかと思います。細かくは割愛させて頂きます。

# ユーザーからキャンセルする場合の対応(PayPalの画面から)
- 今回はWebhookでの対応しました。
- IPNでの対応もできますが、今回は、割愛させて頂きます。


自分の場合、複雑のパターンを設計していなくて、基本的に定期支払がキャンセル（Canceled）、一時的（Suspended）の場合、キャンセルされたこととします。詳細は[webhook](https://developer.paypal.com/docs/integration/direct/webhooks/)をご参照ください。
ローカルでテストするには、[ngrok](https://ngrok.com/)を利用した。

# 本番リリース
- https://developer.paypal.com/docs/subscriptions/integrate/#5-go-live
- SDKを利用した場合、SDKのGo liveページを参照（SDKによってsandbox, liveモード, client_idとsecretのスイッチ）
- 本番向けのwebhookの設置

# 課題
- webhookをテストするにはwebhook simulatorを利用しますが、本物ではない、クリックするたびに、イベントが送られる。実際にSandbox環境で定期支払をキャンセルしでもイベントが発生しません。
- webhookは、本番環境でテストしたところ、ユーザーからキャンセルされた場合、イベントが発生しますが、管理者側からキャンセルされた場合、イベント発生しません。
- 自分中の疑問ですが、結構一般的によくあるニーズなのに、これらを実装、テストまでには結構時間が掛かりました、なぜPayPalにはこんな難しい仕様としているんだろう。

# 参考資料
https://qiita.com/PPJP/items/1668c546a2c09f840819
jenkinsのmaster/slave間のSSH接続でjavaがないと言われた時の対処法(docker)

#経緯
この書籍に沿ってjenkinsコンテナを立ち上げました。

[Docker/Kubernetes 実践コンテナ開発入門(山田 明憲)](https://www.amazon.co.jp/dp/4297100339)

本の通りに進めているとエラーが出てしまったので、備忘録として書きます。

#エラーの内容
masterコンテナを立ち上げる時のimageに書籍通りに**jenkinsci/jenkis：2.142-slim**を指定すると、
プラグインのインストールでエラーが出ました。それは下記の記事で対処法を記載くださっていたので解決しました。
[dockerでjenkins構築（plugin install errorを出さない）](https://qiita.com/_ainosh_/items/04992adbab8502e2ed9e)

私の場合はslaveとSSH接続をさせる時に
下記エラーが出て、SSH接続が成功しませんでした。

```
java.io.IOException: Java not found on hudson.slaves.SlaveComputer@....... Install a Java 8 version on the Agent.
............
............
............
............

```

このエラーはjava8がありません、インストールしてくださいって言われているんですが、
そもそもjavaを探す場所が間違っていて起きていました。


#解決法
まずdockerのslaveコンテナ内でjavaが格納されているディレクトリを調べる必要があります。
下記コマンドを実行します。

```bash
##コンテナの中のbashに入ります
$docker exec -it slave01 bash

##コンテナ内でjavaがどこに入っているか調べます
root@[CONTAINER ID]#which jave
```

上記を実行して出力されたディレクトリを
jenkins上のノード設定画面で指定します
![スクリーンショット 2019-11-09 19.58.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317237/b1901293-16f6-e0aa-24fa-dc7c6718065d.png)


赤枠の「高度な設定」を押すと、**javaのパス**という項目が存在するので、そこに出力されたディレクトリを入力することで、エラーなくなります。
![スクリーンショット 2019-11-09 19.47.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317237/63a29494-fc34-966b-c5bd-2c2dcb47456d.png)


コンテナ内の環境変数にはJAVA_HOMEは設定されてますが、ノード設定画面で指定しないとダメなようでした。

#終わりに
docker起因というより、jenkins起因のエラーだったため、jenkins知ってたらもっと簡単だったなと思いました。
書籍はとっても分かりやすいので、改訂版を出して欲しい、、、
dbpediaの研究 その26

#概要

dbpediaが難解なので、手出してみる。
goで、取得してみた。

#サンプルコード


```
package main
import (
    "fmt"
    "io/ioutil"
    "net/http"
    "log"
    "net/url"
    "strings"
)
func main() {
    values := url.Values{}
	values.Add("query", "SELECT DISTINCT * WHERE { dbpedia-ja:デ・トマソ dbpedia-owl:abstract ?abstract .}")
	values.Encode()
	res, err := http.PostForm("http://ja.dbpedia.org/sparql", values)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("[status] %d\n", res.StatusCode)
	for k, v := range res.Header {
		fmt.Print("[header] " + k)
		fmt.Println(": " + strings.Join(v, ","))
	}
	defer res.Body.Close()
	body, error := ioutil.ReadAll(res.Body)
	if error != nil {
		log.Fatal(error)
	}
	fmt.Println("[body] " + string(body))
    fmt.Println("XXXXXXXX")
}

```

#成果物

https://paiza.io/projects/hO4YrlkZY1HU9RKj34H2AQ


以上。
学習用

#演算子の優先順位

上から順に優先度が高くなってくる（！の上にもまだ存在する）

```
高い  !
　　  &&
　　  ||
　　  not
　　  = (+=, -= ...)
低い  and or
```

例）<font color="red">**!,not**</font> と <font color="red">**||**</font> の関係性
　　<font color="red">**!**</font> の方が <font color="red">**||**</font> より優先度が高いので、3行目は <font color="blue">**true**</font> となる
　　<font color="red">**||**</font> の方が <font color="red">**not**</font> より優先度が高いので、4行目は <font color="blue">**false**</font> となる

```Ruby
a = true
b = false
!a || b       #=> true
not a || b    #=> false
```
※and や or は条件分岐で使うのではなく、制御フローを扱うのに向いている

# 条件演算子（三項演算子）
if文での記述

```Ruby
a = 5

if a > 1
  '1より大きい'
else
  '1以下'
end

#=> "1より大きい"
```
上記のコードを条件演算子に書き直すことができる
<font color="DeepSkyBlue">**式 ？ 真だった場合の処理 : 偽だった場合の処理**</font>

```Ruby
a = 5

a > 1 ? '1より大きい' : '1以下'

#=> "1より大きい"
```
さらに、条件分岐した結果を変数に代入することもできる

```Ruby
a = 5

number = a > 1 ? '1より大きい' : '1以下'

number #=> "1より大きい"
```
Googleが提供するドメイン「.new」が便利らしい

#はじめに
こんにちは、アドベントカレンダー18日目担当の避雷です。流石にネタ切れ感が半端なくなってますね、助けて。
大学同期のドチャクソ優秀なプログラマ氏がGoogleの「.newが良い」という話をしていたので、どんなもんよと調べてみたら結構便利そうだったのでまとめてみます。
#簡単に言うと…
- .newとはアクセスすることで新しいドキュメントやらスプレッドシートやらリポジトリやらを生成することができるURLである。
- `サービス名`.new というリンクになっていてクリックすると対象のサービスに飛んでデータを新規作成する
- Google直下のサービス以外にも提携する様々なサービス上にデータを新規生成することができる。

#実際にどんな感じの物が使えるの？
各種Googleサービスで用いることができます。例えば

| 　URL 　| 　対象サービス 　|　 挙動 　|
|:-----------------|:------------------|:------------------|
| https://doc.new/ | Googleドキュメント| 新規ドキュメントを生成する |
| https://sheet.new/ | Googleスプレッドシート | 新しいシートを作る |
| https://slide.new/ | Googleスライド | 新規スライドを作成する |
| https://form.new/ | Googleフォーム | 新しいアンケートフォームを作る |
| https://cal.new/ | Googleカレンダー | 新しいイベントを自分のカレンダーに作成する |

Google外のサービスでも利用できるものがあります。試しにクリックしてみるとわかりますが、通常のようにウェブページから「新規作成」ボタンを押したときと同じような感じで白紙のデータが表示されます。
https://blog.google/outreach-initiatives/entrepreneurs/shortcuts-made-possible-new/
にて紹介されているものを見てみましょう。

| 　URL 　| 　対象サービス 　|　 挙動 　|
|:-----------------|:------------------|:------------------|
| https://playlist.new/ | Spotify | 新規プレイリストを生成する |
| https://story.new/ | Medium | 新しい記事ページを作る |
| https://canva.new/ | Canva | 新規ポスター・バナーを作成する |
| https://webex.new/ | Cicso Webex | 新しい会議室を作る |
| https://link.new/ | Bitly | 新規URLを作る |
| https://invoice.new/ | Stripe Dashboard | 新規invoices(請求書)を作成する |
| https://api.new/ | Node.JS | RunKitを使って新しいwebAPIのプロトタイプを作成する |
| https://coda.new/ | coda | 新規Docを作る。ドキュメントやスプレッドシートをまとめられる |
| https://music.new/ | OVO | 新しくCDのジャケ絵を作る |

因みにmusic.newにアクセスするとこんなジャケ絵が作れる。
![nocryin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256231/03715d36-1651-d876-0e21-4bfead0f3fad.png)
既存の曲のジャケットでジェネレータみたく遊べるらしい。この画像はNo Cryinという曲のジャケットです。人によって対象の楽曲が違ったりするのかも、使い道は分かりませんが色々遊べそうですねコレ。
https://music.apple.com/jp/album/no-cryin-feat-future-single/1482433401?app=music

#終わりに
.newドメインを使うことで外部APIを利用することなく、新規ツールへのリンクを作れるのはWebサービス系のエンジニア的にはちょっとありがたいのではないでしょうか？
Googleは今後も対応サービスを増やしていくみたいでなので、他サービスとの連携がちょっと楽になるかもしれません。
micro:bit Pythonでプログラミング

# 概要
micro:bitをPythonでプログラミングする方法についてのメモ

# micro:bitにプログラミングする方法
micro:bitへのプログラミング方法は公式のサイトで２種類の方法が提供されています。

１つはMakeCodeエディターと呼ばれるドラッグアンドドロップできるブロックを使用したGUIベースのプログラミング方法で、子供がプログラミングをはじめる場合にはこちらがオススメだと思います。ただ、日本語で使う場合は漢字に振り仮名などはついていないので、小さいお子様の場合は一掃のこと英語でやってしまった方が将来的には良いかもしれません。

https://makecode.microbit.org/

もう１つは`Python Editor for micro:bit`を使ってPythonでプログラミングする方法。

https://python.microbit.org/v/2.0

いずれもブラウザ上で操作するツールとなっていますが、ファイルをアップロードすることもできるので、Pythonの場合はローカルで編集して、ファイルをアップロードしたものを使うという方法の方が使い勝手が良いかもしれません。

また、`Python Editor for micro:bit`では、micro:bitにプログラムデータを書き込む（Flash）する際にWebUSBという方法でmicro:bitと接続するようなのですが、このWebUSBはブラウザがChromeでないと対応できないようです。

# Hello world
micro:bitのhello worldはこんな感じです。

```Python
from microbit import *
while True:
    display.scroll('Hello, World!')
```
これをmicro:bitに書き込むと、micro:bitの5x5のLED上に'Hello, World!'の文字が流れていきます。
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">micro:bitでhello world <a href="https://t.co/i07dfSk6km">pic.twitter.com/i07dfSk6km</a></p>&mdash; 齋藤浩司 (@3J5RVmyfPFjARcq) <a href="https://twitter.com/3J5RVmyfPFjARcq/status/1193128374866071552?ref_src=twsrc%5Etfw">November 9, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

micro:bitへの書き込みは、PCとmicro:bitをmicroUSBケーブルで接続し、
1. エディタ左上の`Connect`をクリック
2. micro:bitと繋がったら、`Flash`をクリック
で完了です。
簡単ですね。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Python Editor for micro:bit でmicro:bitへの書き込み（Flash） <a href="https://t.co/swqIu408rH">pic.twitter.com/swqIu408rH</a></p>&mdash; 齋藤浩司 (@3J5RVmyfPFjARcq) <a href="https://twitter.com/3J5RVmyfPFjARcq/status/1193131761225482240?ref_src=twsrc%5Etfw">November 9, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Jetson XavierでGPUのメモリ使用率表示

`nvidia-smi`がXavierにはないらしい。(Jetson Nanoとかにもないのかな？)
いちおう`sudo ~/.tegrastats`でもできるけどわかりづらいのでメモ。

##gtopのインストール
Xavier用にforkしてくれた人のレポジトリをクローンしてmakeするだけ。

```terminal
$ sudo apt-get install libncurses5-dev libncursesw5-dev
$ git clone https://github.com/MI-LA01/gtop
$ cd gtop
$ make
$ sudo cp gtop /bin/gtop
$ sudo gtop
```

##表示例
こんな感じです。
![Screenshot from 2019-11-09 19-56-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208979/fbdff560-07b2-f7ce-eaf7-5845220fad19.png)
karabiner-elements×尊師スタイル 装飾キーの設定つまりどころ

# tl;dr
- karabiner-elementsで尊師スタイル設定をしたが装飾キーの設定箇所で詰まった。
- 設定する際は使用しているキーボードではなく `Karabiner VirtualHIDKeyboard` を選択なおして設定する必要がある。

※尊師スタイルに関して詳細は[MacBookPro で HHKB 尊師スタイル - Qiita](https://qiita.com/midorinokimi/items/8da9f234e96f1fa0f9e0)が世界で一番わかりやすいです。雑に言うとlaptop版Macの付属キーボードを使用せずに自分の好きなキーボードを使う方法です。

# 設定方法
キーボードの装飾キーに関しては `設定 app > キーボード > キーボードタブの右下の装飾キー` で設定できます。

設定したはずなのにうまく反映しない場合は、以下の `キーボードを選択` 種類を確認してほしい。

![スクリーンショット 2019-11-09 19.30.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171564/75729e4c-5241-15ec-1a37-1743a601c2a1.png)

ちょっと分かりづらいが、karabiner-elementsの場合は `Karabiner VirtualHIDKeyboard` を選択した上で各種キーを設定する必要がある。

![スクリーンショット 2019-11-09 19.30.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171564/cf633490-1acc-0044-928b-301c07513080.png)

# おまけ
karabiner-elementsで外部キーボードが接続しているときは内部キーボードをdisableにする設定も少し探したのでメモ。設定自体はかんたんで、 `Devices > Advanced` でチェックボックスを入れれば良い。
![外部キーボードが接続しているときは内部キーボードをdisableにする説明画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171564/663acab2-2ad2-c269-5d8f-280a8249d4fe.png)

勝手にdisableにしてくれるのでめっちゃ快適。おすすめの設定です。

happy hacking!
Windows10 1709 Fall Creator Update以降のSMB v1.0有効化

## SMB 1.0有効化の背景
Windows10 1709 Fall Creator Updateより、Windowsファイル共通に使われる通信プロトコルの古いバージョンSMB v1.0が無効化されました。

[Windows 10 Fall Creators Update と Windows Server バージョン 1709 以降のバージョンの既定では SMBv1 はインストールされません](https://support.microsoft.com/ja-jp/help/4034314/smbv1-is-not-installed-by-default-in-windows "Windows のサポート")

重要度の低いファイルを保存した一部の古いNASが、SMB v1.0を利用しているようで、Windows10の大型アップデートを適用した端末がファイルサーバーへ繋がらないという症状が出たことがきっかけで気づきました。
ping自体は通るので、初めは原因が分からずおかしいなぁと思っていました。
本来ならば、NAS側のソフトウェアまたはファームウェアをSMB v2.02以降の新しいバージョンをサポートする更新プログラムで対応するのですが、古いNASの場合はメーカー側もそこまでサポートしてくれない場合もありますので、今回はクライアントPC側のプロコトルバージョンを下げて対応してみます。

## SMB v1.0を利用する際のリスク
SMB v1.0の利用については、Microsoftより
>重要: SMBv1 を再インストールしないことを強くお勧めします。 この古いプロトコルには、ランサムウェアや他のマルウェアに関する既知のセキュリティの問題があります。

と前述した[リンク](https://support.microsoft.com/ja-jp/help/4034314/smbv1-is-not-installed-by-default-in-windows)先に案内が出ています。
十分に注意してご利用ください。


## 操作方法
まずはGUIで再有効化してみましょう。
### SMB 1.0/CIFS ファイル共有のサポート（GUI）

1. [コントロール パネル] を開き、[プログラム] をクリックし、次に [Windows の機能の有効化または無効化] をクリックします。
1. Windows の設定画面で [SMB1.0/CIFS ファイル共有のサポート] の項目を展開し、[SMB1.0/CIFS クライアント] のチェックボックスを “オン” にし、[OK] をクリックしてウィンドウを閉じます。
<dl>
  <dt>[ ]SMB1.0/CIFS ファイル共有のサポート</dt>
  <dd>[×]SMB1.0/CIFS クライアント</dd>
  <dd>[ ]SMB1.0/CIFS サーバー</dd>
  <dd>[ ]SMB1.0/CIFS 自動削除</dd>
</dl>
※バージョンによって自動削除が実装されていない場合があります。
1. コンピューターを再起動します。

### SMB 1.0/CIFS ファイル共有のサポート（コマンド）
動作確認検証環境：Windows10 Pro 1903 64bit
キッティング作業など、コマンドやバッチを実行して設定したい場合もありますよね。
コマンドプロンプト、またはPowerShellに実装されたDISMコマンド（展開イメージのサービスと管理ツールコマンド）を利用、管理者権限で実行します。

```visualbasic:EnableFeaturesSMB1Client.bat
echo SMB 1.0/CIFS ファイル共有のサポート：有効化
dism /online /Enable-Feature /FeatureName:SMB1Protocol /NoRestart
rem echo SMB 1.0/CIFS クライアント：無効化
rem ※今回はクライアントPCでSMBv1を利用するためコメントアウト化。
rem dism /online /Enable-Feature /FeatureName:SMB1Protocol-Client /NoRestart
echo SMB 1.0/CIFS サーバー：無効化
dism /online /Disable-Feature /FeatureName:SMB1Protocol-Server /NoRestart
echo SMB 1.0/CIFS 自動削除：無効化　バージョンによって自動削除が実装されていない場合があります。
dism /online /Disable-Feature /FeatureName:SMB1Protocol-Deprecation /NoRestart
echo このあとPCを再起動してください。
PAUSE
```

一旦、SMB 1.0/CIFSに関するものを全てオンにしてから不要なものをオフにするのがミソですね。
［超初心者向け］初期状態のMacBookAir(2019)でGitを使うには

# 1.背景
ソースコードが散らかりまくっているため、整理のためにGit、GitHub、SouceTreeを使うことにしました。
（SouceTreeは、取っ掛かりの練習のため）

# 2.環境
#### 前提条件

1. GitHubアカウント登録済み
2. SouceTreeインストール済み

#### 私の所持しているMac

- MacBook Air（Retina, 13inch, 2019）
- メモリ：16 GB

# 3.Gitのバージョンを確認してみる
開発自体が手探りなもんで、まずGitを使いたいなあと思い立ち
ターミナルを立ち上げてGitのversionを調べると、以下のエラーが。

```
$ git --version
xcode-select: note: no developer tools were found at '/Applications/Xcode.app', requesting install. 
Choose an option in the dialog to download the command line developer tools.
```

Xcode　と　コマンドライン・デベロッパ・ツール　をインストールしなさいよ、と怒られました。

そのあとは、自動的に開発ツールのダウンロードとインストールが始まるので
暫く待つばかり。

ダウンロードが終わったら、Gitのversionを確認します。

```
$ git --version
git version 2.21.0 (Apple Git-122)
```

あっさり終わりました。

調べたところ、現状の[Gitの最新バージョン](https://git-scm.com/)が 2.24.0 だったので、ついでに
最新版をインストールしておきます。
![19.11.090-gitvsn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529339/901c0b6b-2639-8238-7609-452161f05858.png)



# 4.HomeBrewをインストールして、Gitを最新バージョンに更新する
HomeBrewとは、macOS用のパッケージマネージャーのことです。
[こちら](https://brew.sh/index_ja.html)を見てインストールしました。
HomeBrewの説明については、以下の記事がとても参考になります。

>[homebrewとは何者か。仕組みについて調べてみた](https://qiita.com/omega999/items/6f65217b81ad3fffe7e6)

HomeBrewがインストールされたら、早速Gitをインストール。

```
$ brew install git
```

インストールが終わったら、Gitのバージョンを確認してみます。

```
$ git --version
git version 2.24.0
```

無事、最新バージョンに更新されています！

2019年9月から初めてMacを使い始め、ようやく3ヶ月になりました。
今まではWindows一筋でしたが、直感的に操作できるMacの使い心地は最高ですね。
もう虜です。
dbpediaの研究 その25

#概要

dbpediaが難解なので、手出してみる。
javaで、取得してみた。

#サンプルコード


```
import java.util.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

public class Main {
     public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try 
        {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
            connection.connect();
            Map<String, List<String>> map = connection.getHeaderFields();
            for (String key : map.keySet()) 
            {
                System.out.println(key + "--->" + map.get(key));
            }
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) 
            {
                result += line;
            }
        } 
        catch (Exception e) 
        {
            System.out.println("err！" + e);
            e.printStackTrace();
        }
        finally 
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (Exception e2)
            {
                e2.printStackTrace();
            }
        }
        return result;
    }
    public static void main(String[] args) throws Exception {
        Main httpTest = new Main();
        String query = "query=" + URLEncoder.encode("SELECT DISTINCT * WHERE { dbpedia-ja:デ・トマソ dbpedia-owl:abstract ?abstract .}", "UTF-8");
        System.out.println(httpTest.sendGet("http://ja.dbpedia.org/sparql", query));
    }
}




```


#成果物

https://paiza.io/projects/f2-WNirCplt9PQAH3XeK4g


以上。
MavenのデフォルトJDKのバージョンは1.5

# はじめに
Javaで個人的に遊んでいたところ、ちょっとはまったことがあった。
割と基本的なことなのかもしれないけど、知らかなったので備忘録的に記載しておく。
（資格で得た知識が多いからこういう実践的なところが結構抜けてるんだよなぁ・・・）


# 発生した事象
Maven の project update を実行すると、JDK 1.5 でコンパイルされるため、JDK 1.6 以降の構文で記載したプログラムはコンパイルエラーになる。

以下、詳細。

事前の状態。
JRE System Library が 1.8 に設定されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254168/92ab5bb7-dcbd-da15-9e2b-8955f7e1cc1e.png)

右クリック⇒Maven⇒Update Project を実行
（またはAlt＋F5）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254168/590346ea-6916-6a8c-0464-ddf7152befaf.png)



JRE System Library が 1.5 に変更されてしまう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254168/4a582d02-109c-2915-af1a-b3bc6cc70dde.png)

1.5 なので、1.7 から導入された try-with-resources はコンパイルエラー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254168/1d9ccbf9-b230-09bf-4eae-ec5020bcfc8a.png)

ダイヤモンド演算子が導入されたのも1.7からなので、コンパイルエラー
（右辺にも型を明示するかJRE 1.7にしろと言われている）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254168/f45bcd11-35b1-8614-114a-d3d4f7b79080.png)


# 調べてみた
以下のサイトを見たところ、Mavenプロジェクトのデフォルトのコンパイラバージョンが1.5になっていることが原因らしい。

・[MavenでJDKのバージョンを指定する方法【JDK1.5 -> 1.8】](https://reasonable-code.com/maven-jdk-version/)
・[Maven：コンパイラのバージョン設定](https://web-dev.hatenablog.com/entry/maven/java-version-setting)
・[Setting the -source and -target of the Java Compiler](https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html)

# 対応策
[Apache Mavenのサイト](https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html)に書いてあることを参考に、pom.xmlを修正。
こうすることでJREのバージョンを指定することができる。
やり方は以下の①と②があるけど、今回は①を実施。

### ①project properties にて source と target に 1.8 を指定

今回は1.8を指定。

```xml:pom.xml
  <properties>
    ・・・
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    ・・・
  </properties>

```

### ② plugin directly で source と target に 1.8 を指定

今回はこっちの書き方をしていないが、これでも行けるらしい。

```xml:pom.xml
<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
    [...]
  </build>
  [...]
</project>
```

# 対策後に確認

上記①（又は②）の修正をした後、再度、右クリック⇒Maven⇒Update Project を実行
（またはAlt＋F5）
⇒JRE System Library が 1.8になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254168/785a9b8f-162f-324c-2606-7df3128ed4e9.png)

try-with-resourcesのコンパイルエラーが解消されていることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254168/3bc5061f-8a40-85f3-4be7-7644c7e576d1.png)

ダイヤモンド演算子のコンパイルエラーも解消。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254168/04b643b1-aff4-345e-e268-b9b423753569.png)


以上。
Flutterで作ったweb app をGithub Pagesにデプロイする

#下準備
##まずは最新版にする。
なにせflutter_webは正式サポートではないので、最新でないと動くかどうかもわからない。devのほうがよいというタイミングすらあります。

```
flutter channel master
flutter upgrade 
```

##web機能を有効化します

```
flutter config --enable-web
```

##flutterプロジェクトのテンプレ状態を作成します。
自分で作成したプロジェクトディレクトリに移動して、flutterプロジェクトのテンプレ状態を作成します。
現在、動作テストできる環境はchromeのみです
※注：すでに存在するiOSやAndoroid用のプロジェクトをwebで使おうとする場合には、それ用のマニュアルがあるそうなので、そちらを参照してください。

```
cd <あなたのプロジェクトディレクトリ>
flutter create .
```


##デフォルトの画面がchrome上に出てくるはずです

```
flutter run -d chrome
```

##web用のビルドを行います
```
flutter build web
```

##ビルド結果はこの位置にできます
プロジェクトフォルダの直下にbuildその中にwebができているはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173892/18a518cc-9949-e0ad-0200-6bac9dbde0bc.png)

#Githubにデプロイ
##ログインしてレポジトリ作成
https://github.com/
にログインしてレポジトリを作成します。このとき、username.github.io の用になるようにしてください。
GitHub Pagesについての細かい話は公式を参照ください。https://pages.github.com/

私が作成する場合（すでに作った後なので警告が出ている）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173892/8d6fbb9e-66f9-a58a-b1cd-871ebd03da53.png)

##web公開するものを配置するディレクトリを作る
空っぽで構いません。とりあえずローカルにディレクトリを作ります。
ディレクトリを作成したら、そのディレクトリにデプロイ先をクローンします。
多分なにもないか、README.MDがあるかくらいだと思います。

```
cd <web公開するものを配置するディレクトリ>
git clone https://github.com/ClozedJP/ClozedJP.github.io.git
```

##クローンしたレポジトリのフォルダ内に公開したい内容を配置
buildフォルダ内のwebのフォルダごと投入します。
このときにwebのフォルダの名前を自分のプロジェクトの名前などに変更しておくと後でわかりやすいかもしれませんね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173892/3609ddf6-1936-3725-8452-d5a0ee7b696d.png)

##配置した内容をpushする
配置した内容をGithub側にプッシュします。
※注：Github Desktopなどでpushする人もいると思いますので、その場合はGithub Desktopでpushしてください。

```
git add --all
git commit -m "Initial commit"
git push -u origin master
```


##Github側の状態を確認する
私がデプロイした先はこんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173892/8c13903d-ef81-2e83-390b-37e98174f30e.png)

デプロイしたWeb App のURLは

```
https://username.github.io/フォルダ名
```

私の作成したappの動作状態はこちら。みなさんのURLも似たような形になると思います。
https://clozedjp.github.io/adventure/
指定したURLのリンクが有効かどうかをチェックするpythonスクリプトを作成


# 目的
指定したURLのリンク先が有効かどうかをチェックするpythonスクリプトを作成したので備忘録です

# コード

###確認対象がURL１つの場合

以下を参考にさせて頂きました。（一部python3.0用に修正）
> [PythonでURLが存在しているか確認](https://qiita.com/fantm21/items/6996a4f681c53a1338e8)

```python:sample.py
#-*- using:utf-8 -*-
import urllib.request, urllib.error

def checkURL(url):
    try:
        f = urllib.request.urlopen(url)
        print ("OK:" + url )
        f.close()
    except:
        print ("NotFound:" + url)

if __name__ == '__main__':
    url = "http://qiita.com/"
    checkURL(url)
```

実行結果

```
$ python sample.py
OK:http://qiita.com/

$ python sample.py
NotFound:http://nonenonenonenone.com
```

###確認対象がURL２つ以上の場合

ファイルから複数行のURLを入力すれば良い

```python:sample2.py
#-*- using:utf-8 -*-
import urllib.request, urllib.error

def checkURL(url):
    try:
        f = urllib.request.urlopen(url)
        print ("OK:" + url )
        f.close()
    except:
        print ("NotFound:" + url)

if __name__ == '__main__':

    with open("./input.txt") as f:
        for line in f:
            # print(line, end='')
            checkURL(line)
```

実行結果

```
$ cat input.txt 
http://qiita.com/
$ python sample2.py
OK:http://qiita.com/
```


# CodingError対策

```
ImportError: No module named 'urllib2'
```

下記について、

```
import urllib2
```

python3.0系では以下と書く必要がある。

```
import urllib.request, urllib.error
```

# 参考
[【Python/urllib】URLが存在しているか確認](https://algorithm.joho.info/programming/python/urllib-check-url/)
[Pythonで指定したURLにファイルが存在するかを調べる方法](https://toolmania.info/post-12806/)
[PythonでURLの有無、存在をチェックするスクリプト](https://blog.s-giken.net/318.html)
[PythonでURLが存在しているか確認](https://qiita.com/fantm21/items/6996a4f681c53a1338e8)
[python のModule urllib2 を利用する方法を教えて下さい](https://teratail.com/questions/47744)
[Pythonでファイルから一行ずつ読み込み](https://qiita.com/tortuepin/items/d74e5b75dde93d877e6b)