Search 4 Truth

Pythonと仮想通貨

【Python】英単語帳を作る

さて、今年も受験シーズンが本格的にはじまりセンター試験の日になりましたね。
去年の今頃は私も勉強に勤しんでいました。

そんな訳ですが、今回はPythonを使ってフラッシュ英単語帳を作っていきたいと思います。”フラッシュ”というのは私が勝手に名付けたものですが、高速で流れる数値を暗算していくフラッシュ暗算を想像してみたらわかると思います。これの英単語バージョンです。

プログラムの大まかな流れは、英単語サイトのスクレイピング→ファイルに書き込み→英語と日本語に分ける→英語と日本語を交互に出していくというものです。使い方は英単語が出てきて数秒後に日本語(解答)が出てきます。英単語が流れてる間に日本語を想像する、という単純なものです。同一サイトの過度なスクレイピングはサーバー負担の原因となるので、ファイルに書き込んでしまいます。

モジュール

  • BeautifulSoup(外部モジュール pip3 install BeautifulSoup4)
  • random
  • urllib
  • time
  • os
  • re

スクレイピングの対象

http://www7b.biglobe.ne.jp/~browneye/english/
今回はTOEIC頻出単語400点コースを対象としました。

コード

from bs4 import BeautifulSoup as bs
import urllib.request as ur 
import re
import random 
from time import sleep
import os

def Soup():
    url = 'http://www7b.biglobe.ne.jp/~browneye/english/TOEIC400-1.htm'
    req = ur.urlopen(url)
    html = bs(req,"html.parser")
    html = str(html)
    return html

#url =  スクレイピング対象のURL
#htmlを戻り値とする(文字列の同士の正規表現なのでstrをつける)

def Re():
    pa = '<td>(.+)</td>'   
    ma = re.findall(pa,Soup())
    return ma

#pa = 正規表現のパターン(tdタグに囲まれた文字列)を格納 
#ma = 上記の正規表現にマッチする文字列をリストで格納
#変数maを戻り値とする

以前紹介したスクレイピング正規表現の型を流用しています。

s4t.hatenablog.com

画像はサイトの表記ミスだと思いますが、英語、日本語訳、品詞の順番に全て関数Reの戻り値に格納されます。

f:id:lisbeths:20180113162938p:plain

if not os.path.exists('tango.txt'): 
    for i in Re():
        with open('tango.txt','a') as a:
            a.write(i + '\n'#もし"tango.txt"というファイルが存在しなかったら
#”tango.txt"というファイルを生成し英語、日本語訳、品詞を順番に書き込む

生成されたtango.txtはこんな感じ。

f:id:lisbeths:20180113163844p:plain

else:
    with open('tango.txt','r') as r:
        text = r.read().split('\n')
        jp = text[1::3]
        en = text[::3]
        
        while True:
            ran = random.randint(0,len(jp) - 1)
            print(en[ran])
            sleep(2)
            print(jp[ran])
            print('')
            sleep(1)

#"tango.txt"が生成されていた場合
#"tango.txt"を読み込み変数textに段落でsplitしリストとして格納

#下記を無限ループ 擬似乱数はループ内で再定義する必要があるの
#変数enとjpにそれぞれ英語と日本語訳を格納(スライスの説明は略)
#変数ranに0から変数jpのリストに格納されている数から1引いた数までで擬似乱数を格納
#変数jpのインデックスに擬似乱数を入れて出力、sleep2秒、変数enの...、sleep1秒

全体像。

from bs4 import BeautifulSoup as bs
import urllib.request as ur 
import re
import random 
from time import sleep
import os

def Soup():
    url = 'http://www7b.biglobe.ne.jp/~browneye/english/TOEIC400-1.htm'
    req = ur.urlopen(url)
    html = bs(req,"html.parser")
    html = str(html)
    return html

def Re():
    pa = '<td>(.+)</td>'   
    ma = re.findall(pa,Soup())
    return ma

if not os.path.exists('tango.txt'):
    for i in Re():
        with open('tango.txt','a') as a:
            a.write(i + '\n')
            
else:
    with open('tango.txt','r') as r:
        text = r.read().split('\n')
        en = text[::3]
        jp = text[1::3]
        
        while True:
            ran = random.randint(0,len(jp) - 1)
            print(en[ran])
            sleep(2)
            print(jp[ran])
            print('')
            sleep(1)

実行してみました。

f:id:lisbeths:20180113170746g:plain

英単語は反復練習!!!(って誰かが言ってた)

完。

【仮想通貨】自動取引bot制作日記 -1日目-【Python】

タイトル通り!今日からPythonを使い仮想通貨の自動取引botを作っていく過程を日記仕立てでお送りします。

今回は"仮想の"仮想通貨自動取引botをつくるまでが目標です。"仮想の"というのはいわばバーチャル取引のことで実際の取引を行わず数字が上がり下りをする様を眺めて差額でどのくらい損益が出るのかをニヤニヤしながら見守るものを指します。

今回はbitFlyerAPIのTickerを2秒毎に取得して買値を固定し売値をwhileでぶん回して更新し続けどのくらい損益が出るのかを見守っていきます。

買値は大学生の現実的な価格(だと勝手に思っている)0.06BTC(約108,000円)を買います。売買手数料は加味しません。

では作っていきます。

使った環境

  • MacBook Air Early 2015 Sierra 10.12.6
  • Python 3.6.2 pip3
  • iTerm2(コマンドプロント)
  • CotEditor(エディター)

日記形式なので今後は新しいものが追加される度にそれだけを紹介します

モジュール

  • time(標準モジュール)
  • requests(外部モジュール pip3 install requests)

実践

なにはともあれAPIを叩く。

import requests
from time import sleep

def bitflyer():
    URL = 'https://lightning.bitflyer.jp/v1/getticker'
    ticker = requests.get(URL).json() 
    price = int(ticker['best_ask']),int(ticker['best_bid'])
    return price

# ticker = getリクエストでjson形式でtickerを取得
# price = 買値と売値を格納 2000000.0のよう返ってくるのでintで小数点以下を切る
# return 戻り値として上記の変数priceをタプルで戻す


国内の取引所のAPIの叩きかたは前回の記事で扱いました〜。(初新着エントリーしました!ありがとうございます!)

s4t.hatenablog.com

wallet = 0.06
ask = bitflyer()[0] * wallet

#変数walletに買うBTCの枚数を格納
#whileの外で買値を定義・固定(更新しないように)
#変数askに現在の買値に変数walletをかける

while True:
    bid = bitflyer()[1] * wallet
    profit = bid - ask
    print(profit)
    sleep(2)[f:id:lisbeths:20180112155108p:plain]

# bid = 買値を出し毎回更新する
# profit = ひきざん
# 出力
# スリープ(2びょう〜)

全体像

import requests
from time import sleep

def bitflyer():
    URL = 'https://lightning.bitflyer.jp/v1/getticker'  
    ticker = requests.get(URL).json() 
    price = int(ticker['best_ask']),int(ticker['best_bid'])
    return price 

wallet = 0.06
ask = bitflyer()[0] * wallet

while True:
    bid = bitflyer()[1] * wallet
    profit = bid - ask
    print(profit)
    sleep(2)

とりあえず1BTCで動かす。
うぉおおめちゃもうかってるぅう!!!!利確ぅ!!(ctrl + c)(池沼)

f:id:lisbeths:20180112153116g:plain

続いて0.06BTC。

f:id:lisbeths:20180112154355g:plain

(完)

【Python対応】crontabを設定するために最低限覚えたいvim

作ったプログラムはcrontabで定期実行していますが、設定する上で必ず引っかかるのがvimです。

今回はvimの文法を一から覚えるのは酷なので最低限必要なコマンドを紹介します。

1,crontabを開く

コマンドプロンプトを開きます。プリインストールのもので構いません。(私はiTermを使いました)

crontab -e

で編集します。

2, 編集する

先程のコマンドを実行したら編集するためにInsert(書き込み)モードに入ります。キーボードで「i」を打ちます。

f:id:lisbeths:20180110133324p:plain

入りました。これで編集可能になりました。

さっそく設定していきます

crontabの設定の構図としては

分 時間 日 月 曜日 Pythonのpath ディレクトリー/test.py

になっています。

毎日午前7時にtest.pyを実行する設定をしていきます。

まずは日時を設定していきます。

0 7 * * * 

これで完了です。 毎日7時なので、日、月、曜日は指定する必要は無いところは「*」と記述します。

次にPythonのpathを通すために別のウィンドウで以下のコードを入力・実行して下さい。

witch Python3

3の部分は個々のバージョンに合わせてください

/usr/local/bin/Python3

と出たので先程のcrontabの設定に戻り日時の隣におきます。

0 7 * * *  /usr/local/bin/Python3 

次に動かしたいプログラムがあるディレクトリーを階層ごとに記述します。

0 7 * * *  /usr/local/bin/Python3 desktop/py/test.py

私は"デスクトップ"の"py"というフォルダにある"test.py"というプログラムを指定しました。

3, 保存する

設定が終わったら、保存をします。そのままウィンドウを消してはいけません。

キーボード左端の「Esc」キーを押してInsertモードを終了します。

次に「:」を押し「wq」を押すと保存されます。

f:id:lisbeths:20180110141838p:plain

おまけ

crontab -l

で保存した設定が見られます。

f:id:lisbeths:20180110142051p:plain


今回はMacBookでの設定を紹介しましたが、パソコンを一日中動かしたくは無いという方はRaspberry Piを使用するのも手です。(当ブログで紹介してるcrontabを伴うプログラムは全てラズパイで動かしています)

【Python】LINEに電車の遅延情報を送る

さて、前回の続きです。

s4t.hatenablog.com

今回は上記の記事の発展版であるスクレイピングしたデータをLINEに送る、というプログラムを作っていきます。対象となるサイトは、鉄道運行情報様のサイトです。

こちらのサイトをスクレイピングしてLINE NotifyのAPIを使い指定した時間に通知を送る、というところまでが今回の目標です。まずは前回の記事を参考にしてLINEで任意の文字列を送るところまでやってみてください。

使用した環境

モジュール

  • BeautifulSoup(コマンドプロンプトにて pip3 install BeautifulSoup4 でインストール)
  • urllib(標準モジュールのためインストール不要)
  • re(”)

コード

私がスクレイピングする際にいつも使っている型を紹介します。

from bs4 import BeautifulSoup as bs
import urllib.request as ur 
import re

def Soup():
    url = 'url'
    req = ur.urlopen(url)
    html = bs(req,"html.parser")
    return html
    
#def Re():
    #pa = '正規表現'
    #ma = re.findall(pa,Soup())
    #return ma

簡単に説明すると、関数Soupでリンク先のhtmlを取得して関数Reの正規表現で欲しい情報だけを抽出するというものです。大体のhtmlは上記の関数Soupで抜けます。正規表現は抽出するhtmlによってその都度変わるのでこれに関しては以下の記事を参考にしてみて下さい。上記のコードによく使う正規表現の型かきましたが今回は使わないのでコメントアウトしました。

qiita.com


正直な話どの記事を読んでもの正規表現は理解できなかったのでいつもノリでやっています。

とりあえず中央線の運行情報が乗ったURLを関数Soupのurlに代入してhtmlを取り出してみます。

f:id:lisbeths:20180110105859p:plain


ここを取り出したいわけなのですよ。で、いちいちこの文字列を探すのが面倒なのでChromeでhtmlの視覚的に見える要素からそれがどのhtmlなのかを探す方法を紹介します。

中央線のページを使ってやっていきます。まずは右クリックで検証をクリック。

f:id:lisbeths:20180110110749p:plain

右にhtmlがズラッとでてきました。そしてなんにもない空白をクリックしてhtml側に標準を合わせます。(表現がわからないからわかって)

f:id:lisbeths:20180110111413p:plain

「command + f」を押す。

f:id:lisbeths:20180110111837p:plain

抽出したい文字列を入力。→ 一致。

f:id:lisbeths:20180110150955p:plain

簡単にまとめるとこう。

f:id:lisbeths:20180110112920p:plain

このようなhtmlがとれました。この中にある文字列を抽出していきます。

<div class="corner_block_row_detail_d" style="padding-left:5px;">
現在、平常通り運転しています。</div>
from bs4 import BeautifulSoup as bs
import urllib.request as ur 
import re

def Soup():
    url = 'http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_chuokaisoku'
    req = ur.urlopen(url)
    html = bs(req,"html.parser")
    return html

#BeautifulSoupでhtmlを取得して変数htmlを戻り値としました
  
match = Soup().find(class_="corner_block_row_detail_d").string.replace('\n','')

#変数matchに正規表現を書きました
#htmlが<div class>となっていたのでclassを指定します classとするとエラーがでるのでclass_とします 
#クラス名を先程取得した"corner_block_row_detail_d"をいれます。
#.stringでクラス内の文字列を抽出 無駄な改行があったので空白とreplaceしました

#出力します

print(match)

#「現在、平常通り運転しています。」、又は遅延情報など運行情報が出たら成功

実際に遅延情報をLINEに送ってみる

前回の記事のコードをそのまま流用しました。

from bs4 import BeautifulSoup as bs
import urllib.request as ur 
import re
import requests

def line(Me):
    line_notify_token = 'アクセストークン'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    message = '\n' + Me
    payload = {'message': message}
    headers = {'Authorization': 'Bearer ' + line_notify_token}
    line_notify = requests.post(line_notify_api, data=payload, headers=headers)

def Soup():
    url = 'http://www.jikokuhyo.co.jp/search/detail/line_is/kanto_chuokaisoku'
    req = ur.urlopen(url)
    html = bs(req,"html.parser")
    return html
    
match = Soup().find(class_="corner_block_row_detail_d").string.replace('\n','')
text = '中央線快速の運行情報\n> ' + match

#変数textで実際にLINEに送るテキストを編集しました

line(text)
    

実行

先程のコードを"LINE.py"として保存しました。実行してみます。

python3 LINE.py

できた〜

f:id:lisbeths:20180110131352p:plain

これをcrontabを使って指定した時間に通知が来るように設定すれば便利です。

s4t.hatenablog.com

寝る

【Python】LINE Notifyを使ってPythonから通知を送ってみる

LINE Notifyというサービスをご存知でしょうか。IFTTTやmythingsといったウェブサービスと連携して様々な通知を受け取ることができるLINEのサービスです。前回のブログで”LINE Notify”という固有名詞は出しませんでしたがこれもLINE Notifyを使って通知を送っています。

LINE notifyでは開発者向けにAPIを提供していてウェブサービスを連携しなくても通知を送ることができます。今回はPythonを使って通知を送るところまで紹介します。次回のブログではこれを応用し、スクレイピング結果をLINEで通知するプログラムを書きたいと思います。

使用した環境、モジュール

  • MacBook Air Early 2015 Sierra 10.12.6
  • Python 3.6.2
  • iTerm2(コマンドプロント)
  • requests(モジュール pip install requests でインストール)
  • アクセストーク

アクセストークンを取得する

1 以下のリンクでアクセストークンを取得します。
https://notify-bot.line.me/my/


2 トークンを発行するを選択

f:id:lisbeths:20180110005528p:plain

3 通知を行う方法を選択します。
"1:1でLINE Notifyから通知を受け取る"を選択するとLINE Notifyから直接通知が来ます。それ以外のグループを選択するとグループを通して通知が来ます。(グループを選択した場合はLINE Notifyをそのグループに招待する必要があります)トークン名を記入して(なんでもいい)発行するを選びましょう。

f:id:lisbeths:20180109212556p:plain


ちなみにトークン名は通知本文上部の”これ” です。

f:id:lisbeths:20180110003229p:plain


4 発行されました。
このページから...二度と発行されませんと書いてありますが表示されたコードはという意味でいくらでも再発行は可能です。スクショするなりメモするなりしておきましょう。

f:id:lisbeths:20180110003628p:plain

コード

import requests

def line(Me):
    line_notify_token = 'アクセストークン' #先程発行したコードを貼ります
    line_notify_api = 'https://notify-api.line.me/api/notify'
    message = '\n' + Me 
    #変数messageに文字列をいれて送信します トークン名の隣に文字が来てしまうので最初に改行しました
    payload = {'message': message}
    headers = {'Authorization': 'Bearer ' + line_notify_token}
    line_notify = requests.post(line_notify_api, data=payload, headers=headers)

line('Hello World!!') #関数lineの引数に任意の文字列を入れます

実行するとアクセストークン作成の説明の画像をご覧になって下さい。今回は通知を送るところまでです。次回は電車の遅延情報をスクレイピングしてLINEに通知を送る実践活用方法をご紹介します。

おまけ

さっきのコードにおまけ機能として複数のアクセストークンを扱うコードを作ってみました。第二引数に変数numを代入して指定したアクセストークンから通知を送るものです。私は天気予報や電車の運行情報などでグループを作りグループごとにアクセストークンを発行しました。

import requests

def line(Me,num):
    if num == 0:
        line_notify_token = 'アセストークン1'
    if num == 1:
        line_notify_token = 'アセストークン2'
    if num == 2:
        line_notify_token = 'アセストークン3'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    message = '\n' + Me
    payload = {'message': message}
    headers = {'Authorization': 'Bearer ' + line_notify_token}
    line_notify = requests.post(line_notify_api, data=payload, headers=headers)

【仮想通貨】取引所間の差額で確実に儲けるアービトラージに向けて【Python】

アービトラージ(裁定取引)とは

取引所によってコインの価格が違い、一番安く買える取引所で買い、一番高く売れるとろこで売ることによって差額で利益を得る手法のこと。取引所間の送金に多少の時間がかかるものの、価格が大きく変動する前に行えるため確実性が高いのが特徴。

今回やること

今回はpythonを使い各取引所の1BTCあたりの価格(ビットコイン)を取得し最適な取引所を出して差額でどのくらいの利益が出るのかを出してみます。対象となる取引所は日本国内のみ、8箇所(bitFlyer CoinCheck Zaif BTCBOX bitbank kraken QUOINEX FISCO)となります。国内には20近くの取引所がありますが今回はapiを提供している取引所に絞りました。非公式でモジュールを作っている方もいらっしゃいますが(pybitflyerなど)価格のみを取得できれば十分なのと記述方法をできるだけ統一したかったので使いませんでした。

使用した環境とモジュール

  • MacBook Air Early 2015 Sierra 10.12.6
  • Python 3.6.2
  • iTerm2(コマンドプロント)
  • requests(モジュール pip install requests でインストール)

実践

では早速やってみましょう。使うモジュールはrequestsのみです。tickerをrequestsを使いjson形式でレスポンスを得ますが、jsonはインポートしなくても使えたので下記コードには記述してません。まずは各取引所の価格を取得します。なるべく記述方法は統一しました。

import requests 

#ticker = getリクエストでjson形式でtickerが返ってきます
#price = 買値と売値を格納します 2000000.00のよう返ってくるのでintで小数点以下を切ります
#return 戻り値として上記の変数priceをタプルで戻します
#krakenの場合、文字列としての小数点が返ってくるので数値のfloatにしてからintで.0以下を切り離します

def bitflyer():
    URL = 'https://lightning.bitflyer.jp/v1/getticker'  
    ticker = requests.get(URL).json() 
    price = int(ticker['best_ask']),int(ticker['best_bid'])
    return price 
    
def coincheck():
    URL = 'https://coincheck.com/api/ticker'
    ticker = requests.get(URL).json() 
    price = int(ticker['ask']),int(ticker['bid'])
    return price

def zaif():
    url = 'https://api.zaif.jp/api/1/ticker/btc_jpy'
    ticker = requests.get(url).json()
    price = int(ticker['ask']),int(ticker['bid'])
    return price
    
def btcbox():
    url = 'https://www.btcbox.co.jp/api/v1/ticker'
    ticker = requests.get(url).json()
    price = int(ticker['buy']),int(ticker['sell'])
    return price

def bitbank():
    URL = 'https://public.bitbank.cc/btc_jpy/ticker'
    ticker = requests.get(URL).json()['data']
    price = int(ticker['buy']),int(ticker['sell'])
    return price

def kraken():
    url = 'https://api.kraken.com/0/public/Ticker?pair=XXBTZJPY'
    ticker = requests.get(url).json()['result']['XXBTZJPY']
    price = int(float(ticker['a'][0])),int(float(ticker['b'][0]))
    return price

def quoinex():
    url = 'https://api.quoine.com/products/5'
    ticker = requests.get(url).json()
    price = int(ticker['market_ask']),int(ticker['market_bid'])
    return price

def fisco():
    url = 'https://api.fcce.jp/api/1/ticker/btc_jpy'
    ticker = requests.get(url).json()
    price = int(ticker['ask']),int(ticker['bid'])
    return price


取引所ごとに関数を作りました。まとめて出力するとこんな感じ。買値と売値が格納された変数priceが戻り値とします。戻り値が複数あるのでタプルとして戻ります。

f:id:lisbeths:20180108231051p:plain


x = [bitflyer(),coincheck(),zaif(),btcbox(),bitbank(),kraken(),quoinex(),fisco()]
store = ['bitflyer','coincheck','zaif','btcbox','bitbank','kraken','quoinex','fisco']

#変数xに全ての取引所の買値と売値をリストで格納します
#変数storeには全ての取引所の名前をリストで格納します 

ask,bid = [],[]

#リストaskとリストbidを定義しておきます

for i in x:
    ask.append(i[0])
    bid.append(i[1])

#askとbidにxに格納した買値と売値を追加していきます

リストaskとbidを出力させてみました。見づらいですが、買値と売値に振り分けられていることがわかります。

f:id:lisbeths:20180108231741p:plain

dic = {} #辞書dicを定義
count = 0 #カウンター用の変数countに数値0を代入
for i in store: 
    dic.update({ask[count]:i}) 
    #辞書dicに買値が格納された変数askをキーとして前に定義してあった変数storeを順番に値としていきます
    #これにより価格と取引所の名前が紐付きました
    count += 1 #askのリストを順番に出すためのカウンターです 
ask_num = sorted(ask)[0] #変数ask_numにはリストaksを昇順ソートし最前にきたものを格納
best_ask = dic[ask_num] #変数ask_numをdicのキーとして入れると買値が一番安い取引所が出力されます 

#同じように売値でも
dic = {}
count = 0
for i in store:
    dic.update({bid[count]:i})
    count += 1
bid_num = sorted(bid,reverse=True)[0] #降順でソートし最前のものを格納
best_bid = dic[bid_num]

最適価格とその取引所名がわかりました。最後に計算をして終わります。

#文字列として一番安く買える取引所と一番安く高く売れる取引所を出力
#最高価格の売値と最低価格の買値を引いて区切り点をつけるフォーマットをしました
print(best_ask + ' で買い ' + best_bid + ' で売ると ' + str("¥{:,d}".format(bid_num - ask_num)) + ' の利益')

実行してみました。価格は売買手数料や送金手数料を加味していません。現在1BTCあたりの価格が200万前後なのでこの額でアビトラして単純計算でこのくらいになるよ〜というものです。

f:id:lisbeths:20180108234154p:plain

今回使用したコードはgithubにアップしておいたので、こっちを貼り付けて実行するほうがはやいです。

ビットコインの最適価格を出すやつ(アビトラ用)

PythonでMastodonのAPIをいじる【導入編〜tootまで】

最近話題のTwitterライクなSNSMastodonTwitterとの使い道の線引が微妙なやつですが、Pythonのモジュールが公開されていたので、遊んでみました。なにはともあれモジュールをインストールしていきます。

使用した環境

インストール

pip3 install Mastodon.py

コード

MastodonのSetupするやつ

導入

最初にMastodon用のディレクトリを作っておくことをおすすめします。(生成されたkyeファイルを使うため)この中に上記のコードををそのままメモ帳やエディタにコピーして拡張子を.pyにして保存してください。

f:id:lisbeths:20180105223043p:plain

次にコマンドプロンプトで、Mastodonディレクトリに移動します。私はデスクトップ上にMastodonディレクトリをおいたのでこのように打ちます。

 cd desktop/mastodon

そしてプログラムを起動させて...

python3 CreateKyes.py

このようにapp_keyとuser_keyが生成されたら成功です!(CreateKyes.pyは消しても構いません)

f:id:lisbeths:20180105223658p:plain

Tootする

最後にトゥートしてみましょう。Twitterでいうツイートですね。以下のコードをコピーして拡張子.pyで先程のmastodonディレクトリに入れて下さい。whileで無限ループさせてあるので文字を入力してreturnを押すとtootされ次のtootができるようになります。

つーとするやつ

 python3 toot.py

f:id:lisbeths:20180105233818g:plain

トゥートされました!

次回はMastodonAPIを使って遊んでいきたいと思います〜