OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】scikit-learnで単・重回帰分析

scikit-learnでの単・重回帰分析の実装方法を紹介する。

```python
# sklearn.linear_model.LinearRegression クラスを読み込み
from sklearn import linear_model
import pandas as pd
import numpy as npy
import matplotlib.pyplot as plt
import numpy as np
import requests
import io

clf = linear_model.LinearRegression()

url = 'http://pythondatascience.plavox.info/wp-content/uploads/2016/07/winequality-red.csv'
res = requests.get(url)
df = pd.read_csv(io.BytesIO(res.content), sep=";")
df.to_csv('winequality-red.csv', index=False)

print('データ確認')
wine = pd.read_csv("winequality-red.csv")
print(wine.head())
print('\n')
 
print('単回帰')
# 説明変数に "density (濃度)" を利用
X = wine.loc[:, ['density']].values
print(X)
# 目的変数に "alcohol (アルコール度数)" を利用
Y = wine['alcohol'].values
print(Y)
# 予測モデルを作成
clf.fit(X, Y)
# 回帰係数
print('回帰係数\n',clf.coef_)
# 切片 (誤差)
print('切片\n',clf.intercept_)
# 決定係数
print('決定係数\n',clf.score(X, Y))
print('回帰式\n','[alcohol] = %s × [density] + %s'%(clf.coef_[0], clf.intercept_))
# 散布図
plt.scatter(X, Y)
# 回帰直線
plt.plot(X, clf.predict(X))
plt.show()
print('\n')

print('重回帰\n')
wine_except_quality = wine.drop("quality", axis=1)
X = wine_except_quality.values
print(X)
Y = wine['quality'].values
print(Y)
# 予測モデルを作成
clf.fit(X, Y)

# 偏回帰係数
print('回帰係数\n',pd.DataFrame({"Name":wine_except_quality.columns,
                    "Coefficients":clf.coef_}).sort_values(by='Coefficients'))
parameters = pd.DataFrame({"Name":wine_except_quality.columns,"Coefficients":clf.coef_}).sort_values(by='Coefficients')
print(parameters['Coefficients'].values)
pval = parameters['Coefficients'].values
# 切片 (誤差)
print('切片\n',clf.intercept_)
print('回帰式\n','[quality] = %s × [density] + %s × [chlorides] +\
                 %s × [volatile acidity] + %s × [pH] + \
                 %s × [citric acid] + %s × [total sulfur dioxide] + \
                 %s × [free sulfur dioxide] + %s × [residual sugar] + \
                 %s × [fixed acidity] + %s × [alcohol] + \
                 %s × [sulphates] + %s'\
                    %(pval[0],pval[1],pval[2],pval[3],pval[4],pval[5],pval[6],pval[7],pval[8],pval[9],pval[10], clf.intercept_))
print('\n')
```
## まとめ
今回は、scikit-learnでの単・重回帰分析の実装方法を紹介した。
Postmanを使ってLaravelのバリデーションエラーをJSONで返す

# 概要
Postmanを使ってLaravelのAPIを確認。
入力データをバリデートしてエラーが吐き出される想定が、トップページが返ってきた。

# 対策
Headerに以下を付け加える
- KEY : X-Requested-With
- VALUE : XMLHttpRequest

LaravelはXHRリクエスト時に バリデーションエラーをJSONでレスポンスする。
PostmanでXHRを表現するためには、上記のヘッダーを付け加える必要がある。

# 感想
x-www-form-urlencodedなどで送信すれば勝手にXHRになると勘違いしていたが、勘違いもいいところだった。
以前にも勘違いしていて、Postmanを整理している時にヘッダーもリセットしていて、間違いに気づけなかった。。
普段から初歩的な間違いはすぐ気づけるようにしているつもりが、たまに数時間気付けないことがある。。
どうにかならないものか。。
【Swift】アクセス修飾子【リファクタリング】

# はじめに
こんにちは。プログラミング歴1年、エンジニア志望の学生です。
最近、昔作ったiOSアプリのコードのリファクタリングをしています。というのも、プログラミングを始めた頃はコードの可読性とか全く意識せずに書いていたので、見返してみると「うわぁ...🫠」となるようなぐちゃぐちゃなコードだらけでした。
GWというまとまった休みが来たので、これを機に一気に見直そう！と思った次第です。

# 概要
Swiftにおいて、アクセス修飾子の仕方を知る

# 結論
* なるべくアクセス範囲が狭くなるような修飾子を設定する

# アクセス修飾子の種類
詳しくは以下の記事をご覧ください。
https://qiita.com/mototaji/items/d1ae68457a118df71458

# private
`private`は、これを付けた変数・メソッドがクラス内でのみ使用可能となる修飾子です。
例えば、次の`isSetTaskShow`は`ContentView.swift`のみでしか使いません。

```swift:ContentView.swift
@State var isSetTaskShow = false
```
特にこのままでもプログラムは動きますが、`private`を付けることで「この変数はContentViewでしか使われない」と明示的に表現することができます。
```swift:ContentView.swift
@State private var isSetTaskShow = false
```
# private(set)
`private(set)`は、`private`のアクセス範囲を少し広げたようなもので、書き込み(set)には`private`を、読み込み(get)には後述する`internal`と同じアクセス権限を与えます。つまり、参照するのは外部からできるけど、変更は同じクラス内でしかできないと言うことです。

# internal
`internal`は、修飾子を付けなかった場合にデフォルトで設定される修飾子です。同一のターゲット内であれば呼び出せます。
ターゲットとは、プロジェクトの構成単位であり、複数のファイルやリソースをまとめたものです。

正確には、同一のターゲット内ではなく同一のモジュール内らしいのですが、ここで書くと長くなってしまうので、また別の記事で書きたいと思います。

# public
`public`は、クラス、モジュール関係なくどこからでもアクセスできるようになる修飾子です。
ターゲットが同一でなくても呼び出すことができます。
アクセス範囲が広がるので便利ですが、予期せぬタイミングで呼び出されたり、プログラムが終了するまでメモリが確保されてしまう(無駄が多くなる)ため、安易に付けるのはやめましょう。

# アクセス範囲の設定
[Cookpadさんのコーディング規約](https://github.com/cookpad/styleguide/blob/master/swift.ja.md)を見てみると、

>[MUST] 最もスコープが狭くなるようにアクセスレベルを設定すること
[MUST] 外部から読み込めるが、書き込ませたくないプロパティにはprivate(set)を明示すること
[MUST] プロパティの属性としてweakを使える場所では使うこと
・@IBOutletやデリゲートなど、循環参照が発生しうる箇所に付与すること

とあります。`weak`についてはまた今度記事にしようと思います。
なるべくスコープ(アクセス範囲)を狭くすることで、コードの可読性や保守性が向上すると言うことですね。
AWS Glue データカタログ（暗号化済み）へのクロスアカウントアクセスを試してみた

# 背景・目的
[こちらの記事](https://qiita.com/zumax/items/cbe75c5dee757c7720c1)でGlueデータカタログへのアクセスを試しましたが、提供側のメタ情報を暗号化した場合に、そのままだとアクセスできません。
本記事では、メタ情報を暗号化しクロスアカウントアクセスする方法を試してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a8207f24-aa46-95f9-dc5e-0b15796f6d49.png)

# まとめ
暗号化したデータカタログにクロスアカウントアクセスするには、Customer managed keyを作成し、キーポリシーのPrincipalを指定します。

# 概要
## Data Catalog の暗号化
こちらの[Data Catalog の暗号化](https://docs.aws.amazon.com/ja_jp/glue/latest/dg/encrypt-glue-data-catalog.html)を元に整理します。
暗号化されるオブジェクトは、下記のとおりです。
- データベース
- テーブル
- パーティション
- テーブルのバージョン
- Connect
- ユーザ定義関数

暗号化に使用できる鍵は、下記のとおりです。このうち、AWS managed keyについてはクロスアカウントアクセスできないため、Customer managed keyを使用します。
- AWS managed key
- Customer managed key

# 実践
## KMSキーの作成
1. 下記を設定し、「次へ」をクリックします。
    - キーのタイプ：対象
    - キーの使用：暗号化および複合化
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/6a3a7062-532b-95a2-df76-4c33e0ce425c.png)

1. エイリアスを指定し、「次へ」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/46ea5035-5ec9-7a8b-f0db-06729b550f0b.png)

1. 管理者の設定等を設定し作成します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/996e30bd-7a16-41bc-ba98-b981a1501bd2.png)

## Glue Data catalog settings
1. Encryption optionsで「Metadata encryption」をチェックし、先ほど作成したCustomer managed keyを指定し、「Save」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/8e1eccb4-2e33-b18e-aefc-1ea95a4426fc.png)

## KMSのキーポリシーを修正
1. このままでは、クロスアカウントでアクセスができません。下記はAthenaのクエリエディタを参照した際のエラーです。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/df78e619-a9c9-2ee6-d6c7-17c65b00ecbb.png)

1. キーポリシーに、複合のために「kms:Decrypt」を追加します。
    ```
    {
        "Sid": "Enable IAM User Permissions",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::{アカウントB}:root"
        },
        "Action": "kms:Decrypt",
        "Resource": "arn:aws:kms:{リージョン名}:{アカウントA}:key/{キーID}"
    }
    ```

## クロスアカウント（アカウントB）のAthenaで確認
1. 確認できました。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a57e6b6b-fee6-ec2b-a623-18905992282e.png)

# 考察
今回、暗号化済みデータカタログへのクロスアカウントでアクセスする方法を試しました。このようなケースは、多々あるかと思いますので、忘れないようにメモとして残しておきます。

# 参考
https://qiita.com/zumax/items/cbe75c5dee757c7720c1

https://docs.aws.amazon.com/ja_jp/glue/latest/dg/encrypt-glue-data-catalog.html

https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk
AWSで開発環境構築 #4（環境の削除）

# 目的

https://qiita.com/kanerin1004/items/cdb1b8354efe98d6aa15

これの続き！
今日は今まで作ったやつを1回削除します。


# 今回やること

今回の目標は以下の4つ。
* EC2インスタンスの終了
* NATゲートウェイの削除
* Elastic IPの開放
* VPCの削除


# 環境
* windows 10


# いざ出陣

## EC2インスタンスの終了

1. EC2ダッシュボードの左のメニューから、「インスタンス」を選択する。
1. 作成したインスタンスを選択する。
1. 「インスタンスの状態」から「インスタンスを終了」をクリックします。
1. 確認モーダルが表示されるため、「終了」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/16953994-99f7-19ec-8bdf-539bd6af6b27.png)

 ↓ このようになればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/004e8b18-f283-bb0e-d73c-5cc567637560.png)


## NATゲートウェイの削除

1. VPCダッシュボードの左のメニューから、「NAT ゲートウェイ」を選択する。
1. 作成したNAT ゲートウェイを選択する。
1. 「アクション」から「NAT ゲートウェイを削除」をクリックします。
1. 確認モーダルが表示されるため、フィールドに「削除」と入力し「削除」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/ab1607b4-9c4d-3032-c3d9-7887d69c1f91.png)

 ↓ このようになればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/6961fd31-9612-2b6c-b743-b5c94952ef92.png)


## Elastic IPの開放

1. VPCダッシュボードの左のメニューから、「Elastic IP」を選択する。
1. 割り当てられたElastic IPを選択する。
1. 「アクション」から「Elastic IP アドレスの解放」をクリックします。
1. 確認モーダルが表示されるため、「解放」をクリックします。

 ↓ このようになればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/d30524cf-dfbf-8031-8a16-7007576f3972.png)


## VPCの削除

1. VPCダッシュボードの左のメニューから、「お使いの VPC」を選択する。
1. 作成したVPCを選択する。
1. 「アクション」から「VPC の削除」をクリックします。
1. 確認モーダルが表示されるため、フィールドに「削除」と入力し「削除」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/0c9f4511-1608-dd40-3a66-9afdd90355ed.png)

 ↓ このようになればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/dfd8a1ea-e40f-4f4b-e27f-8236398f44bc.png)


# 余談
作るの大変だったのに、消すの簡単だね。
何かみたい。例えは出てこないが。
WSL2 容量不足によるエラーを解消

# やりたいこと
WSL2でのLinux環境において、容量不足が原因のエラーを解決したい

例えば、
Docker使用時 stable-diffusion-webui-dockerを実行する時に発生する以下のエラーはWSL2の容量不足によるものです

`webui-docker-auto-1 exited with code 137`


## やること
**.wslconfig**ファイルを作成して、ファイル内にWSL2に関する設定を記述する。




## .wslconfigファイルの作成
以下のパスにファイルを作成してください
`C:\Users\[ユーザ名]\.wslconfig`

## WSLに関する設定の記述
テキストファイルなどを用いて.wslconfig内に設定を記述します。
今回の場合はメモリ容量を追加したいので以下のように記述してください。
<pre>
[wsl2]
memory=12GB  
</pre>  
  
  

あとはWSL2を再起動すれば設定が反映されます。
エラーが解決しなかった場合は12GBでも容量が足りないか、
容量以外の原因があると思われます。
RubyでAtCoder ABC300(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC300のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - N-choice question
https://atcoder.jp/contests/abc300/tasks/abc300_a
```ruby:a-300.rb
n, a, b = gets.split.map(&:to_i)
c = gets.split.map(&:to_i)
puts c.index(a + b) + 1
```

# B - Same Map in the RPG World
https://atcoder.jp/contests/abc300/tasks/abc300_b
```diff_ruby:b-300.rb
h, w = gets.split.map(&:to_i)
array_a = Array.new(h){ gets.chomp }
array_b = Array.new(h){ gets.chomp }
h.times do |s|
    w.times do |t|
        flag = true
        h.times do |i|
            w.times do |j|
-               flag = false if array_a[(i - s + h) % h][(j - t + w) % w] != array_b[i][j]
+               flag = false if array_a[(i - s) % h][(j - t) % w] != array_b[i][j]
            end
        end
        if flag
            puts "Yes"
            exit
        end
    end
end
puts "No"
```
## 解説
（公式解説を参考にしました）

(s, t)をそれぞれ0<=s<=h, 0<=t<=wの範囲で全探索していきます。このとき、配列Aを縦方向にs回シフト、横方向にt回シフトすると、A[i][j]はA[(i-s+h) % h][(j-t+w) % w]となります。そして、シフト後のAがBと一致していればYesを出力して終了、最後まで一致するものがなければNoを出力しましす。

# C - Cross
https://atcoder.jp/contests/abc300/tasks/abc300_c
```ruby:c-300.rb
h, w = gets.split.map(&:to_i)
array = Array.new(h){ gets.chomp.chars.map{ |i| i == "#"} }
n = [h, w].min

ans = Array.new(n, 0)
h.times do |i|
    w.times do |j|
        next unless array[i][j]
        d = 1
        while 0 <= i - d && i + d < h &&
              0 <= j - d && j + d < w &&
              array[i + d][j + d] && array[i + d][j - d] &&
              array[i - d][j + d] && array[i - d][j - d]

            d += 1
        end
        ans[d - 2] += 1 if d != 1
    end
end
puts ans.join(" ")
```
## 解説
（公式解説と他の方の提出結果を参考にしました）

すべてのバツ印は中央にサイズ１のバツ印を含むためdを1で初期化します。また、(i,j)(i+1,j+1)(i+1,j-1)(i-1,j+1)(i-1,j+1)すべてが`#`なら、バツ印となっているためdをインクリメントします。そして、バツ印でなくなったら、対応するans配列の値をインクリメントします。なお、d-2としているのは、dを1で初期化した分とwhileループの最後の余分な分を除くためです。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
TypeScriptのプロジェクトでTailwindCSSが効かない

# はじめに

TailwindCSSを導入したときにつまづいたのでまとめていきます
公式の導入どおりにやってもうまく適応できないというのが何回か経験したので自分のメモ程度です

# 問題

以下の手順通りにTailwindCSSを導入しました

https://tailwindcss.com/docs/installation

そして試しにCSSを当てましたが以下のように適応されていませんでした

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/bd0e2aea-234e-4f27-5bb6-0f8b760a2040.png)

# 解決方法

公式にはありませんが、以下のファイルを追加したところ解決しました

```
$ touch postcss.config.js
```

```js:postcss.config.js
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};
```

するとうまく適応されました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/de4ab314-c926-6b9d-f1f4-8a6d8beff33c.png)

# おわりに

ChatGPTに助けられました
なぜ公式通りでは動かないのかは謎です。教えてください

# 参考

https://tailwindcss.com/docs/installation
Snowflake 初期設定：⑦SYSADMIN編 データベース作成

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)

### ■本記事の目的
Snowflakeのトライアルおよびご契約後の初期設定を行うため
管理者ロールの段階を理解するため

### ■前回の記事
[Snowflake 初期設定：⑥SYSADMIN編 仮想ウェアハウス作成](
https://qiita.com/taku_tachibana/items/ff8e3f2776aab169b4d4)

### ■今回の作業
SYSADMINでデータベースを作成していきます。
データベースを利用できるロールを割り当てます。

### ■データベースを作成する。
以下のコマンドで作成していきます。
タイムトラベルを行うためのデータ保持期間ですが、ライセンスが「Enterprise Edition」以上
を必要とします。
```
use role SYSADMIN ;
create database TEST_DB
data_retention_time_in_days = 7 --データ保持期間（日数：最大90日）
;
```

### ■データベースの使用権を割り当てる。
作成後は、所有者しかデータベースを使用できないので、
前段で作成したアクセスロールに使用権を割り当てます。
```
use role SYSADMIN ;
grant USAGE on database <データベース> to role <アクセスロール> ;
例
grant USAGE on database TEST_DB to role TEST_ACCESS_SELECT_ROLE ;
grant USAGE on database TEST_DB to role TEST_ACCESS_ALL_ROLE ;
```

### ■あとがき
本記事は、データベースを作成までとします。
次回スキーマ作成を行います。

### ■次の記事
[Snowflake 初期設定：⑧SYSADMIN編 スキーマ作成](https://qiita.com/taku_tachibana/items/477041e4288f3b6cac91)
　
[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)
プロンプト設計における余白の重要性

AIヘルプデスクを作成する際にGPT-3.5-turboを使用したところ、興味深い気づきがありました。AIへの指示において、適度な余白が重要だということです。この記事では、その気づきについて詳しく解説します。

## AIへの指示における余白の重要性

AIへの指示は、過度に厳格にすると柔軟性が失われ、挙動が不自然になることがあります。そのため、絶妙な余白を残すことで、AIがより適切で利口な回答をするようになります。

### 余白がないと起こる問題

- **柔軟性の喪失**：AIへの指示が厳密すぎると、AIが回答の幅を制限され、状況に応じた柔軟な回答ができなくなります。
- **不自然な挙動**：指示が過剰に詳細であると、AIが無理にその条件を満たそうとし、回答が不自然になることがあります。

### 余白を適切に設けることで得られるメリット

- **より適切な回答**：AIに適度な余白を与えることで、状況や文脈に応じた回答が可能になります。
- **利用者に適応**：余白があることで、AIは利用者のニーズや好みに応じて回答を変えることができます。

## まとめ

GPT-3.5-turboを使ったAIヘルプデスクで学んだことは、AIへの指示に適度な余白を設けることが重要だということです。余白を意識することで、AIは柔軟性を保ち、利用者に適応した回答ができるようになります。プログラマーは、AIとのやり取りにおいて、この絶妙なバランスを見つけることが求められます。

**Generated by ChatGPT**
Snowflake 初期設定：⑥SYSADMIN編 仮想ウェアハウス作成

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)

### ■本記事の目的
Snowflakeのトライアルおよびご契約後の初期設定を行うため
管理者ロールの段階を理解するため

### ■前回の記事
[Snowflake 初期設定：⑤SECURITYADMIN編 ユーザーへのロール割当て](
https://qiita.com/taku_tachibana/items/7fb7dc8e2b63c3e9fc72)

### ■今回の作業
SYSADMINでウェアハウスを作成していきます。
ウェアハウス専用ロールに割り当てます。

### ■ウェアハウスを作成する。
以下のコマンドで作成していきます。
単一のスケールでオートスケールもしない設定で作成してみます。
```
use role SYSADMIN ;
create or replace warehouse TEST_WH WITH
warehouse_size = XSMALL --ウェアハウスサイズ
scaling_policy = STANDARD --スケーリングポリシー
enable_query_acceleration = FALSE --ウェアハウス増強
max_cluster_count = 1 --最大クラスタ
min_cluster_count = 1 --最小クラスタ
statement_timeout_in_seconds = 21600 --クエリタイムアウト
auto_resume = TRUE --自動再開
auto_suspend = 60 --自動停止時間　※設定すると自動停止が設定される
initially_suspended = TRUE  --作成初期の一時停止
;
```

### ■ウェアハウスの使用権を割り当てる。
作成後は、所有者しかウェアハウスを使用できないので、
前段で作成したウェアハウス用アクセスロールに使用権を割り当てます。
```
use role SYSADMIN ;
grant usage on warehouse TEST_WH to role <WH用アクセスロール> ;
例
grant usage on warehouse TEST_WH to role TEST_ACCESS_WH_ROLE ;
grant usage on warehouse TEST_WH to role TEST_ACCESS_WH_ROLE ;
```

### ■あとがき
ウェアハウス作成権（CREATE WAREHOUSE）は、下位ロールに許可しない限りは
SYSADMINがウェアハウス作成をすることになるので、
下位ロールに使用権(USAGEなど)を割当てる作業もセットで必要になってきます。

また、DB用途別でのウェアハウスを定義することも必要になります。
リソース使用状況の監視なども視野に入れると、要件に応じたウェアハウス設計が
必要になります。
これもロール設計と同様に図面化してから作成したほうがよさそうです。

### ■次の記事
[Snowflake 初期設定：⑦SYSADMIN編 データベース作成](
https://qiita.com/taku_tachibana/items/171df9a2be79ba4f805f)

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)
フロントエンドのLPIC101合格体験記

こんにちは、私は普段はフロントエンドエンジニアをしています。

サーバーサイドの知識も身につけたいと思い、まずは基本的なLinuxの勉強から始めることにしました。そこで、LPIC（Linux技術者認定試験）の101を受験しようと考えました。
知識ほぼゼロの状態から始めた合格までの体験記をまとめようと思います。

https://www.lpi.org/ja/our-certifications/lpic-1-overview


## 学習期間
結果的に言えば、LPIC101を2回目の受験で合格することができました。知識ほぼゼロの状態から始めたこともあり、学習期間だけをまとめると半年以上かかりました。

## 試験1回目までにやったこと

最初に学習に取り掛かったのは、定番の[あずき本](https://www.shoeisha.co.jp/book/detail/9784798160498)です。あずき本ですが現在はversion5が最新のようです。メルカリなどで安く売られてたりしますが、versionが古かったりするので最新版の購入をおすすめします。

意気揚々と読み始めましたが、本の内容は思ったより難しかったです。1ページ読むのに数時間もかけて進めていくような状態でした。また、LPIC101試験内容は記憶系の問題が多い印象でかなりの量のコマンドを覚える必要があり、それぞれのコマンドに更にオプションが何個もあったりするので覚えるのはかなり辛かったです。

なかなか思うように学習がすすまなかったので、下記のオンラインの動画学習の教材を取り入れてみました。

- [はじめてのLinuxサーバー構築運用入門](https://www.udemy.com/course/learn-basics-of-linux/)
- [もう怖くないLinuxコマンド。](https://www.udemy.com/course/unscared_linux/)
- [【公式】Linux Professional Institute 日本支部 LPI](https://www.youtube.com/@linuxprofessionalinstitute906)
- [LPIC/LinuC(レベル1)試験対策](https://schoo.jp/course/5399)

これらの動画をちょっとずつ見進めていき理解を深めていきました。
個人的には、Schooの「LPIC／LinuC（レベル1）試験対策」の動画が一番わかりやすくとても参考になりました。
動画教材を見つつ、あずき本も少しずつ学習を進めていき3,4ヶ月ぐらいかけ大体の理解できました。
そして、あずき本の問題も解けるようになったのでついに試験を受ることにしました。

結果は不合格。。
試験問題の印象ですが、初めて見る問題であずき本に載っていない内容が数多く出題されていた思います。間違って別の試験を受けているんじゃないのか？と思うほど、初見の問題が多かったです。

## 試験2回目までにやったこと

学習した時間と試験料16,000円ぐらいが無駄になってしまいショック過ぎて一度は心が折れてしまいましたが、しばらく休んでから他の受講者の記事を参考にして教材を変え、もう一度奮起して勉強することにしました。

今回は他の受講者がおすすめしていた[スピードマスター問題集](https://www.shoeisha.co.jp/book/detail/9784798160856)と[Ping-t](https://ping-t.com/)という学習サイトを取り入れてみました。
スピードマスター問題集はその名の通り問題集ですがそれぞれの詳しい解説があります。Ping-tは模擬問題を学習できるサイトで101の問題は無料で使うことができます。
一回目であずき本などを学習していたこともありスピードマスターは割と理解が早かったと思います。しかしあずき本に載っていない内容も多かったです。

今回は上記の2教材をメインに2,3ヶ月ぐらいかけて学習しました。スピードマスターの問題はほぼ記憶しPing-tの擬似問題もいい点数を取れるようになったタイミングで二回目の試験を受けました。
結果的には無事に合格することができました！

## まとめ
LPICの勉強を通じて、サーバーサイドにも触れることができ、自分の知識の幅を広げることができたと思います。
LPIC102も受験しようと思っているので、101を学習した内容の反省点を改めて見直してみました。
RaspberryPi OSでユーザを追加・削除する

# はじめに

RaspberryPi OSでユーザを追加・削除をするためには
各種コマンドをターミナルで実行する必要があります。

### ターミナルを起動する

以下のスクリーンショットのように
ラズベリーパイアイコン > アクセサリ > LXTerminal の順にクリックすることで
ターミナルを起動できます。

<img width="600" alt="ターミナルを起動する" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/8b33cae3-ea0f-b908-5e8a-d417042e74f0.png">

<img width="600" alt="ターミナル" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/0ade6818-c26c-b17b-01b8-c73d3d901082.png">

### ターミナルからコマンドを実行する

起動したターミナルに
以下の各種操作を参考にコマンドをキーボードから入力し、実行してください。

# 各種操作
### ユーザを追加する

```txt:実行コマンド
sudo adduser [ユーザ名]
```

```txt:実行例
sudo adduser narapon
```
<img width="600" alt"ユーザ追加" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/170b2c9f-fbd8-2519-db32-aee9881733d2.png">

### ユーザに管理者権限を与える

```txt:実行コマンド
sudo gpasswd -a [ユーザ名] sudo
```

```txt:実行例
sudo gpasswd -a narapon sudo
```
<img width="600" alt="ユーザに管理者権限を与える" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/621eeccf-966f-e678-7892-f1e340ee4e5d.png">

### ユーザを削除する

```txt:実行コマンド
sudo userdel [ユーザ名]
```

```txt:実行例
sudo userdel narapon
```

<img width="600" alt="ユーザを削除する" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/178849e1-e175-6e5d-ed20-917500d8a12b.png">

※currently used by processと表示され、削除ができない場合はreboot(再起動)してください。
　再起動後は削除するユーザ以外でログインする必要があります。


### 別ユーザでログインする

```txt:実行コマンド
sudo su [ユーザ名]
```

```txt:実行例
sudo su narapon
```

<img width="600" alt="別ユーザでログインする" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/28f1815b-f331-a7ac-bff3-a2fe9d6804d9.png">


### ユーザからログアウトする

```txt:実行コマンド
exit
```

<img width="600" alt="ユーザからログアウトする" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/709b86c4-be4f-7da5-f380-c19c1ed49aeb.png">

# 番外編

### 注意点

・１つでもコマンドに誤りがあるとエラーになります。
・パスワードを忘れてしまうとログインができなくなります。
・一度削除したユーザは元に戻せません。

### 削除したユーザのファイルを削除する

ユーザを削除しても、そのユーザのファイルは削除されません。
以下のコマンドで削除可能ですが一度削除すると元に戻せません。
高度な操作に不安のある方には推奨しません。

```txt:実行コマンド
sudo rm -r /home/[ユーザ名]
```

```txt:実行例
sudo rm -r /home/narapon
```

<img width="600" alt="ユーザファイル削除" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/125840ab-f37d-8b57-1d1f-aeb8c5712032.png">

 ### ユーザのパスワードを変更する

パスワードを変更したいユーザでログインをしてから
以下のコマンドを実行してください。

ターミナルの@以前に記載されてるローマ字がログイン中のユーザ名です。

```txt:実行コマンド
sudo passwd
```

<img width="600" alt="パスワード変更" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289916/0b362dd1-7789-c868-fd2c-3b4424259dea.png">
supabaseでtwitter authする［備忘録］

supabaseの認証をtwitterを用いて行いたかった。

本番で動かすには、DOC通りに行えばすんなり動くのだが、開発環境で認証を通そうとするとリダイレクトに404してしまう。

色々試行錯誤した結果、ローカル環境でのconfig.tomlに記載する設定値が違ったという落ち。

具体的には、config.tomlのclient_idとsecretに渡すIDはdevelopper portalで確認できるclient_idとsecretではなく、Access Token and Secretであった。

設定file内での項目名がclient_idとsecretであったために、惑わされていただけ。

```toml
[auth.external.twitter]
enabled = true
client_id = "env(DEV_TWITTER_CLIENT_ID)" # これがclient_idではなくAPIキー
secret = "env(DEV_TWITTER_SECRET)" # secretでなくAPI Secret Key
```

一応その他設定も晒しておく


```.env.local
# next.js用
NEXT_PUBLIC_SUPABASE_ANON=....
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321/
NEXT_PUBLIC_SUPABASE_REDIRECT_URL=http://localhost:54321/auth/v1/callback
```

```.env.local
# supabase用(supabase/.env.local)
export DEV_TWITTER_CLIENT_ID=...
export DEV_TWITTER_SECRET=...

```
rbenvでRubyのバージョンを上げたらRailsコマンドが効かなくなった

# はじめに
anyenv経由のrbenvでRubyのバージョンを`3.2.1`から`3.2.2`に上げた際にRailsコマンドが効かなくなったので解消するまでを記事として残します。

# 現象
anyenv経由のrbenvでRubyのバージョンを`3.2.1`から`3.2.2`に上げた直後に`rails -v`をすると以下のメッセージが表示された
```zsh
rbenv: rails: command not found

The `rails' command exists in these Ruby versions:
  3.2.1
```
どうやら`3.2.2`のバージョンに　`rails`コマンドが存在しないみたいだ

# 状況確認
`3.2.2`のバージョンがインストールされているRubyのディレクトリまで移動しインストールされているものを確認する

### ディレクトリ確認
私の場合は以下のディレクトリ
```zsh
/Users/ユーザー名/.anyenv/envs/rbenv/versions
```
`ls`コマンドで中身を表示
`3.2.1`と`3.2.2`がインストールされていることが確認取れた
```zsh
3.2.1	3.2.2
```

#### `3.2.1`の中身を確認
`3.2.1`の`bin`に移動し`ls`コマンドを実行
```zsh
_guard-core	faker		pry		rake		sprockets
bootsnap	gem		puma		rbs		thor
bundle		guard		pumactl		rdbg		tilt
bundler		irb		racc		rdoc		typeprof
coderay		listen		rackup		ri
erb		nokogiri	rails		ruby
```
railsが**あること**を確認

#### `3.2.2`の中身を確認
`3.2.1`の`bin`に移動し`ls`コマンドを実行
```zsh
bundle		gem		rake		rdoc		typeprof
bundler		irb		rbs		ri
erb		racc		rdbg		ruby
```
railsが**ないこと**を確認

# 解消
既にグローバルのバージョン指定は`3.2.2`に切り替わっているので以下コマンドを実行
```zsh
gem i rails
```

終了したら`rails -v`でバージョンが表示されるか確認
```zsh
Rails 7.0.4.3
```

念の為`3.2.2`の`bin`ディレクトリに`rails`があるか`ls`コマンドで確認する
```zsh
bundle		irb		rails		rdoc		typeprof
bundler		nokogiri	rake		ri
erb		racc		rbs		ruby
gem		rackup		rdbg		thor
```
`rails`を確認
Snowflake 初期設定：⑤SECURITYADMIN編 ユーザーへのロール割当て

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)

### ■本記事の目的
Snowflakeのトライアルおよびご契約後の初期設定を行うため
管理者ロールの段階を理解するため

### ■前回の記事
[Snowflake 初期設定：④SECURITYADMIN編 ロール階層作成](
https://qiita.com/taku_tachibana/items/4d6895ffcac3edc473e7)

### ■今回の作業
SECURITYADMINでの作業の継続です。
ユーザーにロールを割り当てていきます。

### ■ユーザーにロールを割当てる。
実際に割り当ててみます。
構文は前回行ったロール階層を少し変えるだけです。
```
use role SECURITYADMIN ;
grant role <ロール> to user <ユーザー> ;
例
grant role TEST_FUNCTIONAL_ANALYST_ROLE to user TEST_ANALYST_USER ;
grant role TEST_FUNCTIONAL_DBADMIN_ROLE to user TEST_DBADMIN_USER ;
```

### ■あとがき
割当ては、非常に簡単でしたが、
まだ本筋のDBとウェアハウスを設定していないので、
次回はSYSADMINでの作業を行っていきます。

### ■次の記事
[Snowflake 初期設定：⑥SYSADMIN編 仮想ウェアハウス作成](
https://qiita.com/taku_tachibana/items/ff8e3f2776aab169b4d4)

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)
iOSエンジニアがデータ分析に挑戦！単回帰分析と重回帰分析の基本を解説！

# はじめに

最近はありがたいことに社内で開発以外の分野に挑戦させていただけることが多くなりました:metal:

最近は主に業務内で売上や各種数字からアプリの傾向や売上向上のための施策など分析し、タスクに落とし込む作業に力を入れています:raised_hand:

### そんな中、文系出身の自分がデータ分析の基礎である回帰分析について学んだので、解説してみたいと思います:clap:
(個人開発のアプリの改善や、社内のデータ分析の参考にしていただけると幸いです:bow:)

# 回帰分析とはなんぞや

回帰分析は、2つ以上の変数の関係を分析する統計手法であり、データ分析においてとても有用な手法の1つです！特に
### :point_right:単回帰分析
### :point_right:重回帰分析
は、ビジネスや経済などの分野で広く用いられています。今回は、単回帰分析と重回帰分析について、基本的な概念や手法について解説してみたいと思います!

# 単回帰分析
### 単回帰分析は、1つの説明変数と1つの目的変数の関係を分析する手法です:point_up:

目的変数が説明変数にどのような影響を受けるかを分析することができます！

どういうときに使うの:thinking:
:point_right:　例) 商品の売上高を予測したいとき
商品の価格がその商品の売上高にどのような影響を与えるか分析したときに使えます！

例の場合、価格が説明変数、売上高が目的変数となります！
単回帰分析を行うことで、価格と売上高の関係を直線で表現し、その傾向を分析することができます！:fist:

# 重回帰分析
### 重回帰分析は、2つ以上の説明変数と1つの目的変数の関係を分析する手法です:point_up:

目的変数が複数の説明変数にどのような影響を受けるかを分析することができます!

どういうときに使うの:thinking:
:point_right:　例） 商品の売上高を予測していて、価格だけでなく、広告費や季節性など、複数の要因が売上高に影響することが考えられるとき

この場合、価格、広告費、季節性などが説明変数、売上高が目的変数となります。重回帰分析を行うことで、これらの要因と売上高の関係を直線で表現し、その傾向を分析することができます！:fist:


# 実際にどうやって分析するの？

言葉はわかったけどどうやって分析するの！:unamused:

スプレットシートに目的変数と説明変数を書き出し、「xlminer analysis toolpak」という拡張機能を使うことで表を表示できます！ 
(もっと良い方法があれば教えていただきたいです:bow_tone2:)

※ excelでも可能です！

<img width="300" alt="スクリーンショット 2023-04-30 13.26.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1624020/82a02ab9-0c11-9745-bb89-3724f6d87407.png">

- Input　Y Range：　目的変数
- Input　X Range：　説明変数
- labelsにチェック
- Output Raｎgeに出力したいセル

でOKを押せば表が出来上がります:point_up:


出来上がった表がこちら:point_down:

<img width="400" alt="tech_multivariate_img38.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1624020/e41f0419-da2d-0973-9bea-bd4041eb45a6.jpeg">


着目すべき数字は以下です！:point_down:


## １，決定係数 (重決定R2)

決定係数は、回帰モデルが実データにどれだけ適合しているかを表す指標であり、0から1の値を取ります:point_up:
決定係数が1に近いほど、回帰モデルの予測精度が高いと言えます!

## 2,自由度調整済み決定係数(補正R2)

補正R2は、説明変数の数にも着目したモデルの適合度を評価することができます!:point_up:

どうゆうこと？:thinking:
説明変数を増やせば増やすほど、決定係数は増加する傾向にあります。
説明変数を追加することで決定係数が高くなってしまい、モデルの過剰適合を招いてしまうことがあります:frowning2:

このことを考慮した決定係数が補正R2ということになります:point_up:

## 3,係数　

回帰分析において、係数は説明変数と目的変数の関係性を表す指標です:raised_hand:

単回帰分析では、1つの説明変数が1つの係数に対応します:point_up:
一方、重回帰分析では、複数の説明変数が複数の係数に対応します:point_up:

係数の値は、その説明変数が目的変数に与える影響の大きさを表します:point_left:
具体的には、説明変数が1単位変化した場合に、目的変数がどの程度変化するかを表します!


## 4, t値(t)

t値が大きい場合、回帰係数の推定値が有意であることを示すため、その説明変数が目的変数に対して有意な影響を与えている可能性が高くなります。一方、t値が小さい場合、回帰係数の推定値が有意でないことを示し、説明変数が目的変数に対して有意な影響を与えていない可能性が高くなります。:point_up:

## 5, p-値　

p-値は有意性の判定基準として使用される統計的な指標です！

基本的にP値が0.05以下の時に仮説が有意であるとされます:point_up:

# まとめ

今回は、単回帰分析と重回帰分析について解説してみました！:raised_hand:
回帰分析は、データ分析において非常に有用な手法の1つであり、ビジネスや経済などの分野で広く用いられています。

単回帰分析は、1つの説明変数と1つの目的変数の関係を分析する手法であり、
重回帰分析は、2つ以上の説明変数と1つの目的変数の関係を分析する手法です！

データ分析に関してはまだひよっこですが、開発の勉強と並行して今後も学習していこうと思います！:airplane:
AzureからAzure Arcで接続されたマシン上でスクリプトを実行する方法

### はじめに

Azure上の仮想マシンであれば、[Run Command機能](https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command)を使ってスクリプトを実行することができるのですが、Azure Arcで接続されたマシンには現状Run Commandのメニューがないためその方法が使えません。そこでAzure Automation Hybrid Workerを使うことでAzure Automation PowerShellやPython runbooksをAzure Arcで接続されたサーバー上で直接実行することができます。

### 手順

#### Hybrid Worker Groupsを作成する

以下のようにHybrid Worker Groupを作成します。またHybrid Worker Groupsに追加するマシン（＝スクリプトを実行したいマシン）を選択します。
![hybridworker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/26783759-3878-bf88-62e1-9a2d56823518.png)

#### Azure Automation Runbookを作成する

Runbookを作成します。今回はHostnameを使って本当にAzure Arc接続マシン上でコマンドが実行されているのかを確認してみます。
![createrunbook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/0bd724a5-58ea-311f-5219-dd970c7130be.png)
![hostname.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/6fc561ac-71f8-f494-59c9-9e10633406e0.png)


#### Azure Arcマシン上でスクリプトを実行する

Start RunbookでHybrid Workerを選択し、スクリプトの実行基盤を選択します。これは一回実行する場合に使います。定期実行やスケジュールした処理をしたい場合は”Link to Schedules”を使用します。
![Startrunbook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/dc9ccda3-50cf-ba80-9362-4e1aede28c13.png)

ちゃんと選択したオンプレミス基盤でスクリプトを実行したことが確認できました。
![resultrunbook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/e33dadcf-52c0-371f-b739-4565ce240dea.png)

### まとめ

Azure Arcで接続されたマシン上でスクリプトを実行する方法を確認しました。今回の方法では拡張機能ベースのHybrid Runbook Worker(V2)を使った方法を紹介しましたが、もし[Log Analytics AgentベースのHybrid Runbook Worker(V1)をご利用の場合は2024年8月31日に廃止予定](https://learn.microsoft.com/ja-jp/azure/automation/migrate-existing-agent-based-hybrid-worker-to-extension-based-workers?tabs=bicep-template%2Cwin-hrw)ですのでご注意ください。

### 参考

[Run PowerShell Scripts with Azure Automation Hybrid Workers on-premises using Azure Arc](https://www.thomasmaurer.ch/2022/09/run-powershell-scripts-with-azure-automation-hybrid-workers-on-premises-using-azure-arc/)
Snowflake 初期設定：③USERADMIN編 ユーザー ロール作成

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)

### ■本記事の目的
Snowflakeのトライアルおよびご契約後の初期設定を行うため
管理者ロールの段階を理解するため

### ■前回の記事
[Snowflake 初期設定：②SECURITYTADMIN編 NETWORK POLICY](
https://qiita.com/taku_tachibana/items/6de80c90bef72ce0a9fd)

### ■今回の作業
SECURITYTADMINでもユーザー、ロール作成は可能ではあるのですが、
USERADMINで作成することが望ましいようなので、
こちらの編で実施していきます。

### ■ユーザー作成
ユーザー作成はUSERADMINで行います。
以下のコマンドでユーザーを作成してみます。
例に特定DBへの分析用ユーザーと管理用ユーザーを作成してみます。
```
use role USERADMIN ;
create user TEST_ANALYST_USER ;
create user TEST_DBADMIN_USER ;
```

### ■ロール作成
ロール作成はUSERADMINで行います。
以下のコマンドでユーザーを作成してみます。
以下を作成します。
・権限セット用のアクセスロール
　　　データベース権限用：データベース構成に応じて作成してください。
　　　ウェアハウス権限用：ウェアハウス構成に応じて作成してください。
・アクセスロールで構成するファンクショナルロール
```
use role USERADMIN ;
--データベース権限セット用アクセスロール
create role TEST_ACCESS_SELECT_ROLE ;
create role TEST_ACCESS_ALL_ROLE ;

--ウェアハウス権限セット用アクセスロール
create role TEST_ACCESS_WH_ROLE ;

--ファンクショナルロール
create role TEST_FUNCTIONAL_ANALYST_ROLE ;
create role TEST_FUNCTIONAL_DBADMIN_ROLE ;
```

### ■あとがき
ロール2種類作成した理由ですが、
ロール階層や権限継承の説明については、少し複雑になりますので
次回の記事でまとめたいと思います。
今回は、作成のみで一旦締めます。

### ■次の記事
[Snowflake 初期設定：④SECURITYADMIN編 ロール階層作成](
https://qiita.com/taku_tachibana/items/4d6895ffcac3edc473e7)

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)
Snowflake 初期設定：④SECURITYADMIN編 ロール階層作成

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)

### ■本記事の目的
Snowflakeのトライアルおよびご契約後の初期設定を行うため
管理者ロールの段階を理解するため

### ■前回の記事
[Snowflake 初期設定：③USERADMIN編 ユーザー ロール作成](
https://qiita.com/taku_tachibana/items/9c340cb3b40261095127)

### ■今回の作業
SECURITYADMINでの作業に戻ります。
ロールを実際に階層化していきます。

### ■ロール階層の作成
前段でアクセスロールとファンクショナルロールを定義した理由ですが、
オブジェクト制御権限は、オブジェクトによっては非常に細かい制御をロールに対して行う必要があります。一つのロールに対してオブジェクトで都度考えながら権限を振るのは管理上の手間となります。そのためアクセスケースをあらかじめ整理して、オブジェクトのアクセス制御権限をロールでセットとする考え方で管理を効率化します。
上位ロールは下位ロールの操作権限を継承できるためアクセスロールとファンクショナルロールというロールの階層構成が可能となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/ceaff86f-a1a3-19a6-52c0-3791bf17923a.png)

上位ロールに下位ロールを構成します。
アクセスロールとファンクショナルロールの関係性ですが、
継承を利用したロール階層構成ですので、以下の構文となります。
```
use role SECURITYADMIN ;
grant role <アクセスロール> to role <ファンクショナルロール> ;
例
--データベースアクセスを付与
grant role TEST_ACCESS_SELECT_ROLE to role TEST_FUNCTIONAL_ANALYST_ROLE ;
grant role TEST_ACCESS_ALL_ROLE to role TEST_FUNCTIONAL_DBADMIN_ROLE ;

--ウェアハウスアクセスを付与
grant role TEST_ACCESS_WH_ROLE to role TEST_FUNCTIONAL_ANALYST_ROLE ;
grant role TEST_ACCESS_WH_ROLE to role TEST_FUNCTIONAL_DBADMIN_ROLE ;
```

親ロールの最後は一部の例を除き、SYSADMINとしておきます。
SYSADMINで下位ロールのオブジェクト管理ができるようにしておきます。
```
use role SECURITYADMIN ;
grant role <ファンクショナルロール> to role SYSADMIN ;
例
grant role TEST_FUNCTIONAL_ANALYST_ROLE to role SYSADMIN ;
grant role TEST_FUNCTIONAL_DBADMIN_ROLE to role SYSADMIN  ;
```

Webコンソールの階層図を見ると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/b9b07fba-8bd0-f4d0-1099-d12d3abbe12b.png)

### ■ロール階層における注意点
別の方の記事での注意点を閲覧したところ
共有（SHARE）の権限はむやみにSYSADMINに継承しない方がいいみたいです。
ロール階層を組むことが必須ではないロール構成もあるようです。
DB関連ではないですが、サポート管理ロールなども独立させるようにしていたので、
上位ロールに継承させたくない場合は考慮しましょう。

### ■あとがき
ロール設計については、お客様の要件や規模、DB環境などで構成が変わるので
図面化してから作成したほうが良さそうです。
ユーザーへのロールの割当ては、次回とさせてください。

### ■次の記事
[Snowflake 初期設定：⑤SECURITYADMIN編 ユーザーへのロール割当て](
https://qiita.com/taku_tachibana/items/7fb7dc8e2b63c3e9fc72)

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)
Googleのソフトウェアエンジニアリングの1章「ソフトウェアエンジニアリングとは何か」を読んで感じたこと

# 前書き
## 全体を通しての感想

読んだ本
Googleのソフトウェアエンジニアリング
―持続可能なプログラミングを支える技術、文化、プロセス
https://www.oreilly.co.jp/books/9784873119656/

ソフトウェアエンジニアリングについて、その定義からうまく実行するために必要な文化、プロセス、ツールといった内容についてGoogle社での実際の事例をもとに書かれた本で、とても良い本でした。
かなり分厚く読むのが大変な本ですが、それに見合った学びが得られる内容が記載されていると思います。

特に文化、プロセスについて優秀な集団が多くの年月をかけて実験や失敗を繰り返して醸成し、磨き上げてきたものであることが感じられる内容です。
自社でのやり方と比較したり、これから先直面するであろう問題を既に経験した先人の知恵として得られます。
これから自社内でCI/CDの仕組みを構築したり、プロセスを策定したりする際に辞書的に参照し活用していきたいと思っています。

## この記事について
かなり分厚い本であるため、以下のように感じています。
- 単純に分量が多いためすべてに対して感想を一気に書ききるのが難しい
- 流し読みをした部分や情報量が多く頭に入りきっていない部分がある
- 実践的な内容なので問題に直面して実感することで感じることが変わりそう

そのため章ごとに感想を書いていきます。
この記事は1章「ソフトウェアエンジニアリングとは何か」の感想です。

# 感想
## 1章　ソフトウェアエンジニアリングとは何か の感想
まず第1章がこのソフトウェアエンジニアリングとは何か、という問いである点がこの書籍が素晴らしい書籍であることを表していると感じます。
「プログラミング」は単にコードを生産する活動、「ソフトウェアエンジニアリング」は生産したコードを稼働期間中に保守するためにプログラミングを拡張する活動。
両者ではコードの稼働期間が全く異なる。

稼働期間の違いによって、

- コードを書いたことによる価値
- コードにを書くにあたって直面する制約
- コードを書くためのベストプラクティス

が全く異なる。
稼働期間が長いと、

- ビジネス要件が変化する
- 提供する機能も増えていく（かもしれない）
- 依存するOS、ミドルウェア、ライブラリ、他のアプリケーションが変化する
- ソフトウェアを保守する人間が変化する

ほとんどのプロジェクトは無期限の継続を前提に運営されなければならない。
変化しないことを選択することはできるが、変化できないことはプロジェクトの継続において致命的なリスクになり得る。
依存する他のソフトウェアが変化するように、自身が保守するソフトウェアも変化を強いられる。
その時どのように変化していくのかを決定していくためにスケールするポリシーが必要である。
ぽつりぽつりと、しかし確かな関連性を持って綴られる各事例は
ソフトウェアを保守する上で体感し続けてきた難しさを言語化してくれていると感じました。

## 特に印象に残った内容
### Hyrumの法則とBeyonceルール

Hyrumの法則：
あるAPIに十分な数のユーザーがいる場合、APIを作った者自身が明示した仕様として何を約束しているかは重要ではない。
システムが持つあらゆる観測可能な挙動について、それに依存するユーザーが出てくる。

これは放っておくとAPIを開発している人があらゆる利用者の利用方法を担保しなければいけなくなることを示していますが、それに対して

Beyonceルール：
製品がインフラストラクチャーの変更の結果として障害やほかの問題に陥った場合、問題がCIでのテストで表面化しなかったのならば、インフラストラクチャーの変更に落ち度はない。とするポリシー。

を定めて責任範囲を明確にし、一つの現実的に可能な運用を示してくれていると感じました。

### 徹底したデータ駆動での意思決定
書けなくなったり無くなってしまうホワイトボードマーカーによってミーティングの思考が寸断されてしまうことを防ぐために、あらゆる場所に十分な量のホワイトボードマーカーを置く、という簡単な事例と
開発者のローカル端末で頻発するビルド待ち時間を解消するために、大きなコスト（開発コスト、運用コスト、利用者教育コスト）を支払って自社用の分散ビルドシステムを開発した事例が挙げられ、それぞれの背景には徹底したデータ駆動の意思決定があるという点が記載されていた。

特に後者では、運用後今までエンジニア個人がビルドにかかるリソース消費を抑えようという前提で行動していた共通のインセンティブが失われ、分散ビルドにおける浪費が横行するようになり予想以上のコストがかかったといった話が記されていた。
継続してデータを取り続けることによって決定を再考すること、間違いが起きる（時間経過によって間違いとなる）前提であることの重要性が記載されていた。
表層的な施策ではなく、データ駆動での意思決定という本質的な取り組みを踏まえた上で自分たちの取り組みに取り入れなければいけないと感じた。

## まとめ
- ソフトウェアエンジニアリングは難しい
- ソフトウェアエンジニアリングとプログラミングは違う
- ソフトウェアエンジニアリングを継続するには「良い状態のコードセット」も「文化を維持するポリシー」も「それらを支える周辺の仕組み」も全てが重要である

といったことを強く感じました。
2章の感想につづく。
App Service for Linux の PHP 8.0 で ログストリームに PHP からログ出力してみた

WordPress が動いている App Service for Linux の PHP 8.0 で、どうやったら WP-Cron のメッセージ出力をログストリームに出せるのか試してみました。意外と簡単にメッセージ出力する事ができるんですね。

## WP-Cron のサンプルコード

```php:php
error_log("[WP Cron]: Error message", 0, "php://stderr");
```

![wp-cron-php-sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/45062a10-93c5-986c-5f66-e6b600c6bbff.png)

## AppService　のログストリーム

![wp-cron-error-message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/79dd801b-45a6-3140-5ebe-46dc40a5664a.png)

## 参考

https://www.php.net/manual/ja/function.error-log.php

https://www.php.net/manual/ja/wrappers.php.php
[iTerm2] 地味に役立つ〜現在のディレクトリで新しいタブを開く〜

# はじめに
iTerm2で現在のディレクトリで新しいタブを開きたいと思ったことはありませんか？
新しくタブを開いた時にディレクトリを移動するのが地味にめんどくさいと感じていました。
そこで今回は現在のディレクトリで新しいタブを開ける設定を書いていきます。


# 設定方法
![スクリーンショット 2023-04-30 13.38.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880196/bd76b533-1141-c3a8-010e-8aa081090632.png)

iTerm2 > Preferences > Profiles > Working Directory
Reuse previous session's directory にチェックを入れるだけ。


# まとめ
最後まで見ていただきありがとうございます！
少しでも役に立てれば幸いです！
PrismaはRDS Proxyと相性が良くないらしい

# はじめに
Lambda+RDS=RDS Proxy(コネクションプールのため)みたいに考えてしまっていた。

https://www.prisma.io/docs/guides/deployment/deployment-guides/caveats-when-deploying-to-aws-platforms

しかし、RDS Proxyの「ピン留め」を考慮すると、RDS Proxyを用いることにメリットはない(no benefits)そうです。
ピン留めとは

>複数のDBクライアントが安全にDB接続を共有できない場合、RDSProxyはコネクションプール内のDB接続を特定のDBクライアントに対して固定してしまいます

というもので、ピン留めの発生条件の一つには[Prepared Statement](https://e-words.jp/w/%E3%83%97%E3%83%AA%E3%83%9A%E3%82%A2%E3%83%89%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%A1%E3%83%B3%E3%83%88.html)の使用があります。
Prismaは、Prepared Statementを用いているためピン留めを発生させる可能性があるということです。

# じゃ、コネクションプールどうするのよ

RDS Proxyを利用しないとなると、「コネクションプールどうするの？」となりますが、実はPrismaがやってくれます。

https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#the-serverless-challenge

PrismaClientは、コネクションプールを管理してくれるので、例えば

1. 5リクエストくる
2. Lambdaはリクエストごとにコンテナを生成
3. 1リクエスト1コンテナの場合、5つのPrismaClientがそれぞれコネクションプールを管理することになる
4. プールサイズが3の場合は、5×3=15ということになる。

ということです。
そのためリクエストが多くなるとコネクションの上限にすぐ到達してしまう可能性があるため

>Start by setting the connection_limit to 1

の通り、サーバレス環境ではプールサイズを1にするように書かれています。
その他、サーバレス環境で考慮するべきこととしては

https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#other-serverless-considerations

を参照してください。
また、押さえておくべきこととしてコンテナは

* 再利用される可能性がある
* 一定の時間後に破棄される(この時間を指定することはできません)

ため、

```
$disconnect()
```

↑のように、disconnectする必要はない点と、アプリケーション内でPrismaClientは使い回すようにしましょう。


# その他

学んだことを置いておきます。

## Lambdaは実行時に何が行われているのか

https://qiita.com/ny7760/items/700ae917da2c5b5e3f8a

関数を実行する際はコンテナを作っています。必ずしもではないですが、5リクエスト=5コンテナという理屈です。
そして、Lambdaは

* コールドスタート
    * Lambda関数実行時に通常より時間がかかること
* ウォームタート
    * 起動時間を省略しての実行

のどちらかでスタートする。

## コネクションの確認の仕方

https://qiita.com/snaka/items/b6e7500c96e04c131d9e

# まとめ

* 必ずしもLambda+RDS=RDS Proxyではない
* PrismaにはRDS Proxyは必要なく、コネクションプールはPrismaで管理するで基本問題ない
    * サーバレス環境ではプールサイズを1にする
* ドキュメントを読む

# 参考

* https://www.keisuke69.net/entry/2020/09/29/131203
* https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/connection-management
* https://www.keisuke69.net/entry/2017/06/21/121501
* https://qiita.com/snaka/items/b6e7500c96e04c131d9e
* https://libitte.hatenablog.jp/entry/20141202/1417452564
* https://dev.classmethod.jp/articles/rds-proxy-avoid-session-pinning/
* https://qiita.com/keitakn/items/fac324cd44c4374d82e6
Snowflake 初期設定：②SECURITYTADMIN編 NETWORK POLICY

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)

### ■本記事の目的
Snowflakeのトライアルおよびご契約後の初期設定を行うため
管理者ロールの段階を理解するため

### ■前回の記事
[Snowflake 初期設定：①ACCOUNTADMIN編](
https://qiita.com/taku_tachibana/items/b293ed07c8303999dcc6)

### ■今回の作業
SECURITYADMINロールを使用して、
ネットワークポリシーでIPリストを定義し、
SnowflakeアカウントへのIP制限を行います。

### ■ネットワークポリシー：アカウントレベル
まずはアクセス元のセキュリティを設定します。
ネットワークポリシーには、アカウントもしくはユーザーレベルでの設定が可能です。
後者はクラウドツール専用ユーザーなどでも利用するケースがあります。
 
以下のコード例になります。
ネットワークポリシーの定義名は任意です。
許可IPリストは、カンマ区切り、''囲みで記述します。
CIDR表記でアドレス範囲指定も可能です。※CIDRなしは[/32]と見なされます。
拒否IPアドレスは、記述しなくても問題ありません。
許可リストのアドレス範囲から一部だけ拒否したい場合に利用します。
```
use role SECURITYADMIN ;
create or replace network policy XXX_ACCESS_RESTRICTION_POLICY 
allowed_ip_list = 
(
'XXX.XXX.XXX.XXX/YY',
'XXX.XXX.XXX.XXX/YY'
) 
   --ブロックアドレス指定は任意
   blocked_ip_list = 
   (
   'XXX.XXX.XXX.XXX/YY',
   'XXX.XXX.XXX.XXX/YY',
   )
   --ブロックアドレス指定は任意
comment = 'トライアル-アカウントレベル' --管理用に記載しておくと便利
;
```
 
 
定義を作成しただけでは、IP制限は機能しませんので、アクティブ化します。
```
use role SECURITYADMIN ;
alter account set network_policy = XXX_ACCESS_RESTRICTION_POLICY;
```

これで、IP制限がかかりました。
それでは、回線を切り替えて実際に再度ログイン検証すると、
以下のIP制限がかかったことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/f159fbc3-bf43-2026-e53d-4da740f2f798.png)

ネットワークポリシーの一覧確認は以下のコマンド実行することで確認できます。
```
use role SECURITYADMIN ;
show parameters like 'network_policy' in account;
```
ネットワークポリシーの詳細は以下で確認できます。
```
use role SECURITYADMIN ;
describe network POLICY XXX_ACCESS_RESTRICTION_POLICY ;
```

### ■あとがき
SECURITYADMINで、ユーザー、ロール作成まで記事を書きたかったのですが、
上記の作業は、USERADMINを使用する方が良さそうなので、
今回はここまでの作業とします。

### ■次の記事
[Snowflake 初期設定：③USERADMIN編 ユーザー ロール作成](https://qiita.com/taku_tachibana/items/9c340cb3b40261095127)

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)
window.open()を使用して複数ファイルを順番通りにダウンロードする方法

### 経緯
実務で実装を行なっているときに、こんなバグを発見しました。
window.open()を使用して別ウィンドウを開き、複数ファイルをダウンロードする処理があるが、ファイル名001~ファイル名010までが順番通りにダウンロードされないという現象です。

### 試したこと
最初は遅延処理を入れて、ダウンロード処理とダウンロード処理の間に間隔を入れてみましたが解決には至りませんでした。

## 解決策
結論から言うと、 **$(window).on('unload', function() {});** を使用することで解決しました。
unloadイベントはページが閉じられる時などに処理を行うことができます。
具体的には、以下のようなソースコードで今回の問題を解決しました。
```javascript:qiita.js
function downloadFile() {
    var wdl = window.open(URL);
    $(wdl).on('unload', function () {
        // 再起処理
        if (ダウンロード数 条件) {
            downloadFile()
        }
    });
}
```

:::note warn
警告
検証ブラウザはChromeなため、他ブラウザでは今回のバグが解決可能か不明です。
また上記の理由により、unloadは非推奨となっているのでお気をつけください！
:::
大量のemlファイルをpythonでCSV形式の一覧に書き起こした話

# 概要
開発していてあるわけではなく、営業の先輩から「過去のメールのやりとりをExcel一覧で見れるようにしておきたい」という相談をもらい、「地味にeml形式だからテキストに起こすの面倒ですからね…」という共感の元、やってみたという話です。

# やったこと
* ディレクトリに保存してある「emlファイルの一覧」から、「差出人」「宛先」「件名」「本文」「作成日時」が項目となっているCSVファイルを作った。
* 言語はpythonです。こういう痒いのをやりやすい。
* jupyter notebookでやりました。便利。

# 処理手順

## 必要パッケージのインポート

* 主にメールの処理に必要なもの
* CSV処理に必要なもの
* 日付処理に必要なもの

```
import email
import os
from email import policy
from email.parser import BytesParser
import csv
from datetime import datetime
```

## （関数定義）emlファイルをメールオブジェクトに

```
def parse_eml(file_path):
    with open(file_path, 'rb') as f:
        msg = BytesParser(policy=policy.default).parse(f)
    return msg
```

## （関数定義）メールオブジェクトからテキスト情報を取得

```
def get_email_text(email_msg):
    text = ""
    if email_msg.is_multipart():
        for part in email_msg.walk():
            if part.get_content_type() == 'text/plain':
                charset = part.get_content_charset() or 'utf-8'
                text = part.get_payload(decode=True).decode(charset, errors='replace')
                break
    else:
        if email_msg.get_content_type() == 'text/plain':
            charset = email_msg.get_content_charset() or 'utf-8'
            text = email_msg.get_payload(decode=True).decode(charset, errors='replace')
    return text
```

## （関数定義）各メール情報を取得

```
def get_email_data(email_msg):
    from_address = email_msg.get('From', '')
    to_addresses = email_msg.get('To', '')
    to_addresses = '/'.join([addr.strip() for addr in to_addresses.split(',')])  # 複数の宛先を '/' 区切りにします
    subject = email_msg.get('Subject', '')
    text = get_email_text(email_msg)
    sent_date = email_msg.get('Date', '')

    return {
        'from': from_address,
        'to': to_addresses,
        'subject': subject,
        'text': text,
        'date': sent_date,
    }
```

## （関数定義）取得したテキスト情報をCSVファイルに書き出し

```
def write_to_csv(file_name, data):
    with open(file_name, 'w', newline='', encoding='utf-8') as csvfile:
        fieldnames = ['from', 'to', 'subject', 'text', 'date']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()
        for item in data:
            writer.writerow(item)

```

## 実行処理

* emlファイルの一覧は、同階層の「mail」ディレクトリに入れました

```
if __name__ == '__main__':
    eml_dir = './mail'  # emlファイルが保存されているディレクトリ
    timestamp = datetime.now().strftime('%Y%m%d%H%M%S')  # 処理開始時刻を取得
    output_csv = f'output_{timestamp}.csv'  # 出力するCSVファイル名に時刻を追加

    email_data = []

    for filename in os.listdir(eml_dir):
        if filename.endswith('.eml'):
            file_path = os.path.join(eml_dir, filename)
            email_msg = parse_eml(file_path)
            email_info = get_email_data(email_msg)
            email_data.append(email_info)

    write_to_csv(output_csv, email_data)

```

# おわり

* 言語や環境は色々ありますが「これ手動でやったら５時間ぐらいかかりそうだな」みたいなものを１時間で終わらせるにはpythonあたりがラクに着手できてよいですね。
初心者VBAを使いExcelでShift JISへの変換関数調査ノート

ExcelでShift JISへの文字コード変換をしたかったのですが、標準でExcelに搭載されている関数になかったので、情報を集めながら作成したときのノートを書きたいと思います。

・環境
Windows   :11
Excel     :バージョン 2023

#### 参考サイト
-「ExcelマクロVBA入門編」
https://excel-ubara.com/excel_vba1.html
-「VBAでの文字コードの取得」
https://office-fun.com/dev-vba-character-encoding/
-「Office VBA リファレンス」
https://learn.microsoft.com/ja-jp/office/vba/api/overview/

# 目次
　[作業準備](#作業準備)
　[用語整理](#用語整理)
　[実行](#実行)
　[まとめ](#まとめ)

#### 作業準備
用語としては聞いたことがあったのですが、そもそもVBAとは何か、マクロを使うため準備は何をしたらよいかがわからなかったので、以下のサイトを参考にExcelを触りながら理解をしていきました。
ClosedXMLを触っていたので、セル範囲の指定などは、比較的簡単に理解することができました。

-「ExcelマクロVBA入門編」
https://excel-ubara.com/excel_vba1.html

#### 用語整理
参考サイトのわからなかった部分をまとめます。
-「VBAでの文字コードの取得」
https://office-fun.com/dev-vba-character-encoding/

使っているデータの型
|データ型|概要|用途|
|:---|:---|:---|
|Long|長整数型|-2,147,483,648 ～ 2,147,483,647の範囲の整数|
|String|文字列型|最大約20億文字までの文字列を表現|
|Variant|バリアント型|すべてのデータを表現|

関数
|関数名|引数|返り値のデータ型|用途|
|:---|:---|:---|:---|
|CLng|任意のString型または数式|Long型|引数を評価し整数型を返す/16進数→10進数に変換|
|Mid|String型, Long型 [,Variant型(Long型)]|String型|第一引数のString型をLong型指定の位置から切り抜く。開始位置の添え字は1|

#### 実行
開発のマクロから参考サイトの関数を登録することでShift JISへ変換関数を実行することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3096978/79f5f52b-27e9-5b79-fbab-b8db903608d5.png)

#### まとめ
マクロを初めて使ってみてExcelにこんな使い方があるとは知らなかったです！
VBAの知識を広げて定型的に行っているOfficeアプリ系の事務処理を楽にできたらいいなと思いました！
iOSショートカットレシピ Nature Remoで部屋の照明を“確実に”ON/OFFする

[Nature Remo](https://nature.global/nature-remo/) は通常付属の赤外線リモコンで操作するさまざまな家電を付属のリモコンの替わりにRemoの汎用リモコンが操作することで、PCやスマホから家電を制御できるスマートリモコンです。TVの電源入れ→ケーブルテレビの電源入れ→入力をHDMIに設定、みたいな操作を１つのコマンドに設定でき、Siriとの連携もスマートで大変便利です。しかし、僕の部屋の照明はリモコンの反応が悪くRemoからの１回のON/OFFコマンドでは反応しないことがあります。指で押すリモコンならば、反応があるまで繰り返しボタンを押せばいいのですが、何回押せば照明が点灯（消灯）するかはわかりません。また、ONコマンド、OFFコマンドは同じコマンドでトグル動作になっています。そこで自動化するとなると部屋の明るさが変化するまでボタンを押す（信号を送る）という処理を行います。
# ショートカット
Remoを使って部屋の照明をON/OFFするショートカットを示します
![照明リビング.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535482/19252b0d-5f7d-28d4-5dc8-7deab69c4424.jpeg "Remoを使って部屋の照明をON/OFFするショートカット")
# ショートカットの構成
概略のフローチャートは次のような感じです
```mermaid
flowchart LR
    A[Start] --> B[before il]
    B --> C{5 loop or less}
    C -->|Yes| D[command ON/OFF]
    D --> E[wait 10s]
    E --> F[after il]
    F --> G{change il? after-before}
    G --> |Yes| H[End]
    G --> |No| C
    C -->|No| H
```
最初に操作前の明るさを記録して、ON/OFFコマンドを出力し、明るさが変わったら照明器具がコマンドに反応して実際にON/OFFたとして処理を終了します。処理のポイントは
* コマンドは最大５回繰り返します
* センサーの計測周期を待つため、コマンドを出力した後、10秒間待ってから明るさを計測します
* リモコンの信号はON/OFF共通（トグル動作）
* ON/OFF共通のショートカットにするため、明るくなったら（暗くなったら）でなく変化があったら、器具が反応したとする
## 部屋の明るさ値を取得する
このアクションは[Remoのcloud APIを使ったショートカットです](https://qiita.com/osadataku/items/0a8be499031224f448e7)が、何度も利用するので、別のショートカットにして、サブルーチンのように読んでいます。明るさの値はクリップボード経由で受け取ります。
## 照明にON/OFFコマンドを送る
Remoのアプリで設定した、赤外線リモコンから学習したON/OFFコマンドを出力します。
## コマンドに反応したかを判断する
ON/OFFコマンドを送信した後、器具の反応時間と明るさセンサーの検出周期を待つため10秒間待機します。待機後、明るさが処理前の明るさから大きく変化していればコマンドに反応したとして、処理を終了します。

pythonのbreak文のような処理が見当たらなかったので、ショートカットを終了しています
PythonによるWebスクレイピング-入門編、その2 - テキストのスクレイピング

Webスクレイピングの学習が進みました。今回はテキストのスクレイピングまで学習しました。

https://www.udemy.com/course/python-scraping-beginner/

# テキストデータの取得
ページからテキストを抜き出す処理を行います。このページから講師情報を取得します。

https://scraping-for-beginner.herokuapp.com/mypage

![スクリーンショット 2023-04-30 120322.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/40c54082-8547-8952-fcbc-ef86c88ec03b.png)

```python
#ユーザーネームの要素を取得
elem_username = browser.find_element_by_id("name")
elem_username.text

#所属企業
elem_company = browser.find_element_by_id("company")
elem_company.text

#生年月日
elem_birthday = browser.find_element_by_id("birthday")
elem_birthday.text

#出身地
elem_come_from = browser.find_element_by_id("come_from")
elem_come_from.text

#hobby
elem_hobby = browser.find_element_by_id("hobby")
hobby = elem_hobby.text

#replaceを使って改行コードをコンマに変える
hobby02 = hobby.replace("\n",",")
hobby02
```
![スクリーンショット 2023-04-30 124312.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/0ce2d7c4-ddf3-4cb5-29ff-9b6437fcc58b.png)

# テキストデータの一括取得
テーブルから一括でテキストデータを取得する方法を考えます。
`th`タグに必要なテキストがが含まれているので、**タグ名を使って複数の要素を取得**します。

```python
#thの要素を取得 - 一番最初の要素のみが取得される
elem_thtext = browser.find_element_by_tag_name("th")
elem_thtext.text

#複数要素を一括取得 - thタグとなっている要素全て取得する（list型で表示）
elem_thtext = browser.find_elements_by_tag_name("th")
elem_thtext

#取得した要素
for i in range(0, len(elem_thtext)):
    print(elem_thtext[i].text)

#取得した要素をリストに
keys = []
elem_thtext = browser.find_elements_by_tag_name("th")

for elem_th in elem_thtext:
    text = elem_th.text
    keys.append(text)

print(keys)
```
![スクリーンショット 2023-04-30 124827.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/2ff4a1c3-2111-0d31-5851-23bb2ba5eee0.png)

テーブルのキー側が取得できたので、次はバリュー側を取得します。

```python
#tdの方を取得する
elem_tdtext= browser.find_elements_by_tag_name("td")
elem_tdtext

#取得した要素
for i in range(0, len(elem_tdtext)):
    print(elem_tdtext[i].text)
    
#取得した要素をリストに
values = []
elem_tdtext = browser.find_elements_by_tag_name("td")

for elem_td in elem_tdtext:
    text = elem_td.text
    values.append(text)

print(values)
```
![スクリーンショット 2023-04-30 124827.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/d6cf83fe-2ea1-cb0d-ab18-3dfcd359c461.png)

# CSVにして出力
スクレイピングしたテキストをCSVファイルにして出力します。
データフレームの作成には**Pandas**を用います。Pandasは2次元データの作成とその入力・出力に向いているライブラリーです。

https://pandas.pydata.org

```python
import pandas as pd
df=pd.DataFrame()

df["項目"] = keys
df["値"] = values
df

#csvに出力(インデックスは無し)
df.to_csv("講師情報.csv", index = false)
```
![スクリーンショット 2023-04-30 125240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/12472181-575c-ecc2-7a7b-988a327db08a.png)

次回は画像データのスクレイピングについて学習します。