徒然だみー

オオトリ様との日常

MENU

見ることは好きということ!!

テスト前になるとおなか痛くなることあるよね


こんちゃ!だみーです

こんな記事を読みました↓


サルに二つの画像を見せどちらの像を好むかを把握しておいて、好まれていない画像を見ているときに、快感回路を刺激すると、好まれなかった画像が好まれるようになります。

ちなみに、赤ちゃん研究でもそうですが、物言わぬものの好みは視線や体重移動から判断されます。

視線の停留時間が長かったり、そちらを見る回数が多かったり、体が傾いたりすると、そちらを好むのだろうと推測します。

サルに画像を見せたとき、ドーパミン神経の出発点である腹側被蓋野を刺激すると、本来好まなかった画像を好むようになります。

嫌いなものでも、見ているときに快感回路が刺激されると、「嫌い」が「好き」に変わるのです。
商売やサービスでいえば、その商品やサービスに接しているときに、いかに腹側被蓋野を活性化させるか、快を感じさせるかが勝負、ということになります。

 

視覚から好きなものを取り入れて快感を得れば嫌いなものも好きと勘違いする?みたいですね。
これって逆も言えると思うんです。

例えば子供の好き嫌い。
単に味が苦いという記憶から嫌い!というだけでなく
精神的に苦痛を感じる場面で食べたものを嫌いになることだってあると思うんです。
両親が喧嘩しているときに毎回同じもの食べてたら嫌いになると思いませんか?

どんなに好きな食べ物でもグロテスクな映画やホラー映画を見ながら食べるとおいしさが減少しませんか?

これが食わず嫌いになったりするのかも。
勉強ってできないが積み重なってやりたくなる人が大半だと思いますが、この時も自分の好きなもの、、推しとかを目につくとこに置いとけばもしかしたら気持ちの変化があるかも。

音楽を聴きながら何かをするのも脳内のドーパミン神経を刺激することになるからかもしれません。


自分が好き!やってて楽しいことを面倒なことするときに一緒にやればもしかしたら面倒な気持ちが少し減るかもしれませんね


んじゃ!おやすみです

テスト終わった~

やっとテスト終わったーーーーー
な・つ・や・す・み!

こんちゃ!だみーです

昨日テストが終わり、就活も終わっているワシは本日から夏休みです
卒研もぼちぼち進み、存分分に楽しめる


ワシ、ゲーム好きなんです。
FPS大好きなんです

夏休みは、オオトリ様とお出かけ、デート、旅行、ダラダラをしてゲームをします。
久しぶりにTwitchで配信でもしてみよかと思ってます

www.twitch.tv

ほんとだらだらゲームするだけなんですけど、もしよければ見てってください


いや
一緒にゲームしてくださいーーーー

んじゃ!明日から楽しく生きるぞー

日本語勉強に向いていない説

明日テストだー
勉強!勉強?

こんちゃ!だみーです

いましがた、明日のテスト勉強をしていたのですが、、
日本語ってわかりにくくないですかーーー?

説明に不向きというか、無駄な言葉が多いなーとか、、、、


例えば、
「パイプと同様の円環状ダイスから出た溶融プラスチックの内側に空気を吹き込んでプラスチック膜を風船のように膨らませる。」

という説明文があったとする。
これを英語にすると、

Air is blown into the inside of molten plastic that comes out of an annular die similar to a pipe to inflate the plastic film like a balloon.」

うん、理解しやすいな〜
日本語では溶融プラスチックの説明があってから、それをどうするかの説明がある。
それに「風船のように」のような比喩表現が間にある。
この部分は必要ないが、文の間にあることでその重要性を考える必要がある。

その点英語は「風船のように」の部分が文の最後にある。
どうでもいいことを最後に置いてある。
また、「空気を吹き込んでプラスチックの膜を膨らませる」というこの文で一番重要な部分を最初に記述し、
その後にプラスチックについての説明
最後におまけ程度に「風船みたいに!」って記述している。

もちろん英訳は一通りではないが、英語の方がものを理解するのに適していると思う。


しかし、日本語には感情、繊細な感情を細かく表現する力がある。
言語にも人のようにそれぞれ特徴があるのだな〜

英語苦手だけど勉強頑張らないとな〜

ほんじゃ、勉強してきます!

【Python】日向坂メンバーのブログ画像をスクレイピングしてみた~◢⁴⁶

今長野にいるんですけど、ほんと暑いですね~
山梨けぇったら溶けちゃうんだろーな

こんちゃ!だみーです

山梨ってほんと暑いんですよ
気温もなんですけど体にまとわりつく湿気の塊みたいなのがほんとにいや!!
でも、桃とかおいしいもの一杯です♡

はじめに

今回は日向坂メンバーのブログから画像をスクレイピングしようと思います。
昨年、「あなたは日向坂に入れるか!」といったメンバーの画像から日向坂に入れる確率を求めるモデルを作成しようと思い立った。
そのためには大量のメンバーの画像が必要となる

決してやましいことに使うのではない。研究のため、これも世のためだ!

画像を集めるときに使ったプログラムを紹介します。
基本的にコピペで日向坂メンバーの大量の画像が入った変態フォルダが創れると思います。


ちなにみ、わしはくみてん推しでした

プログラム

以下が全コードです↓

import requests,os,time,urllib
from bs4 import BeautifulSoup
import glob

home_url = 'https://www.hinatazaka46.com/s/official/diary/member?ima=0000/'
html = requests.get(home_url)

urlss = []
url_all = []
soup = BeautifulSoup(html.text, "html.parser")
for element in soup.find_all("a"):
    urll = element.get("href")
    if 'diary/detail' in urll:
      a="https://www.hinatazaka46.com"+urll
      urlss.append(a)

#フォルダ内の画像を格納
files = glob.glob("-----------画像を保存したいフォルダへのパス---------------------/*.jpg")

#同じリンクを取り除く
url_all =tuple(urlss)
print(url_all)

j = len(url_all)
for i in range(j):
  #サイトのURL
  target_url = url_all[i]
  response = requests.get(target_url)
  image = response.content
  #画像保存先
  save_dir = "-----------画像を保存したいフォルダへのパス---------------------"
  #ダウンロードの処理
  def download_images():
    #HTML取得
    html = requests.get(target_url).text
    #URLの取得
    urls = get_image_urls(html)
    #URLダウンロード
    go_download(urls)

  #URLの一覧取得
  def get_image_urls(html):
    #HTML解析
    soup = BeautifulSoup(html,"html.parser")
    #画像URLを取得
    res = []
    dv = soup.find('div', class_="c-blog-article__text")
    for img in dv.find_all("img"):
      src = img['src']
      #URLを絶対パスに変換
      url = urllib.parse.urljoin(target_url,src)
      #print('img.src = ',url)
      res.append(url)
    return res

  #URLダウンロード
  def go_download(urls):
    l = len(urls)
    #保存先フォルダー
    if not os.path.exists(save_dir):
      os.mkdir(save_dir)
    for url in urls:
      fname = os.path.basename(url)
      save_file = save_dir + '/' + fname
      r = requests.get(url)
      j = len(fname)
      with open(save_file,'wb') as fp:
        fp.write(r.content)
        print("save:",save_file)
      time.sleep(1)

  if __name__ == '__main__':
    download_images()


普通にスクレイピングすると、実行のたびに同じ画像が保存されてしまうのですが
今回は同じ名前の画像を削除するようにしてあるのでその心配はありません!!

注意点

  • 「-----------画像を保存したいフォルダへのパス---------------------」この部分は画像の保存先を指定してください。
  • プログラムはpythonで記述されています。google colaboを使えばネット上でも実行できます。

colab.research.google.com

  • 上のリンクからgoogle colaboのサイトを開きます。
  • 新しいノートブック作成をクリックします。
  • 次のコードを先にコピペして実行してください。
#ドライブをマウントする
from google.colab import drive
drive.mount('/content/drive')
%cd "/content/drive/My Drive/Google Colab"
  • 次にさっきの全コードをコピペしましょう。
  • google colaboで実行する場合は画像の保存先(-----------画像を保存したいフォルダへのパス--------------------- ←この部分)以下のように指定します。
/usr/bin/chromedriver

これで以上です!!

おひさまの皆さん、変態の皆さんぜひやってみてください!!
最高のフォルダができることを願っています

んじゃ!

おひさしぶり

9時とか10時から外気30温の表示見ると速攻家帰りたくなる

 

こんちゃ!だみーです

 

私事ではございますが先日google adsenseの審査が通りました;;

今後広告が表示されると思いますが、邪魔だったら言ってください。

どうでもいいよって人はスターください

 

今回は最近見たアニメやらの感想をつらつら書くことにします。

面白そうだなと思ったら見てみてください。

 

※重大なネタバレを含む場合がございますのでご了承ください

 

終末のワルキューレ

ragnarok-official.com

気が付いたら続きが配信されていたのでわっくわくで見ました

第六回戦!!!

神代表から人類代表になったに(日本FPSの伝説)「釈迦!!」

VS

神代表、「七福神!!」

七福神はもとは一つの神という設定で7神が合体し「零福」となり戦った。

 

零福は本作オリジナルの神だ。

オリジナルは少し残念だった

七福人だったら「毘沙門天」が出てくると思ってたんだけどなー

 

釈迦は豪快で人が良くていいキャラしてる

今回も反則級の技に反則級の技で返してるとこ中二ぽくてすき

さらにここからもうひと悶着あるのですがそれは見てください。

 

神話上の神々と歴史上の偉人を戦わせるこの話。

勉強になるとまではいわないが、神話に興味がもてたし内容も興奮するものなのでこの夏ぜひ!

 

カウボーイビバップ

www.cowboy-bebop.net

これまた古めのチョイスですね~

1998年からテレビ放送されたアニメです

 

2071年の火星を中心とした太陽系を舞台に賞金稼ぎのスパイクらの活躍を描いた作品だ。

粋なセリフやクールな映像、メカアクションなどが楽しめる。

 

主人公の声優は山寺宏一さん。さらにヴァレンタインの声優には林原めぐみさんと豪華声優陣!

 

話数によって作品のテイストがかなり異なるので飽きずに最後まで一気に見ました。

寝苦しい夏の夜は寝ずにアニメ一気見しよー

 

花の画像をスクレイピングしてみた!

昨日上げたブログを修正してみました!
見やすくなってると思います。

こんちゃ!だみーです

卒研のために現在の進捗とかまとめ解こうと思ってブログに書くことにしました。

今回はトルコギキョウという花の画像をスクレイピングして集めたのでまとめます。

環境

Google Chrom(バージョン:114.0.5735.199)

chromedriver(バージョン:114.0.5735.90)

python(Python 3.10.11)

全コード

とりあえず全コード貼っときます。

適切なchromedriverインストールすればすぐに使えると思います!

import requests

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

import os

import time

import datetime

from selenium.common.exceptions import NoSuchElementException

from selenium.common.exceptions import ElementClickInterceptedException




tm_sum = time.time()  # 処理時間の計測用

dt_now = datetime.datetime.now()  # 現在日時

dt_date_str = dt_now.strftime('%Y/%m/%d %H:%M')

print(dt_date_str)



QUERY = '〇〇〇'  # 検索ワード

LIMIT_DL_NUM = 400               # ダウンロード数の上限

SAVE_DIR = '---------'  # 出力フォルダへのパス(フォルダがない場合は自動生成する)

FILE_NAME = 'trc'                       # ファイル名(ファイル名の後ろに0からの連番と拡張子が付く)

TIMEOUT = 60                     # 要素検索のタイムアウト(秒)

ACCESS_WAIT = 1                  # アクセスする間隔(秒)

RETRY_NUM = 3                    # リトライ回数(クリック、requests)

DRIVER_PATH = '-------'        # chromedriver.exeへのパス



# Chromeをヘッドレスモードで起動

options = Options()

options.add_argument('--headless')

options.add_argument('--no-sandbox')

options.add_argument('--disable-dev-shm-usage')

options.add_argument('--start-fullscreen')

options.add_argument('--disable-plugins')

options.add_argument('--disable-extensions')

driver = webdriver.Chrome(DRIVER_PATH, options=options)



# タイムアウト設定

driver.implicitly_wait(TIMEOUT)

tm_driver = time.time()

print('WebDriver起動完了', f'{tm_driver - tm_sum:.1f}s')



# Google画像検索ページ

url = f'https://www.google.com/search?q={QUERY}&tbm=isch'

driver.get(url)



tm_geturl = time.time()

print('Google画像検索ページ取得', f'{tm_geturl - tm_driver:.1f}s')



tmb_elems = driver.find_elements_by_css_selector('#islmp img')

tmb_alts = [tmb.get_attribute('alt') for tmb in tmb_elems]



count = len(tmb_alts) - tmb_alts.count('')

print(count)



while count < LIMIT_DL_NUM:

    # ページの一番下へスクロールして新しい画像を表示

    driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')

    time.sleep(4)



    # 画像取得

    tmb_elems = driver.find_elements_by_css_selector('#islmp img')

    tmb_alts = [tmb.get_attribute('alt') for tmb in tmb_elems]



    count = len(tmb_alts) - tmb_alts.count('')

    print(count)



# 画像をクリックすると表示される領域を取得

imgframe_elem = driver.find_element_by_id('islsp')



# 出力フォルダ作成

os.makedirs(SAVE_DIR, exist_ok=True)



# HTTPヘッダ作成

HTTP_HEADERS = {'User-Agent': driver.execute_script('return navigator.userAgent;')}

print(HTTP_HEADERS)



# ダウンロード対象の拡張子

IMG_EXTS = ('.jpg', '.jpeg', '.png', '.gif')



# 拡張子取得

def get_extension(url):

    url_lower = url.lower()

    for img_ext in IMG_EXTS:

        if img_ext in url_lower:

            extension = '.jpg' if img_ext == '.jpeg' else img_ext

            break

    else:

        extension = ''

    return extension



# urlの画像を取得しファイルへ書き込む

def download_image(url, path, loop):

    result = False

    for i in range(loop):

        try:

            r = requests.get(url, headers=HTTP_HEADERS, stream=True, timeout=10)

            r.raise_for_status()

            with open(path, 'wb') as f:

                f.write(r.content)

        except requests.exceptions.SSLError:

            print('***** SSL エラー')

            break  # リトライしない

        except requests.exceptions.RequestException as e:

            print(f'***** requests エラー({e}): {i + 1}/{RETRY_NUM}')

            time.sleep(1)

        else:

            result = True

            break  # try成功

    return result



tm_thumbnails = time.time()

print('画像取得', f'{tm_thumbnails - tm_geturl:.1f}s')



# ダウンロード

EXCLUSION_URL = 'https://lh3.googleusercontent.com/'  # 除外対象url

count = 0

url_list = 

for tmb_elem, tmb_alt in zip(tmb_elems, tmb_alts):



    if tmb_alt == '':

        continue



    print(f'{count}: {tmb_alt}')



    for i in range(RETRY_NUM):

        try:

            # 画像をクリック

            tmb_elem.click()

        except ElementClickInterceptedException:

            print(f'***** click エラー: {i + 1}/{RETRY_NUM}')

            driver.execute_script('arguments[0].scrollIntoView(true);', tmb_elem)

            time.sleep(1)

        else:

            break  # try成功

    else:

        print('***** キャンセル')

        continue  # リトライ失敗



    # アクセス負荷軽減用のウェイト

    time.sleep(ACCESS_WAIT)



    alt = tmb_alt.replace("'", "\\'")

    try:

        img_elem = imgframe_elem.find_element_by_css_selector(f'img[alt=\'{alt}\']')

    except NoSuchElementException:

        print('***** img要素検索エラー')

        print('***** キャンセル')

        continue



    # url取得

    tmb_url = tmb_elem.get_attribute('src')  # サムネイル画像のsrc属性値

 

    for i in range(RETRY_NUM):

        url = img_elem.get_attribute('src')

        if EXCLUSION_URL in url:

            print('***** 除外対象url')

            url = ''

            break

        elif url == tmb_url:  # src属性値が遷移するまでリトライ

            print(f'***** urlチェック: {i + 1}/{RETRY_NUM}')

            #print(f'***** {url}')

            time.sleep(1)

            url = ''

        else:

            break



    if url == '':

        print('***** キャンセル')

        continue



    # 画像を取得しファイルへ保存

    ext = get_extension(url)

    if ext == '':

        print(f'***** urlに拡張子が含まれていないのでキャンセル')

        print(f'{url}')

        continue



    filename = f'{FILE_NAME}{count}{ext}'

    path = SAVE_DIR + '/' + filename

    result = download_image(url, path, RETRY_NUM)

    if result == False:

        print('***** キャンセル')

        continue

    url_list.append(f'{filename}: {url}')



    # ダウンロード数の更新と終了判定

    count += 1



    if count >= LIMIT_DL_NUM:



        break



tm_end = time.time()

print('ダウンロード', f'{tm_end - tm_thumbnails:.1f}s')

print('------------------------------------')

total = tm_end - tm_sum

total_str = f'トータル時間: {total:.1f}s({total/60:.2f}min)'

count_str = f'ダウンロード数: {count}'

print(total_str)

print(count_str)



# urlをファイルへ保存

path = SAVE_DIR + '/' + '_url.txt'

with open(path, 'w', encoding='utf-8') as f:

    f.write(dt_date_str + '\n')

    f.write(total_str + '\n')

    f.write(count_str + '\n')

    f.write('\n'.join(url_list))



driver.quit()

ここから詳しくコードを解説します。

使用ライブラリ宣言

import requests

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

import os

import time

import datetime

from selenium.common.exceptions import NoSuchElementException

from selenium.common.exceptions import ElementClickInterceptedException

今回使用したライブラリは大まかに5つ。

requestsはメソッドを操作しやすくしたもの
import requests

webスクレイピングやwebAPIを使いwebからデータを取得したいときに使う。

selenium
from selenium import webdriver

from selenium.webdriver.chrome.options import Options

from selenium.common.exceptions import NoSuchElementException

from selenium.common.exceptions import ElementClickInterceptedException

seleniumはブラウザを自動的に操作するライブラリです。

seleniumの使い方は以下のサイトにわかりやすくまとまっていたので参考にしてください。

【Python】Seleniumとは?Webブラウザ操作の自動化方法を徹底解説

os
import os

osに存在している様々な機能を利用するためのモジュールです。

主にファイルやディレクトリのを操作する際に用います。

time
import time

timeはプログラム内で現在時刻を確認したり処理を一時停止できるモジュールです。

datetime
import datetime

datetimeは日付をプログラムから取得でき、日付や時間の表示を可能にするモジュールです。

プログラムの実行状況を記録

tm_sum = time.time()  # 処理時間の計測用

dt_now = datetime.datetime.now()  # 現在日時

dt_date_str = dt_now.strftime('%Y/%m/%d %H:%M')

print(dt_date_str)

プログラムの処理時間と現在日時を表示します。

検索内容の指定

QUERY = '〇〇〇'  # 検索ワード

LIMIT_DL_NUM = 400               # ダウンロード数の上限

SAVE_DIR = '---------'  # 出力フォルダへのパス(フォルダがない場合は自動生成する)

FILE_NAME = 'trc'                       # ファイル名(ファイル名の後ろに0からの連番と拡張子が付く)

TIMEOUT = 60                     # 要素検索のタイムアウト(秒)

ACCESS_WAIT = 1                  # アクセスする間隔(秒)

RETRY_NUM = 3                    # リトライ回数(クリック、requests)

DRIVER_PATH = '-------'        # chromedriver.exeへのパス

検索キーワードや画像のダウンロード枚数の指定をします。

出力フォルダへのパスと、chromedriver.exeのパスはご自身の環境のパスを指定してください。

chromeの起動

options = Options()

options.add_argument('--headless')

options.add_argument('--no-sandbox')

options.add_argument('--disable-dev-shm-usage')

options.add_argument('--start-fullscreen')

options.add_argument('--disable-plugins')

options.add_argument('--disable-extensions')

driver = webdriver.Chrome(DRIVER_PATH, options=options)

ここではoptionchromeの起動条件を追加していきchromeを起動します。今回はヘッドレスモードで起動します。(ここは個人の好みで調節してください。)

起動条件などは以下のサイトでまとめてくれています。

【Python3】SeleniumのChrome起動オプションについて | せなブログ

残りのプログラムコードの大まかな処理の流れ

while count < LIMIT_DL_NUM:
    # ページの一番下へスクロールして新しい画像を表示
    driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
    time.sleep(4)


    # 画像取得
    tmb_elems = driver.find_elements_by_css_selector('#islmp img')
    tmb_alts = [tmb.get_attribute('alt') for tmb in tmb_elems]


    count = len(tmb_alts) - tmb_alts.count('')
    print(count)

ページをスクロールして画像を取得する。

# ダウンロード対象の拡張子
IMG_EXTS = ('.jpg', '.jpeg', '.png', '.gif')

ダウンロードする画像の拡張子を指定する。

# 拡張子取得
def get_extension(url):
    url_lower = url.lower()
    for img_ext in IMG_EXTS:
        if img_ext in url_lower:
            extension = '.jpg' if img_ext == '.jpeg' else img_ext
            break
    else:
        extension = ''
    return extension

web上の拡張子を取得する。

# ダウンロード
EXCLUSION_URL = 'https://lh3.googleusercontent.com/'  # 除外対象url
count = 0
url_list = []
for tmb_elem, tmb_alt in zip(tmb_elems, tmb_alts):


    if tmb_alt == '':
        continue


    print(f'{count}: {tmb_alt}')


    for i in range(RETRY_NUM):
        try:
            # 画像をクリック
            tmb_elem.click()
        except ElementClickInterceptedException:
            print(f'***** click エラー: {i + 1}/{RETRY_NUM}')
            driver.execute_script('arguments[0].scrollIntoView(true);', tmb_elem)
            time.sleep(1)
        else:
            break  # try成功
    else:
        print('***** キャンセル')
        continue  # リトライ失敗


    # アクセス負荷軽減用のウェイト
    time.sleep(ACCESS_WAIT)


    alt = tmb_alt.replace("'", "\\'")
    try:
        img_elem = imgframe_elem.find_element_by_css_selector(f'img[alt=\'{alt}\']')
    except NoSuchElementException:
        print('***** img要素検索エラー')
        print('***** キャンセル')
        continue


    # url取得
    tmb_url = tmb_elem.get_attribute('src')  # サムネイル画像のsrc属性値
 
    for i in range(RETRY_NUM):
        url = img_elem.get_attribute('src')
        if EXCLUSION_URL in url:
            print('***** 除外対象url')
            url = ''
            break
        elif url == tmb_url:  # src属性値が遷移するまでリトライ
            print(f'***** urlチェック: {i + 1}/{RETRY_NUM}')
            #print(f'***** {url}')
            time.sleep(1)
            url = ''
        else:
            break


    if url == '':
        print('***** キャンセル')
        continue


    # 画像を取得しファイルへ保存
    ext = get_extension(url)
    if ext == '':
        print(f'***** urlに拡張子が含まれていないのでキャンセル')
        print(f'{url}')
        continue


    filename = f'{FILE_NAME}{count}{ext}'
    path = SAVE_DIR + '/' + filename
    result = download_image(url, path, RETRY_NUM)
    if result == False:
        print('***** キャンセル')
        continue
    url_list.append(f'{filename}: {url}')


    # ダウンロード数の更新と終了判定
    count += 1


    if count >= LIMIT_DL_NUM:


        break

画像をクリックし、URLを取得してリスト化する。

URLから画像を保存する。この際に、後で扱いやすいようにファイル名を整える。


まとめ

今回はgoogle chromeを使って画像スクレイピングを行った。

500枚ほど画像が欲しかったのだが、どうしても400枚画像を読み込んだところで処理がフリーズしていまった。

断念して今回は400枚の画像をダウンロードした。

今後より多くの画像を保存できるようにプログラムを変える必要がある。




また、画像判別のモデルを作る予定なので画像の水増しが必要だ。



今回ダウンロードした画像をクラスタリングしてどのくらい分類できるか調べるのが今後の課題だ。


進捗あったらまた書きます。

んじゃ!!

はてなブログでプログラミング言語を記述する方法

昨日上げたpythonのプログラムコード見づらいなー

こんちゃ!だみーです

はてなブログpythonを記述するときは設定を変更した方が見やすいようです。

はてなブログの設定


まず、ブログの設定を開きます。


ブログの記述方法をはてな記法に変更し、保存します。


これで準備完了です。

記述方法

プログラムコードを記述する際は以下のように言語を指定して記述します。

 >|python|
 import numpy as np
 arr = np.array([1, 2, 3])
 ||<  

使用言語のところを変更すれば様々なコードを記述できます

プレビュー

import numpy as np
arr = np.array([1, 2, 3])

昨日上げたブログを見てひどく見づらかったので調べてみました。
参考になれば幸いです

んじゃ!