Python WebsiteBlockerを作成

##実行環境

* MacBook Air (11-inch, Mid 2012)
* JupyterLab (from Anaconda)
* Python 3.6.4

##参考元
教材元：
https://www.udemy.com/the-python-mega-course/learn/v4/content
ローカル・ループバック・アドレス（127.0.0.1）とは？
http://www.atmarkit.co.jp/ait/articles/0610/14/news021.html
サイトのURLにwwwはいるのか？
http://tzcat.com/wwwsite/
crontab MacOS
http://feb19.jp/blog/archives/000226.php

##まえがき
hostファイルにリダイレクトの記述を追加する。特定のurl(ドメイン)が入力されたとき、localhostサーバー上のurl(ドメイン)にリダイレクトさせる。が、localhost(俺のPC上)にはtwitterもyoutubeもredditのサービスはないので接続できない。
これを利用して、特定の時間だけ、特定のサイトへの接続を遮断できるよう.pyを作る。

hostファイル場所：

```
windows:
cd C:\Windows\Systems32\dirivers\etc

mac:
cd /etc
```

* hostファイルとは？: DNSの代わりにホスト名とIPアドレスの紐付けを指定するものです。 通常、自分が使っているコンピュータに存在して、そのコンピュータにのみ参照されるファイルです。テキストファイル。参考元：http://help.dozens.jp/post/knowhow/hosts_file/
* DNSとは？: IPアドレスとドメイン名を紐つけるして管理するシステムのこと。IPアドレスはインターネット上住所(数値)。ドメインはwww.~.com的なもの。IPアドレスとドメインの組み合わせがあり、1:1対応している。参考本：https://wa3.i-3-i.info/word1287.html

##寄り道 絶対パスを知る
macで`pwd`せず絶対パスをしる方法。フォルダを開く、フォルダ上部のフォルダ名が記述されているところに、小さなフォルダのアイコンがある。ばっかもーんそいつが絶対パスだ！追えー！で、terminalかテキストエディターにでもドラッグすれば絶対パス、ゲットだぜ！
windows?しらね。

##website blocker.py

```py

from datetime import datetime as dt
import time

hosts_path=r"/etc/hosts"
redirect = "127.0.0.1"
#wwwはあってもなくてもいい
website_list = ["www.youtube.com", "youtube.com", "www.twitter.com", "twitter.com", "www.reddit.com", "reddit.com"]

while True:
    #Working Time, 9:00~17:00
    if 9<=dt.now().hour<=17:
        with open(hosts_path, "r+") as file:
            content_list = file.read().split()
            for website in website_list:
                if website not in content_list:
                    file.write(redirect+" "+website+"\n")
    else:
        print("Party Time")
        with open(hosts_path, "r+") as file:
            content = file.readlines()
            file.seek(0)
            for line in content:
                if not any(website in line for website in website_list):
                    file.write(line)
            #現在stream以降を切り捨て
            file.truncate()
        time.sleep(10)
        
    
#これを実行すると通常ユーザーだとperimissin error
```
1. `host_path`はhostsファイルの場所。こいつを書き換える。hostファイルの書き換えには管理者権限がいるため、terminal上で実行しても、permission errorが出る。`su`で管理者権限上で実行可能。
2. 変数`redirect`はlocalhostのIPアドレスである。このIPアドレスに再接続させる。
3. wwwはつけても、つけなくてもyoutubeには行ける。これは基本的に別のwebページおいても言える。サイト側で設定できるようだ。無難にwww有り無しどちらもリストへ登録。
4. 現在の時間を`datetime.now().hour`で取得する。今回は午前9時~午後17時までならTrueになる。`dt`なのは`datetime`をimportするときに`dt`って呼ぶよと指定したから。
5. hostファイルはテキストファイル。`open`で文字列として呼び出せる。中にサイトurlがない場合は、`127.0.0.1 url \n`の形で最後尾に文を追加している。
6. `file.write`でなぜ最後尾に追加できるかというと、`read`メソッドで、streamと呼ばれるファイルを読み込むため位置情報てきなものが最後尾にあるから。軽い説明：`open`するとstreamは初期位置最初の文字の前にいる。`read`するとファイルをstreamが先頭から末尾まで動いて読み込む。`read`のあと、streamの位置は末尾に留まる。`read`や`write`はストリームの位置から始まるため、末尾に行が追加された。つまり`read`したとに、もっかい`read`してもファイルの文字列は呼び出せない。なぜなら、streamが一度目の`read`で末尾に動き、末尾以降に文字はないはずだからである。
7. 時間外の場合、hostファイルから`127.0.0.1 url \n`の記述を削除する。`seek(0)`はstreamの位置を初期位置に戻す。(文字列のindex0の位置へ)。`write`は現在のstream位置から文字を上書きしていく。これも試すとわかりやすいんだけど、言葉だとわかりにくいね。`truncate()`は現在のストリーム位置以降の文字列を切り捨て削除する。stremについての詳細は後述。
8. `time.sleep(10)`は10秒待つ。つまり10秒ごとにwhile文が実行される。


##ファイルのstreamについて
アメ公はカーソルとかよんだり、公式ドキュメントはstreamと読んでたりする。公式ドキュメントのstreamで呼ぶ。

```py

with open("test.txt", "w+") as file:
    file.write("line1\n")
    file.write("line2\n")
    file.write("line3\n")

#1
    content = file.read()
    print(content)
>>>
    
#2
    file.seek(0)
    content = file.read()
    print(content)
>>>line1
   line2
   line3

```
1. `open`において、様々なモード(`w`,`r`,`a`)などがあるが、`+`をつけると動作を追加できる。`w+`は読み込み、書き込みモード。つまり`test.txt`ファイルに3行を書きこんだ。`test.txt`が存在しない場合は`test.txt`が現在の作業ディレクトリに作成される。
2. 1回目のprint()では何も表示されない。2回めは全文が表示される。なぜだろう？の答えがstream。streamは位置情報のようなもの。初期位置はファイルの先頭いる。動作ごとに、移動を行う。
3. このファイルでのstreamの動きは以下のような感じ。streamが`write`によって与えられた文字列をstreamが動きながら書き込んでいく。結果streamの位置は末尾になる。

```
#1
(stream初期位置)

#2 file.write("line1\n")。行書き込み
line1\n(stream位置)

#3 file.write("line2\n")。別の行書き込み
line1\n
line2\n(stream位置)

#3 file.write("line3\n")。別の行書き込み
line1\n
line2\n
line3\n(stream位置)
```

4.`read`メソッドはstream位置以降を読み込む。つまり、現在のstream位置以降に文字は存在しないため何も読み込まない
5.`seek(0)`でstreamの位置を先頭に動かせる。
6.2回目のprintではsreamが先頭に存在するため`read`で文字列を読み込むことができた。

###writeの上書き
test.txtの中身は下記とする。

```py
#test.txtの中身
>>>this is test.txt

with open("test.txt", "w") as file:
    file.write("apple")
    print(file.read())
>>>is test.txt
    
    file.seek(0)
    print(file.read())
>>>appleis test.txt
```
1. streamの初期位置は先頭にあるので、`write`は先頭からすでに存在する文字列を`apple`で上書きしていく。indexで例えるとappleは長さ5なので、0から4までの元の文字列は"this "なので、この部分が"apple"に置き換えられた。同時に、streamの位置も"apple"の直後まで移動した。index位置で例えるならindex4,5の間なイメージ。
2. `read`はstream位置から後のを読み込むため、index5から読み込まれた。"is test.txt"が出力される。
3. `seek(0)`で戻せば先頭から読みこめる。
4. 単純に最初から文末に行を追加したい場合は、`open("fike_path", "a")`と`a`のappendモードでファイルを呼び出せばいい。`a`のモードで呼び出した場合は、`write`メソッドで渡した文字列が文末に追加される。


##website_blocker.pyをcrontabで自動実行させる。
メモ：
terminal上のコマンド

* `control + c` : 現在実行中のプロセスを強制終了。KeyboardInterrupt。無限ループなどを終了したりするときにも使える。
* `control + z` : 中断して、一個前の画面に戻る？中断してるので再会もできる
* `su` : 管理者権限画面に移行。passwordを入力する必要がる
*  `sudo crontab -e` : crontabを編集するvimの画面に入る。ここに記述して保存することで様々な動作を実行させることができる。

vimの画面から抜け出す方法：
esc押してeditモードをやめる。続けて以下でコマンドを入力可能。
control + xしてyしてenterじゃ保存できなくね？←unixだけ？

* :q 保存済みのファイルを開いているvimから抜ける
* :q! 保存しないで抜ける
* :wq 保存して抜ける

```
#terminalで
sudo crontab -e
@reboot python3 /home/user_name(ユーザー名)/applications/website_blcker.py
escキー
:wq
```

1. これで再起動後、のwebsite_blocker.pyが自動実行される。
2. プロセスを強制終了このwebsite_blocker.pyを止められる。windowのほうがタスクマネージャーをすぐ開ける関係でプロセス終了しやすいな。


あとがき：
vim画面から抜けられなくて最初焦った