csv」タグアーカイブ

pythonでCSVを読み込みクラスオブジェクトを配列に入れる

CSVを読み込みクラスオブジェクトを配列に入れる

CSV例,6列必要。1行目は除外する。米ヤフーファイナンスから日経平均株価データを取得すると、今日の分は取得できるのに、なぜか前日のデータが時間帯によって取得できない。そのため、取得できたデータと取得できないデータをCSVにしておいて使用する。

日付,高値,安値,始値,終値,調整終値

となっている。

index      High      Low    Open   Close    AdjClose  列数チェックが必要                                                               
2021-01-07,27624.730469,27340.460938,27340.460938,27490.130859,27490.130859
2021-01-08,28139.029297,27667.750000,27720.140625,28139.029297,28139.029297
2021-01-12,28287.369141,27899.449219,28004.369141,28164.339844,28164.339844
2021-01-13,28140.10,28503.43,28139.66,28456.59,28456.59
2021-01-14,28979.529297,28411.580078,28442.730469,28698.259766,28698.259766

クラスから実際のデータを取得するときは

df[0].indexとかdf[0].closeみたいにして取得する。つまり1行分が1オブジェクトの配列として登録されている。

#CSVにするときは、列数があっているかをチェックする。ヤフーファイナンスはAdjCloseがあるが、ほかはCloseしかない。
import os
import pandas_datareader.data as data
from datetime import datetime,timedelta

#日経平均株価データのクラスオブジェクト、カプセルデータ
class nikkeiClass:
    def __init__(self, cindex, chigh,clow,copen,cclose,cadjclose):
        self.index = cindex
        self.high = chigh
        self.low = clow
        self.open = copen
        self.close = cclose
        self.adjclose = cadjclose
#########################
end = datetime.now()
#start = datetime(end.year, end.month, end.day-8)#こっちだと月マタギでエラーになる。
start = end - timedelta(days=7)
print('start:',start.strftime("%Y/%m/%d"))
print('today:',end.strftime("%Y/%m/%d"))

df=[]
checkLineCount=0
#CSVを読み込む
ifile='/Users/toshiromaseda/Documents/blender/script/2021年1月14日日経.csv'
try:#ファイルが存在しないときのエラー処理try
    with open(ifile,'tr') as fin:
        for iline in fin:
            #try:
                tmp=iline.strip().split(",")#stripしてからsplit()だと理解している。
                if 'High' in tmp[0]:
                    continue
                if len(tmp) < 6:#全部で6列存在する。
                    print('ERROR 列の数があっていません。少ないようです。行数:',checkLineCount)
                    break
                #here
                df.append(nikkeiClass(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5]))
                checkLineCount+=1
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
    print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
    ifile.close()
    sys._exit()#ファイルがなければ終了

print(df[0].index) 
for f in df:
    print('日付:',f.index)


print('END')

 

pythonでTXTからCSV変換してMysqlへのインサート処理

#pythonメソッドは外部ファイルpy
#2020/12/21
#CSVをMysqlにインサート
#Test_Table_StockOption
#TXTからCSVに変換してCSVファイルを読み込んでMysqlのテーブルに登録を一括して行えるようにする。DB,テーブルは作成済とする。スタンドアローンでの利用

環境:MacOS BigSur、Python3、Mysql、JupiterLab Anaconda

#実行用

# MySQLdbのインポート
import MySQLdb
import os
import re
import sys
import datetime
import glob#ファイル一覧
import shutil#move

import methodMysql#個人用メソッド pyファイル
#本文は下にある。メソッドを先に記載しないと呼び出しでエラーになる。


#本文
########入力内容########################################################################
ifile='2020年12月23日AM7時39分.txt'#CSVはTXTから作成されるのでCSV名は不要
useTable='Table_StockOption'#Mysqlへ登録するテーブル、テスト用、通常用がある
useDate='2020/12/23'#オプション取り込みの日付
useMonth=1#月限 12月の作業はたいてい翌月である1月
########入力内容

#TXTをCSVに出力してからMysqlへ登録する。DB,テーブルは事前に用意されたものとする
###本文 ここでoutMojiMKIII()メソッドを使用している
path='/Users/toshiromaseda/Documents/2020年株関連/kabu_python/'
os.chdir(path)#ディレクトリ変更
print(os.getcwd())#ディレクトリ確認

csvfile='c_'+ifile.split('.')[0]+'.csv'

methodMysql.checkFile(ifile)#check 取り込み済みのファイルかどうかを調べる

try:
    ofile=open(csvfile,'tw') 
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
   print("ファイルが見つかりません", e)
   #print("強制終了")
   sys.exit()#ファイルがなければ終了
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

try:#ファイルが存在しないときのエラー処理try
    with open(ifile,'tr') as fin:
        for iline in fin:
            #ilineに、”コール”、”出来高”の文字がある行は無視するようにする
            #countで探すか 1行目、2行目は不要なのでDBにインサートしないための処理
            if iline.count('コール')>=1 or iline.count('出来高')>=1:
                continue#以下は実行されない
            try:
                ofile.write(methodMysql.outMojiMKIII(iline)+'\n')#MKIII改良版2020/12/18
                #次はMysqlに直接インサートするバージョンを作業する
            except Exception:
                print("do not")
        ofile.close()
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
    print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
    ofile.close()
    print("強制終了")
    sys.exit()#ファイルがなければ終了
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

#CSVからMysqlへ CSVファイルがないと実行できない。重複チェックなし
#csvToMysql(difileはCSVファイル名,dtablename、doptionDate日付、dmonth月限)
#テスト用テーブルTest_Table_StockOption
methodMysql.csvToMysql(csvfile,useTable,useDate,useMonth)

#Testが終わったら試す。 単独実行可能 但し、ファイルの移動先チェックがないので、他で移動がないことをチェックする必要あり
methodMysql.fileMove(ifile,'./option_python_execute')
methodMysql.fileMove(csvfile,'./option_python_execute')

#表、グラフを出力する 単独実行可能
methodMysql.selectMysql('Table_StockOption')

print("終わりました。")

メソッド 外部ファイルにしたmethodMysql.py これをimport methodMysql として読み込む

#pythonUseMysql2.ipynbで使用
# MySQLdbのインポート
import MySQLdb
import os
import re
import sys
import datetime
import glob#ファイル一覧
import shutil#move

#株探の先物オプション記事について、特定文字列について空白をカンマに置換処理するためのメソッド
#def latterHalf(text):数字を後ろから探す
#def outMojiMKIII(text):空白をカンマに置換処理
#def csvToMysql(difile,dtablename,doptionDate,dmonth):
#def checkFile(filename):fileが存在するかチェック。パスは固定
#def fileMove(file,path):file移動
#def selectMysql(tablename):select 



#メソッドを別ファイルにした。
#文字列の後ろ側の数字を後ろから探し、抜けていた場合0を埋める
def latterHalf(text):
    textout=text
    pattern=re.compile('[0-9]+')#findで正規表現ができない
    i=0
    checkArray=[]#タプルを入れる配列
    while i>=0:#数字を探す
      m=pattern.search(textout, i)
      if m:
        #print(m.start())
        #print(m.end())
        #これをタプル配列に入れて、N,N-1で差が大きいときに0を入れる
        #print(m.span())
        checkArray.append(m.span())
        i = m.end()#m.start() + 1#m.end()
      else:
        break
    n=len(checkArray)
    if n>=2:#nは最低2こ必要 最後と最後の1こ前の
        #print("[n-1][0]",checkArray[n-1][0])#0番目の1個目 [0](0,1)
        #print("[n-2][1]",checkArray[n-2][1])#0番目の2個目
        #個数はNだけど配列の指定はそれより1小さいのでN-1となる
        if (checkArray[n-1][0]-checkArray[n-2][1])>=6:
            print("put抜けている")
            #checkArray[n-1][1]の後ろに挿入する
            texttmp=textout[:checkArray[n-2][1]+2]+ '0' + textout[checkArray[n-2][1]+2:]
            textout=texttmp
    output=textout
    return output
#end def

def outMojiMKIII(text):
    #空白を削除する前に、空白の個数を数える
    #株探の仕様が変わったらここを変える。2020/12/16
    kuro=re.compile('[  ]+')#半角と全角の空白置換 半角全角が[半角全角]として入っている
    
    if text.count(' ',0,15)>=13:
           #空白13個はプット
            opt='put'
            textout=text.strip()#先頭、末尾の空白、改行を削除する
    else:
            #コールの場合、2種類あるのでそれをチェックする
            textout=text.strip()#先頭、末尾の空白を削除する
            check=kuro.sub(',',textout)#半角全角の空白を置換
            count=check.split(",")
            #print ('len count:',len(count))
            if len(count)>=5:#配列が5個以上なら、call,putが含まれる       
                opt='callandput'
            else:
                opt='onlycall'
    pattern=re.compile('[0-9]+')#findで正規表現ができない
    if opt=='onlycall' or opt=='callandput':
        #次に、「call,putあり」OR「Callのみ」かをチェックする。
        #optSub='callandput' 'onlycall'
        #callのみを先に処理して、put側を調べる
        matchobj=re.search('[0-9]+',textout)#最初の数字を探す
        if matchobj:
            #print('マッチした文字列:'+matchobj.group())
            #print('マッチした文字列グループ:',matchobj.groups())
            #print( '開始位置'+str(matchobj.start()) )#先頭位置は0番として数える 3番目(4文字目)に見つかった
            #print( '終了位置'+str(matchobj.end()) )#終了位置は次の番目を含んでいるので実際は1を引いた数が終了位置
            #print(matchobj.span())#'マッチした文字列の (開始位置, 終了位置) のタプル'+
            #2番めの数字を探す
            secondMatch=pattern.search(textout,matchobj.end())#compileを使用してpatternで再度位置を指定して探す
            if secondMatch:
                #print( '開始位置2:'+str(secondMatch.start()) )#先頭から数えて10番目に次の数字が見つかった
                #1番目と2番めの文字数が5以上空いていたら数字が抜けている事がわかる。
                #ここに0を埋める処理を入れる
                if secondMatch.start()-matchobj.end() >=5:
                    print('値が抜けてる')
                    # hash = "355879ACB6"
                    # hash = hash[:4] + '-' + hash[4:]
                    #文字列の挿入。#1番目の文字の3文字目くらいに0を追加する。
                    texttmp=textout[:matchobj.end()+2]+ '0' + textout[matchobj.end()+2:]
                    textout=texttmp
        #put側のチェック。再度optでチェックする
        if opt=='onlycall':
            #置換して終わる
            output=kuro.sub(',',textout)+',,,'
        elif opt=='callandput':
            #print('callandputの処理')
            tmp=latterHalf(textout)#後半PUTの処理をして文字を返す
       
            #置換して終わる
            output=kuro.sub(',',tmp)
    elif opt=='put':
    #putのみの場合
        #3つのカンマを付ける
        tmp=latterHalf(textout)#後半PUTの処理をして文字を返す
        output=',,,'+kuro.sub(',',tmp)#>>,,,26250,285,-10,189
    #end if
 
    return output
### end def

def csvToMysql(difile,dtablename,doptionDate,dmonth):
#ここからSTART
#Mysqlに接続メソッドを入れる
# データベースへの接続とカーソルの生成
    connection = MySQLdb.connect(
        host='localhost',
        user='maseda',
        passwd='Test1030',#知られても問題ないパスワード
        db='Stock')
    cursor = connection.cursor()

    #csvファイル名
    ifile=difile
    
    #table
    tablename=dtablename#"Test_Table_StockOption"#テスト用テーブルを使用する

    #カラム名
    rowname="(Volume1,Change1,Price1,ExercisePrice,Price2,Change2,Volume2,Month,OptionDate,CreateDate,YOBI)"
    #VALUES (%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s)>>%dは%sにしないとエラーになった。

    #カラム変数
    month=dmonth#1#月限
    optionDate=doptionDate#"2020/12/22"#データ取得の日付、たいていCSVに記載の日付になる。
    
    dt_now=datetime.datetime.now()
    createDate=dt_now.strftime('%Y-%m-%d %H:%M:%S')#今日の日付時刻を入れて、取り込み実行の日付で良い。後で削除操作するときの目安くらいだから厳密ではない

    yobi=""#コメントがあればいれる。
    
    count=0
    #テーブルにデータを挿入する部分から書いていく
    #CSVを1行ごとに読み取り、列ごとにカラムに入れていく
    try:#ファイルが存在しないときのエラー処理try
        with open(ifile,'tr') as fin:
            for iline in fin:
                try:
                    #Mysqlに直接インサートするバージョンを作業する
                    # ここに実行したいコードを入力します

                    #cursor.execute("INSERT INTO Test_Table_StockOption (カラム,) VALUES(値,,,)")
                    #cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%s,%s)", ("test1","test2"))
                    #count=count+1
                    tmp=iline.strip().split(",")#stripしてからsplit()だと理解している。 iline.split(",")のままだと改行が入ってくるのでstripで前後の空白と改行を削除する
                    #CSVのデータが空の場合は、値0を入れる
                    if tmp[0]=='':
                        tmp[0]=0
                    if tmp[1]=='':
                        tmp[1]=0
                    if tmp[2]=='':
                        tmp[2]=0
                    if tmp[3]=='':
                        tmp[3]=0
                    if tmp[4]=='':
                        tmp[4]=0 
                    if tmp[5]=='':
                        tmp[5]=0
                    if tmp[6]=='':
                        tmp[6]=0    
                    #テストテーブルにインサートする前に、確認する前に、Splitを確認する。
                    #print(count,tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6])
                    #%dにするとエラーになるのでINT型は%sにしておくとエラーにならない。なのでINTなのに%sとして記述してある。
                    cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",\
                                   (tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],month,optionDate,createDate,yobi))

                    #こっちだと、%dに値がないよとエラーになる。正しい記述のはずがパイソンではエラーになるようだ。
                    #cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s)",\
                    #               (tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],month,optionDate,createDate,yobi))

                except MySQLdb.Error as e:
                    print('MySQLdb.Error: ', e)
                    connection.rollback()#失敗したらもとに戻す。これだと途中で成功してもコミットされるので、1回でもエラーのときはBREAKのほうがいいかも。
                    print("強制終了MYSQL")
                    connection.close()
                    return
            #ofile.close()
        connection.commit()

    except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
        print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
        ofile.close()
        sys.exit()#ファイルがなければ終了
    except Exception as e: # Exceptionは、それ以外の例外が発生した場合
       print(e)

    # 接続を閉じる
    connection.close()  

    print("Mysql書き込み終了")
#defここまで

#check file
def checkFile(filename):
    #他にもimport os os.listdir(path) というのもある
    files=glob.glob('./option_python_execute/*.txt')
    for file in files:
        #print(file)
        if filename in file:#ファイル名を含んでいればTRUE
            print('すでに取り込み済みのファイルです。')
            sys.exit()#return
#end def

def fileMove(file,path):
    shutil.move(file, path)#('./new.txt', './sample')
    print('file move',file)
#end def

def selectMysql(tablename):
# データベースへの接続とカーソルの生成
    connection = MySQLdb.connect(
        host='localhost',
        user='maseda',
        passwd='Test1030',#知られても問題ないパスワード
        db='Stock')
    cursor = connection.cursor()  
    try: 
        # ここに実行したいコードを入力します
        cursor.execute("SELECT SUM(Volume1) as callVolume1, ExercisePrice, SUM(Volume2) as putVolume2 FROM "+ tablename +\
                        " WHERE Month=1 GROUP BY ExercisePrice ORDER BY ExercisePrice Desc")

        #カラム名を取得
        #cursor.execute("show columns from Table_StockOption")

        # fetchall()で全件取り出し
        rows = cursor.fetchall()
        searchArray=[]#タプルで登録
        for row in rows:
          print(row[0],row[1],row[2])
          searchArray.append(row)  
            # print(row[Volume1]) ERROR

        #print(searchArray[0])#IDの情報:('ID', 'int', 'NO', 'PRI', None, 'auto_increment')
        #for srow in searchArray:
        #    print(srow)#
    
    except MySQLdb.Error as e:
        print('MySQLdb.Error: ', e)
    
    #表示
    connection.commit()
    connection.close()  
#end def

 

MysqlにCSVファイルをインサート

環境:MacOS Bigsur
Mysql8
CSV カンマ区切り UTF8
Pythonを使ってテキストファイルをCSVに出力して、
そのCSVファイルをMysqlのテーブルにターミナル手動でインサート処理する。
コマンドラインで実行する
LOAD DATA LOCAL INFILE

注意点はMySQLバージョン8では、デフォルトでは無効化されている。
mysql> SELECT @@local_infile;
を実行して「1」になっているかを確認する。「0」なら無効なので有効にする必要がある。
以下、下方に記載

参考サイト
http://jigsaw.hatenablog.jp/entry/2013/06/12/113016

参考、エラーになった
https://mita2db.hateblo.jp/entry/2020/01/13/163218
MySQL 8.0 で LOAD DATA LOCAL INFILE は無効化されている

以下のDBとテーブルは作成済み
作成方法については、他の記事を参照してほしい

ユーザ:maseda
pass:Tes****
DB:Stock
Table:Table_StockOption
・カラム構成
ID:id , int auto_increment、自動採番
出来高1 Volume1
前日比1 Change1
価格1 Price1
行使価格 ExercisePrice
価格2 Price2
前日比2 Change2
出来高2 Volume2
月限 Month , 例 12月限 12
取引日付、株探掲載日付 OptionDate ,date , DATE(NOW()) >> 2014-01-15
テーブル取り込み作成日 CreateDate ,datetime, NOW() >>2014-01-15 17:05:43
予備YOBI (テキスト),text


CSVファイルをテーブルのカラムにインサート処理する。
事前に与える値
「月限」はファイル名に記載していないので、取り込み毎に与える。
今後ファイル名に12月限みたいに記載してそこから取得するようにするか?

また「取引日付、株探掲載日付 OptionDate」については、任意の日付を与える。
「テーブル取り込み作成日」は、NOW()で与える。

@1から@7はCSVのカラムの左側からの順番で、列数は7つ
なおIDカラムが存在するが自動採番なので何も指定しない

mysqlのコマンドラインで実行する。ファイル名とテーブル名、カラム等を変更。
CSVは7つあり、テーブルのカラムは12こある。そしてIDは自動採番設定あり。
CSVの1番目を@1として該当のカラムVolume1に入れる。
SET Volume1=@1
以降CSVの@番号をカラム名に入れていく。

LOAD DATA LOCAL INFILE "/Users/toshiromaseda/Documents/2020年株関連/kabu_python/c_pythontest_2020年12月17日.csv"
INTO TABLE Table_StockOption
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(@1,@2,@3,@4,@5,@6,@7)
SET Volume1=@1, Change1=@2, Price1=@3, ExercisePrice=@4,
Price2=@5,Change2=@6,Volume2=@7,Month='1',OptionDate='2020/12/01',
CreateDate=NOW(),YOBI='';

画像CSVの構成7つの列がある

Number
テーブルカラム一覧画像、Volume1にCSVの1列目が入る。IDは自動採番なのでCSVにはない

キャプチャ

LOAD DATAを実行するとエラーになった。

mysql> use Stock;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> LOAD DATA LOCAL INFILE "/Users/toshiromaseda/Documents/2020年株関連/kabu_python/c_pythontest_2020年12月17日.csv"
-> INTO TABLE Table_StockOption
-> FIELDS TERMINATED BY ','
-> LINES TERMINATED BY '\n'
-> (@1,@2,@3,@4,@5,@6,@7)
-> SET Volume1=@1, Change1=@2, Price1=@3, ExercisePrice=@4,
-> Price2=@5,Change2=@6,Volume2=@7,Month='1',OptionDate='2020/12/01',
-> CreateDate=NOW(),YOBI='';
ERROR 3948 (42000): Loading local data is disabled; this must be enabled on both the client and server sides
mysql>

エラーになった。↑
LOAD DATA INFILE LOCAL は セキュリティ上のリスクになるため、デフォルトでは無効化されているらしい。

・以下の2つを設定する
1ターミナル
$ mysql -u root -p –local_infile=1

2mysql側
mysql> SET GLOBAL local_infile=on;

確認
SELECT @@local_infile;

mysql> SELECT @@local_infile;
+----------------+
| @@local_infile |
+----------------+
| 1 |
+----------------+
1 row in set (0.00 sec)

1になっているのでOK。

user:masedaでMysqlに接続して再度確認して問題なし。

mysql> SELECT @@local_infile;
+----------------+
| @@local_infile |
+----------------+
| 1 |
+----------------+
1 row in set (0.00 sec)

mysql> LOAD DATA LOCAL INFILE "/Users/toshiromaseda/Documents/2020年株関連/kabu_python/c_pythontest_2020年12月17日.csv"
-> INTO TABLE Table_StockOption
-> FIELDS TERMINATED BY ','
-> LINES TERMINATED BY '\n'
-> (@1,@2,@3,@4,@5,@6,@7)
-> SET Volume1=@1, Change1=@2, Price1=@3, ExercisePrice=@4,
-> Price2=@5,Change2=@6,Volume2=@7,Month='1',OptionDate='2020/12/01',
-> CreateDate=NOW(),YOBI='';
Query OK, 85 rows affected, 222 warnings (0.04 sec)
Records: 85 Deleted: 0 Skipped: 0 Warnings: 222

 

warningはあるがCSVデータは登録されているようだ。

mysql> select OptionDate ,CreateDate,YOBI from Table_StockOption limit 5;
+------------+---------------------+------+
| OptionDate | CreateDate | YOBI |
+------------+---------------------+------+
| 2020-12-01 | 2020-12-18 10:59:06 | |
| 2020-12-01 | 2020-12-18 10:59:06 | |
| 2020-12-01 | 2020-12-18 10:59:06 | |
| 2020-12-01 | 2020-12-18 10:59:06 | |
| 2020-12-01 | 2020-12-18 10:59:06 | |
+------------+---------------------+------+
5 rows in set (0.00 sec)

 

一旦、データを消して再度CSVを登録してワーニングを見る
ワーニングを表示させるには
show warnings;

データを全部削除
mysql> delete from Table_StockOption;
Query OK, 85 rows affected (0.02 sec)

再度、Loadを実行
そして
show warnings;
warningが表示された。
どうやら、値がない(空)でワーニングが表示されたようだ。空でもいいので
これは無視していいようだ。
INTで空の場合は0が入っている
| Warning | 1366 | Incorrect integer value: ” for column ‘Volume1’ at row 85 |
| Warning | 1366 | Incorrect integer value: ” for column ‘Change1’ at row 85 |
| Warning | 1366 | Incorrect integer value: ” for column ‘Price1’ at row 85 |

mysql> select count(*) from Table_StockOption;
+----------+
| count(*) |
+----------+
| 85 |
+----------+



mysql> select * from Table_StockOption limit 3;
+-----+---------+---------+--------+---------------+--------+---------+---------+-------+------------+---------------------+------+
| ID | Volume1 | Change1 | Price1 | ExercisePrice | Price2 | Change2 | Volume2 | Month | OptionDate | CreateDate | YOBI |
+-----+---------+---------+--------+---------------+--------+---------+---------+-------+------------+---------------------+------+
| 128 | 95 | 0 | 1 | 32000 | 0 | 0 | 0 | 1 | 2020-12-01 | 2020-12-18 11:03:16 | |
| 129 | 52 | 0 | 2 | 30750 | 0 | 0 | 0 | 1 | 2020-12-01 | 2020-12-18 11:03:16 | |
| 130 | 12 | 0 | 3 | 30250 | 0 | 0 | 0 | 1 | 2020-12-01 | 2020-12-18 11:03:16 | |
+-----+---------+---------+--------+---------------+--------+---------+---------+-------+------------+---------------------+------+
3 rows in set (0.00 sec)

 

IDはリセットしていないので、削除した後に追加すると次の番号がふられるから、
実際の行数とは一致しない。

・mysql auto_increment リセット
ALTER TABLE テーブル名 AUTO_INCREMENT = 1;

なので、データをdeleteしてから実行するとよいはず。
delete from Table_StockOption;
ALTER TABLE Table_StockOption AUTO_INCREMENT = 1;

mysql> delete from Table_StockOption;
Query OK, 85 rows affected (0.01 sec)

mysql> ALTER TABLE Table_StockOption AUTO_INCREMENT = 1;
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0

 

>>削除してリセットまで済。次は、必要なデータを順次取り込む。今ここ、2020-12-18、11時27分
—適宜、ファイル名を変更していく

mysqlコマンド

LOAD DATA LOCAL INFILE "/Users/toshiromaseda/Documents/2020年株関連/kabu_python/c_pythontest_2020年12月17日.csv"
INTO TABLE Table_StockOption
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(@1,@2,@3,@4,@5,@6,@7)
SET Volume1=@1, Change1=@2, Price1=@3, ExercisePrice=@4,
Price2=@5,Change2=@6,Volume2=@7,Month='1',OptionDate='2020/12/01',
CreateDate=NOW(),YOBI='';

 

 

python テキストファイルを読み込んで、CSVファイルを出力する

 

#テキストファイルを読み込んで、CSVファイルを出力する
#def outMojiMK(text):テキストファイルの1行をtextに入れて、空白をカンマに置換する
#カンマに置換してCSVとして出力する
#今の手順は、株探のページからオプションのデータをテキストファイルに保存
#そしてShift+Enterで実行
#なお、テキストファイルとCSVファイルは今の所指定である。上書き注意

anaconda、JupyterLabを使用。Shift+Enterで実行する

テキストファイル画像、スペースで配置されている。状態をカンマに置き換えたいテキストファイル

↓CSVにした。不足分はカンマを追加している

CSV

表計算アプリでCSVを表示した

Number

import re
import sys
import os

##
    #半角と全角の置換をする前に、出来高の次に前日比があるかをチェックする。
    #チェック方法
    #チェックは、出来高と価格の間に、前日比がないときは、空白の数が多いのでその数で、前日比が
    #入っていないことがわかる。
    #これから、2020/12/16
    #考え方1:先頭から数字1を探す。次に、その数字から次の半角を探して、また次の数字2を探す
    #数字1と数字2の間の空白が4以上空いていたら、前日比が存在しない。
    #find,re.search()を使う。ただしFindは正規表現が使えない。
def outMojiMK(text):
    #空白を削除する前に、空白の個数を数える
    #株探の仕様が変わったらここを変える。2020/12/16
    kuro=re.compile('[  ]+')#半角と全角の空白置換 半角全角が[半角全角]として入っている
    
    if text.count(' ',0,15)>=13:
           #空白13個はプット
            opt='put'
            textout=text.strip()#先頭、末尾の空白を削除する
    else:
            #コールの場合、2種類あるのでそれをチェックする
            textout=text.strip()#先頭、末尾の空白を削除する
            check=kuro.sub(',',textout)#半角全角の空白を置換
            count=check.split(",")
            #print ('len count:',len(count))
            if len(count)>=5:#配列が5個以上なら、call,putが含まれる       
                opt='callandput'
            else:
                opt='onlycall'
    pattern=re.compile('[0-9]+')#findで正規表現ができない
    if opt=='onlycall' or opt=='callandput':
        #次に、「call,putあり」OR「Callのみ」かをチェックする。
        #optSub='callandput' 'onlycall'
        #callのみを先に処理して、put側を調べる
        matchobj=re.search('[0-9]+',textout)#最初の数字を探す
        if matchobj:
            #print('マッチした文字列:'+matchobj.group())
            #print('マッチした文字列グループ:',matchobj.groups())
            #print( '開始位置'+str(matchobj.start()) )#先頭位置は0番として数える 3番目(4文字目)に見つかった
            #print( '終了位置'+str(matchobj.end()) )#終了位置は次の番目を含んでいるので実際は1を引いた数が終了位置
            #print(matchobj.span())#'マッチした文字列の (開始位置, 終了位置) のタプル'+
            #2番めの数字を探す
            secondMatch=pattern.search(textout,matchobj.end())#compileを使用してpatternで再度位置を指定して探す
            if secondMatch:
                #print( '開始位置2:'+str(secondMatch.start()) )#先頭から数えて10番目に次の数字が見つかった
                #1番目と2番めの文字数が5以上空いていたら数字が抜けている事がわかる。
                #ここに0を埋める処理を入れる
                if secondMatch.start()-matchobj.end() >=5:
                    print('コールで値が抜けてる')
                    # hash = "355879ACB6"
                    # hash = hash[:4] + '-' + hash[4:]
                    #文字列の挿入。#1番目の文字の3文字目くらいに0を追加する。
                    texttmp=textout[:matchobj.end()+2]+ '0' + textout[matchobj.end()+2:]
                    textout=texttmp
        #put側のチェック。再度optでチェックする
        if opt=='onlycall':
            #置換して終わる
            output=kuro.sub(',',textout)+',,,'
        elif opt=='callandput':
            print('callandputの処理')
            #後ろの文字のチェックをする
            i = 0
            checkArray=[]#タプルを入れる配列
            while i >= 0:#数字を探す
              m = pattern.search(textout, i)
              if m:
                #print(m.start())
                #print(m.end())
                #これをタプル配列に入れて、N,N-1で差が大きいときに0を入れる
                #print(m.span())
                checkArray.append(m.span())
                i = m.end()#m.start() + 1#m.end()
              else:
                break
            print("len checkArray",len(checkArray))
            #次はここから、2020/12/17
            n=len(checkArray)
            if n>=2:#nは最低2こ必要 最後と最後の1こ前の
                print("[n-1][0]",checkArray[n-1][0])#0番目の1個目 [0](0,1)
                print("[n-2][1]",checkArray[n-2][1])#0番目の2個目
                #個数はNだけど配列の指定はそれより1小さいのでN-1となる
                if (checkArray[n-1][0]-checkArray[n-2][1])>=6:
                    print("putで抜けている")
                    #checkArray[n-1][1]の後ろに挿入する
                    texttmp=textout[:checkArray[n-2][1]+2]+ '0' + textout[checkArray[n-2][1]+2:]
                    textout=texttmp
       
            #置換して終わる
            output=kuro.sub(',',textout)
    elif opt=='put':
    #putのみの場合
        #3つのカンマを付ける
        output=',,,'+kuro.sub(',',textout)#>>,,,26250,285,-10,189
    #end if
 
    return output
### end def

###本文 ここでoutMojiMK()メソッドを使用している
path='/Users/toshiromaseda/Documents/2020年株関連/kabu_python/'
os.chdir(path)#ディレクトリ変更
print(os.getcwd())#ディレクトリ確認
ifile='pythontest.txt'#sys.argv[1] このスクリプトと同じ階層ならパスは不要 

try:
    ofile=open('c_'+ifile.split('.')[0]+'.csv','tw') 
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
   print("ファイルが見つかりません", e)
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

try:#ファイルが存在しないときのエラー処理try
    with open(ifile,'tr') as fin:
        for iline in fin:
            #ilineに、”コール”、”出来高”の文字がある行は無視するようにする
            #countで探すか 1行目、2行目は不要なのでDBにインサートしないための処理
            if iline.count('コール')>=1 or iline.count('出来高')>=1:
                continue#以下は実行されない
            try:
                ofile.write(outMojiMK(iline)+'\n')

            except Exception:
                print("do not")
        ofile.close()
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
    print("ファイルが見つかりません", e)
    ofile.close()
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)


print("CSV出力終わりました。")

修正が必要だったので改良したものがこちら。Put側にも抜けた文字が存在したので、0を挿入するようにした。↓2020/12/18

#MKIII対応版、2020/12/18 こちらが修正版になる。違いはlatterHalf()とMKIII()になったこと。
#違いは、put側でも抜けた文字が存在したので抜けた文字があった場合0を挿入する部分を入れた
#opt=='onlycall' 'callandput' putのみも前半は同じ処理が必要だった。
#putのみにも挿入処理を入れた。2020/12/18
import re
import sys
import os
#ファイル名は下に指定する。

#文字列の後ろ側の数字を後ろから探し、抜けていた場合0を埋める
def latterHalf(text):
    textout=text
    pattern=re.compile('[0-9]+')#findで正規表現ができない
    i = 0
    checkArray=[]#タプルを入れる配列
    while i >= 0:#数字を探す
      m = pattern.search(textout, i)
      if m:
        #print(m.start())
        #print(m.end())
        #これをタプル配列に入れて、N,N-1で差が大きいときに0を入れる
        #print(m.span())
        checkArray.append(m.span())
        i = m.end()#m.start() + 1#m.end()
      else:
        break
    #print("len checkArray",len(checkArray))
    #次はここから、2020/12/17
    n=len(checkArray)
    if n>=2:#nは最低2こ必要 最後と最後の1こ前の
        #print("[n-1][0]",checkArray[n-1][0])#0番目の1個目 [0](0,1)
        #print("[n-2][1]",checkArray[n-2][1])#0番目の2個目
        #個数はNだけど配列の指定はそれより1小さいのでN-1となる
        if (checkArray[n-1][0]-checkArray[n-2][1])>=6:
            print("put抜けている")
            #checkArray[n-1][1]の後ろに挿入する
            texttmp=textout[:checkArray[n-2][1]+2]+ '0' + textout[checkArray[n-2][1]+2:]
            textout=texttmp
    output=textout
    return output
#end def

def outMojiMKIII(text):
    #空白を削除する前に、空白の個数を数える
    #株探の仕様が変わったらここを変える。2020/12/16
    kuro=re.compile('[  ]+')#半角と全角の空白置換 半角全角が[半角全角]として入っている
    
    if text.count(' ',0,15)>=13:
           #空白13個はプット
            opt='put'
            textout=text.strip()#先頭、末尾の空白を削除する
    else:
            #コールの場合、2種類あるのでそれをチェックする
            textout=text.strip()#先頭、末尾の空白を削除する
            check=kuro.sub(',',textout)#半角全角の空白を置換
            count=check.split(",")
            #print ('len count:',len(count))
            if len(count)>=5:#配列が5個以上なら、call,putが含まれる       
                opt='callandput'
            else:
                opt='onlycall'
    pattern=re.compile('[0-9]+')#findで正規表現ができない
    if opt=='onlycall' or opt=='callandput':
        #次に、「call,putあり」OR「Callのみ」かをチェックする。
        #optSub='callandput' 'onlycall'
        #callのみを先に処理して、put側を調べる
        matchobj=re.search('[0-9]+',textout)#最初の数字を探す
        if matchobj:
            #print('マッチした文字列:'+matchobj.group())
            #print('マッチした文字列グループ:',matchobj.groups())
            #print( '開始位置'+str(matchobj.start()) )#先頭位置は0番として数える 3番目(4文字目)に見つかった
            #print( '終了位置'+str(matchobj.end()) )#終了位置は次の番目を含んでいるので実際は1を引いた数が終了位置
            #print(matchobj.span())#'マッチした文字列の (開始位置, 終了位置) のタプル'+
            #2番めの数字を探す
            secondMatch=pattern.search(textout,matchobj.end())#compileを使用してpatternで再度位置を指定して探す
            if secondMatch:
                #print( '開始位置2:'+str(secondMatch.start()) )#先頭から数えて10番目に次の数字が見つかった
                #1番目と2番めの文字数が5以上空いていたら数字が抜けている事がわかる。
                #ここに0を埋める処理を入れる
                if secondMatch.start()-matchobj.end() >=5:
                    print('値が抜けてる')
                    # hash = "355879ACB6"
                    # hash = hash[:4] + '-' + hash[4:]
                    #文字列の挿入。#1番目の文字の3文字目くらいに0を追加する。
                    texttmp=textout[:matchobj.end()+2]+ '0' + textout[matchobj.end()+2:]
                    textout=texttmp
        #put側のチェック。再度optでチェックする
        if opt=='onlycall':
            #置換して終わる
            output=kuro.sub(',',textout)+',,,'
        elif opt=='callandput':
            print('callandputの処理')
            tmp=latterHalf(textout)#後半PUTの処理をして文字を返す
       
            #置換して終わる
            output=kuro.sub(',',tmp)
    elif opt=='put':
    #putのみの場合
        #3つのカンマを付ける
        tmp=latterHalf(textout)#後半PUTの処理をして文字を返す
        output=',,,'+kuro.sub(',',tmp)#>>,,,26250,285,-10,189
    #end if
 
    return output
### end def

###本文 ここでoutMojiMKIII()メソッドを使用している
path='/Users/toshiromaseda/Documents/2020年株関連/kabu_python/'
os.chdir(path)#ディレクトリ変更
print(os.getcwd())#ディレクトリ確認
ifile='2020年12月18日AM8時39分.txt'#sys.argv[1] このスクリプトと同じ階層ならパスは不要 

try:
    ofile=open('c_'+ifile.split('.')[0]+'.csv','tw') 
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
   print("ファイルが見つかりません", e)
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

try:#ファイルが存在しないときのエラー処理try
    with open(ifile,'tr') as fin:
        for iline in fin:
            #ilineに、”コール”、”出来高”の文字がある行は無視するようにする
            #countで探すか 1行目、2行目は不要なのでDBにインサートしないための処理
            if iline.count('コール')>=1 or iline.count('出来高')>=1:
                continue#以下は実行されない
            try:
                ofile.write(outMojiMKIII(iline)+'\n')#MKIII改良版2020/12/18

            except Exception:
                print("do not")
        ofile.close()
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
    print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
    ofile.close()
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)


print("CSV出力終わりました。",ifile)

 

python メソッド、半角と全角の置換、CSV向け

#メソッドを使った。メソッドは先に記述されていないと、関数呼び出しでエラーになる。
#次は先頭から空白が13個以上の場合は、カンマを4つ追加する仕様に対応する
text='             26250   285    -10   189 '
ntext='  42   -5   655  26375   330    -5   226 '#'42,-5,655,26375,330,-5,226'
#outMoji(text)#ここにメソッドを書くとnot definedとなる

def outMoji(text):
    #空白を削除する前に、空白の個数を数える
    #株探の仕様が変わったらここを変える。2020/12/16
    if text.count(' ',0,15)>=13:
           #空白13個はプット
            opt='put'
            print('13こある')
    else:
            #はじめからあればコール このときは何もしない
            opt='call'

    textout=text.strip()#先頭、末尾の空白を削除する
    kuro=re.compile('[  ]+')#半角と全角の置換 半角全角が[半角全角]として入っている
    if opt=='put':
        #3つのカンマを付ける
        print('カンマを付けた↓')
        output=',,,'+kuro.sub(',',textout)#>>,,,26250,285,-10,189
    else:
        output=kuro.sub(',',textout)
    return output


###ここに関数を書く
outMoji(ntext)

#>>結果はOK ,,,26250,285,-10,189

 

ゲームプログラム、swift3.0でCSVファイルを扱うのでSwiftCSVライブラリをゲットしたがエラーでまくり

swift3.0でCSVファイルを扱うのでSwiftCSVライブラリをゲットしたがエラーでまくり

色々エラー

https://github.com/naoty/SwiftCSV
良かったライブラリあるじゃん、楽できるじゃんと思ったが、
でもSwiftのバージョン3.0に上がったためにエラー20件ほど。チクチク直すが、自分で基本的なところだけでも作ったほうが良くないか?と思いはじめて、簡単読み込みを作り直すことにする
続きを読む