IT」カテゴリーアーカイブ

株価チェックEXCELマクロ、安値高値

株価をチェックして、安値高値でサウンドを再生

ちなみにヤフーファイナンスでも安値、高値に達したらメールで知らせてくれるサービスは存在するが、メールを見ないといけないし、複数の銘柄をチェックする場合は面倒になってくる。エクセルシートを見ながら、再生音で安値、高値をチェックできたら便利と思った。

エクセルを複数起動したい場合は、Windowキー+Rファイルを指定して起動で[excel /x]と入力して起動させて、エクセルブックを開けばよい。

仕様
楽天証券、マーケットスピード、RSS.exeが必要。Windowsのみ。
VBAによるループ処理で、現在値と安値、高値を比較します。
DoEvntsでイベントを受け付けます。
安値、高値になるとサウンドが1回再生されます。達成チェック列(H2以降)の文字を消すと再度再生します。サウンドファイルは個別に用意をする必要があります。
コードを入力後は銘柄ボタンをクリックしないと株価を取得しません。

参考にしたサイト

https://dp-invest.hateblo.jp/entry/2020/11/09/192427

使い方

(1)コードを入力して銘柄ボタンをクリックすると銘柄名と株価を取得します。
(2)安値と高値を入力します。省略可能。
(3)チェック開始ボタンで比較実行
(4)終了ボタンで処理を停止

Public goFlag
Public endFlag
Sub mycolor(cell As String)
'
' color Macro
'マクロの記録で作成

'
    Range(cell).Select
    With Selection.Font
        .color = -16776961
        .TintAndShade = 0
    End With
    With Selection.Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = xlThemeColorAccent4
        .TintAndShade = 0.799981688894314
        .PatternTintAndShade = 0
    End With
End Sub
Sub colorBack(cell As String)
'
' colorBack Macro
'

'
    With Selection.Font
        .color = -16776961
        .TintAndShade = 0
    End With
    With Selection.Font
        .ThemeColor = xlThemeColorLight1
        .TintAndShade = 0
    End With
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With
    ActiveCell.FormulaR1C1 = ""
    Range(cell).Select
    Range(cell).Value = ""
    
End Sub


Sub meigara()
'https://dp-invest.hateblo.jp/entry/2020/11/09/192427
'を参考にした

Dim i As Integer
Dim n, m As Integer
Dim code

n = Cells(Rows.Count, "A").End(xlUp).Row

For i = 2 To n 'A2から以降のコード
    code = Cells(i, 1)
    If code <> "" Then
        Cells(i, 2).Value = "=RSS|'" & code & ".T’!銘柄名称"
        Cells(i, 3).Value = "=RSS|'" & code & ".T’!現在値"
    Else '
        Cells(i, 2).Value = "" 'B cell
        Cells(i, 3).Value = "" 'C
        Cells(i, 8).Value = "" 'H cell
    End If

Next i

m = Cells(Rows.Count, "B").End(xlUp).Row
For i = 2 To m
    If Cells(i, 1) = "" Then
        Cells(i, 2).Value = "" 'B cell
        Cells(i, 3).Value = "" 'C
        Cells(i, 4).Value = "" 'D
        Cells(i, 6).Value = "" 'F
        Cells(i, 8).Value = "" 'H cell
        colorBack ("H" & i)
    End If
Next i

m = Cells(Rows.Count, "D").End(xlUp).Row
For i = 2 To m
    If Cells(i, 1) = "" Then
        
        Cells(i, 4).Value = "" 'D
        Cells(i, 6).Value = "" 'F
        Cells(i, 8).Value = "" 'H cell
        colorBack ("H" & i)
    End If
Next i

End Sub
Sub endCheck()
    Range("E14").Value = "停止"
    endFlag = False
    Debug.Print "end"
    MsgBox "株価チェック終了しました"
End Sub

Sub kabuCheckAlert() 'チェック開始ボタンで実行
    '株価をチェックして、指定した値に達したら警告音やアラートを表示する
    Dim t As Long
    Dim nTime As Long
    Dim n As Integer
    Dim strYasune
    Dim strTakane
    endFlag = True 'falseで処理を終わる
    nTime = 3
    t = Timer
    strYasune = "安値です"
    strTakane = "高値です!!"
    'H列を空欄にする
    m = Cells(Rows.Count, "H").End(xlUp).Row
    For i = 2 To m
        Range("H" & i).Value = ""
    Next i
    
    meigara
   Range("E14").Value = "実行中"
    Do
        DoEvents
     '------Start Timer
        If t + nTime < Timer Then '秒単位のタイマー Timeは時刻nTimeで指定した秒間隔でコピー処理を行う
            Debug.Print nTime&; "秒間隔 株価チェック 実行中"
            t = Timer
            'nTime毎に株価をチェックする
            'ここを行数分ループする
            n = Cells(Rows.Count, "A").End(xlUp).Row
            'For next Start
            For i = 2 To n
                If Range("C" & i).Value <> "" And Range("D" & i).Value <> "" Then
                    If Range("C" & i).Value <= Range("D" & i).Value Then
                        If Range("H" & i).Value <> strYasune Then 'Hセルが空のときだけ再生し、すでにHセルに記載があれば音を再生しない
                            Debug.Print "株価が安値に達しました"
                            Range("H" & i).Value = strYasune
                            mycolor ("H" & i)
                            Shell "C:\Program Files\Windows Media Player\wmplayer.exe C:\Users\mased\Music\ヒューンと落下.mp3", 1
                        End If
                    End If
                    
                End If
                If Range("C" & i).Value <> "" And Range("F" & i).Value <> "" Then
                    If Range("C" & i).Value >= Range("f" & i).Value Then
                        If Range("H" & i).Value <> strTakane Then 'Hセルが空のときだけ再生し、すでにHセルに記載があれば音を再生しない
                            Debug.Print "株価が高値に達しました"
                            Range("H" & i).Value = strTakane
                            mycolor ("H" & i)
                            Shell "C:\Program Files\Windows Media Player\wmplayer.exe C:\Users\mased\Music\決定、ボタン押下37.mp3", 1
                        End If
                    End If
                End If
            Next i
            'For next end
        End If
     '----End Timer
     
        If endFlag = False Then
            Debug.Print "exit loop"
            Range("E14").Value = "停止"
            Exit Do
        End If
    Loop
    Debug.Print "End"
End Sub

 

python スクレイピング、BeautifulSoupライブラリ

#株探先物オプションのスクレイピング。取得した文字列をコピペしてTEXTにして、
#CSVに出力してMysqlにインサートするコード
#URLと日付と月限は手動で毎回入力する必要がある。

#以前はファイル作成まで手動で作業していた。
#WEBページを開き
#先物オプションの出来高データを取得して
#テキストファイルにする
#所定のフォルダにコピー、移動する
#個人用クラスメソッドを使う。

いままでWebdriverライブラリを使用していたが、空白部分が自動で削除されてしまった。
削除してほしくなかったので、BeautifulSoupライブラリを使用した。こちらのほうはクロムは起動しないし純粋にhtmlの文字を空白を含めて取得してくれた。
以下は今回作ったコードの一部。class cGetOption()
なおdef returnDriver(self,lurl)はwebdriverを使用したもので実際には採用しなかった。
株探の先物オプションのURLを取得して
そのページの文字列を取得。このとき、ある文字列Aと文字列Bの間の文字を取得(findFirstStrのところ)
そしてタプルで、文字列とファイル名文字列を出力する

https://github.com/maseda1030/yahoofinance_python.git

import MySQLdb
import os
import re
import sys
import time
import datetime
import glob#ファイル一覧
import shutil#move
from selenium import webdriver
import importlib#再読み込みのためのライブラリ

import requests#スクレイピング
from bs4 import BeautifulSoup#スクレイピング

import methodMysql#個人用メソッド pyファイル

###START
importlib.reload(methodMysql)

##以下は毎回手動で確認すること
#株探の市況の先物オプション、市場が開いている当日のPM4:06分頃と、翌日の朝AM6:30以降に更新される。
#土日祝は更新されないが、前日が市場が開いていると更新される。
optionUrl='https://kabutan.jp/news/marketnews/?b=n202103010692'#都度修正、毎日
useDate='2021/3/1'#オプション取り込みの日付               #都度修正、毎日
useMonth=3#月限 12月の作業はたいてい翌月である1月            #都度修正、月
useTable='Table_StockOption'#テーブルは固定

#
print('START')
print('chrome起動')
obj=methodMysql.cGetOption()
#このURLは手動でコピペする
#BeautifulSoup版
tupleArray=obj.getOptionDataByBeautifulSoup(optionUrl)

#webdriver版
#tupleArray=obj.getOptionData(optionUrl)
a,b=tupleArray
print(a)#text
print(b)#年月日時分


path='/Users/toshiromaseda/Documents/2020年株関連/kabu_python/'
obj.outputText(path,tupleArray)
#file名は、年月日時分.txtになって保存される。

#ファイルの存在チェックで拡張子をつけてチェックする
if b.find('.txt')>=0:
    pass
else:
    ifile=b+'.txt'

##--
checkFlag='nashi'
files=glob.glob(path+'*.txt')
for file in files:
    if ifile in file:#ファイル名を含んでいればTRUE
        print(file)
        checkFlag='ari'
        break
    else:
        #print(file)
        checkFlag='nashi'
if checkFlag=='nashi':
    print('ファイルが存在しないか、ファイル名が間違っています')
    sys.exit()

        
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()#ファイルがなければ終了#tryのときは_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#以下は実行されない
            if len(iline)==1:#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()#ファイルがなければ終了 #tryのときは_exit()が良いらしい
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

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

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

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

print("終わりました。")
print('+++++++')
print('chrome終了')
print('END')


'''
mysql> mysql> SELECT SUM(Volume1) as callVolume1, ExercisePrice,  SUM(Volume2) as putVolume2 
FROM Table_StockOption WHERE Month=3 GROUP BY ExercisePrice ORDER BY Exerce Desc;
'''

 

#先物オプションテキストコピペ 2021/02/28
class cGetOption():
    def __init__(self):
        pass

    def returnDriver(self,lurl):
        # 仮想ブラウザ起動、URL先のサイトにアクセス
        driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
        #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
        url=lurl
        driver.get(url)
        mydriver=driver
        return mydriver
    #BeautifulSoup版はクロムは起動しない
    def getOptionDataByBeautifulSoup(self,lurl):#BeautifulSoup対応版、別途Importが必要、2021/03/01
        target_url = lurl
        r = requests.get(target_url)         #requestsを使って、webから取得
        soup = BeautifulSoup(r.text, 'lxml') #要素を抽出
        shijyounews=soup.find(id="shijyounews")#id
        article=shijyounews.find("article")#tag
        tagTime=article.find("time")#tag
        mono=article.find(class_="mono")#class

        print("BeautifulSoup")
        #print(mono.text)
        outputFileName=tagTime.text#年月日時分
        #ここに処理を入れる。
        #2021/03/01
        findFirstStr='コール      プット'#を探して
        findSecondStr='株探ニュース'#の前までを取得する
        findFirstPosition=mono.text.find(findFirstStr)
        findSecondPosition=mono.text.find(findSecondStr)
        if(findFirstPosition>=0 and findSecondPosition>=0):
            print('search success.')
            outputText=mono.text[findFirstPosition:findSecondPosition]
        else:
            print('先物オプションが見つかりませんでした。URLが正しいか確認してください。')
            sys.exit()       

        output=()#初期化
        output=(outputText,outputFileName)#タプルで出力する,この時点で拡張子.txtは付記していない。
        time.sleep(1)       
        return output

    #webdriver版は、クロムが起動する。こっちは文字の先頭に空白を自動で削除する。この処理がよいときもあるが、今回は空白が必要だったのでB4にした
    def getOptionData(self,lurl):
        driver=self.returnDriver(lurl)
        time.sleep(1)
        #tag,id,css
        main = driver.find_element_by_id("wrapper_main")
        container=main.find_element_by_id("container")
        container_main=container.find_element_by_id("main")
        shijyounews=container_main.find_element_by_id("shijyounews")
        article=shijyounews.find_element_by_tag_name("article")

        tagTime=article.find_element_by_tag_name("time")
        mono=article.find_element_by_class_name("mono")
        #brs=mono.find_elements_by_tag_name("br")
        print(tagTime.text)
        outputFileName=tagTime.text#年月日時分
        #tagTimePosition=tagTime.text.find('日')
        #print(tagTime.text[0:tagTimePosition+1])#年月日
        #print(mono.text)

        findFirstStr='コール      プット'#を探して
        findSecondStr='株探ニュース'#の前までを取得する
        findFirstPosition=mono.text.find(findFirstStr)
        findSecondPosition=mono.text.find(findSecondStr)
        if(findFirstPosition>=0 and findSecondPosition>=0):
            print('search success.')
            outputText=mono.text[findFirstPosition:findSecondPosition]
        else:
            print('先物オプションが見つかりませんでした。URLが正しいか確認してください。')
            sys.exit()
        output=()#初期化
        output=(outputText,outputFileName)#タプルで出力する,この時点で拡張子.txtは付記していない。
        time.sleep(1)
        driver.close()#起動したウィンドウを閉じる
        return output

    def outputText(self,path,tupleArray):#ここで受け取るタプルは2つ
        #getOptionData()からテキストとファイル名をタプルを受け取る
        outputText,filename = tupleArray
        if outputText=='' or filename=='' or path=='':
            print("パスかファイル名かテキストがありませんでした。filename,outputText")
            sys.exit()
        os.chdir(path)#ディレクトリ変更
        print(os.getcwd())#ディレクトリ確認
        if filename.find('.txt')>=0:
            pass
        else:
            filename+='.txt'
        try:
            ofile=open(filename,'tw') 
        except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
           print("ファイルが見つかりません", e)
           sys._exit()#ファイルがなければ終了#tryのときは_exit()が良いらしい
        except Exception as e: # Exceptionは、それ以外の例外が発生した場合
           print(e) 
        
        ofile.write(outputText)
        ofile.close()

 

MySqlでDB、テーブル作成メモ 備忘録

MySqlでDB、テーブル作成メモ(条件はユーザはすでに作成済)
株式市場の企業の株価と出来高を登録する。
pythonを使ったスクレイピング処理をこれから行う。この記事にはPythonの記載はない。
mysqldbを使用していたがmysql-connector-pythonが良いらしいのでpip install済

ターミナルでの作業

最近忘れっぽくて、使っていないコマンドをどんどん忘れている。SQL文も忘れてるので、備忘録メモとして記載しておく。記憶力の低下に抵抗せずに、メモをしていつでも思い出せるかメモを見ながら作業するようにする。

・ユーザはmaseda
mysql -u maseda -p
psssはTes*****にした。上に記載。このパスワードはデモ用なので知られてOK

・DBを作成
CREATE DATABASE YahooFinance DEFAULT CHARACTER SET utf8mb4;

・DBを指定する
use YahooFinance;

重複を避けるときはUNIQUEを使う
UNIQUE uni_Code int(5) NOT NULL,
>>今回は使用せず
mysqlのコメントは #,--(ハイフン2つ) /*  */ がある
CodeについてはUNIQUEユニークにしない、毎回同じ企業コードが入るかも

・テーブルを作成
CREATE TABLE Table_Dekidaka(
ID int(11) NOT NULL AUTO_INCREMENT,
Code int(5) NOT NULL,
Market text,
Name text,
Price int(11) ,
Volume int(14),
PreviousVolume int(14),
VolumePer float,
StockDate DATE,
CreateDate DATETIME,
Yobi text,
PRIMARY KEY (ID)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

>>オートインクリメントのIDは、PRIMARY KEY(ID)が必要。ないとエラーになる。

mysql> show tables;
mysql> show columns from Table_Dekidaka;

+----------------+----------+------+-----+---------+----------------+
| Field          | Type     | Null | Key | Default | Extra          |
+----------------+----------+------+-----+---------+----------------+
| ID             | int      | NO   | PRI | NULL    | auto_increment |
| Code           | int      | NO   |     | NULL    |                |
| Market         | text     | YES  |     | NULL    |                |
| Name           | text     | YES  |     | NULL    |                |
| Price          | int      | YES  |     | NULL    |                |
| Volume         | int      | YES  |     | NULL    |                |
| PreviousVolume | int      | YES  |     | NULL    |                |
| VolumePer      | float    | YES  |     | NULL    |                |
| StockDate      | date     | YES  |     | NULL    |                |
| CreateDate     | datetime | YES  |     | NULL    |                |
| Yobi           | text     | YES  |     | NULL    |                |
+----------------+----------+------+-----+---------+----------------+
11 rows in set (0.03 sec)

mysql> 
権限がないときは、権限を与える。
GRANT SHOW DATABASES ON *.* to maseda@localhost;
これでいいはず。もしこれでだめな場合は、必要な権限を与えて。

---
python
mysqldbを使用していたがmysql-connector-pythonが良いらしい。
pip install mysql-connector-python

pip list 一覧表示 OK

 

python、テキストファイル出力、配列に文字を連結するだけ

#python、トレーディングビューのリストに追加するテキストファイル出力、配列に文字を連結するだけ
#必要な情報は、リスト名(テキストファイル名)、企業コード(このコードは調べたい企業コードなので、これだけは自分で探さないといけない)

#トレーディングビューのウォッチリスト(右側)のインポート(、、、のようなアイコン)で取り込める。テキスト名がリスト名になる
#複数企業の登録が楽になるのでチャートを選ぶのが楽になる。

import os
import re
import sys
import datetime
import glob#ファイル一覧
import shutil#move


class twList:
    def __init__(self):
        print()
    def outputText(self,codeList,filename):
        print("文字列処理開始")
        path='/Users/toshiromaseda/Documents/2021年/2021年株/トレーディングビュー/'
        os.chdir(path)#ディレクトリ変更
        print(os.getcwd())#ディレクトリ確認
        try:
            ofile=open(filename+'.txt','tw') 
        except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
            print("ファイルが見つかりません", e)
        except Exception as e: # Exceptionは、それ以外の例外が発生した場合
            print(e)
        #ここで処理する
        #
        addStr="TSE:"
        outputStr=""

        i=0
        for f in codeList:
            if i==len(codeList)-1:
                outputStr+=addStr+str(f)#最後の配列の要素にはカンマを付けない。
            else:    
                outputStr+=addStr+str(f)+','#配列の要素ごとにカンマを付ける
            i+=1    
        print(outputStr)    
        print("文字列処理終了")
        i=0
        #OUTPUT
        ofile.write(outputStr)
        ofile.close()
        
###START
print("START#####################################")
codeList=[2345,
         2670,
         2700,
         3486,
         3646,
         3696,
         4004,
         4544,
         4587,
         4619]#0217記事
fileName="0217記事"#.txtなしで記載すること

if fileName!='' and len(codeList)!=0:
    cList=twList()
    cList.outputText(codeList,fileName)
    print(fileName)


print("End#####################################")

出力例

START#####################################

文字列処理開始
/Users/toshiromaseda/Documents/2021年/2021年株/トレーディングビュー
TSE:2345,TSE:2670,TSE:2700,TSE:3486,TSE:3646,TSE:3696,TSE:4004,TSE:4544,TSE:4587,TSE:4619
文字列処理終了
0217記事
End#####################################

Pythonを使ってヤフーファイナンス日経平均株価の時系列を取得、スクレイピング

Python を使ってヤフーファイナンス 日経平均株価の時系列を取得、スクレイピング
#https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O
#日経平均株価の時系列のテーブル表から該当の文字列を取得する、日付 始値 高値 安値 終値

https://github.com/maseda1030/yahoofinance_python.git

import time
from selenium import webdriver
import csv
import datetime
import os

class jikeiretsu:
    def __init__(self,day,kopen,khigh,klow,kclose):
        self.day=day
        self.kopen=kopen
        self.khigh=khigh
        self.klow=klow
        self.kclose=kclose
        
class yahooFinanceTimeline:
    def __init__(self):
        self.hello="yahoo Finace"
        
    def getTimeline(self):
        #print("カプセルにして取得")
         #動作確認のためのメソッド
        # 仮想ブラウザ起動、URL先のサイトにアクセス
        driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
        #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
        url='https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O'
        driver.get(url)
        time.sleep(1)
        #title = driver.title
        #print(title)
        main = driver.find_element_by_id("main")
        el = main.find_element_by_css_selector(".padT12.marB10.clearFix")
        tableElem = el.find_element_by_tag_name("table")
        trs = tableElem.find_elements_by_tag_name("tr")
        ths = trs[0].find_elements_by_tag_name("th")
        kabuka=""
        #thタグは1行目のTRにだけ存在する。
        for f in range(0,len(ths)):#日付	始値	高値	安値	終値
            ths[f].text
            kabuka+=ths[f].text+" "
        print(kabuka)
        jikeiretsuArray=[]
        for i in range(0,len(trs)):
            tds = trs[i].find_elements_by_tag_name("td")
            if len(tds)>=5:
                getJikeiretsu=jikeiretsu(tds[0].text,tds[1].text,tds[2].text,tds[3].text,tds[4].text)
                jikeiretsuArray.append(getJikeiretsu)
            else: 
                print("tdsの数が足りない行があるので無視")
        time.sleep(1)    
        driver.close()#起動したウィンドウを閉じる
        print("通常出力日付	始値	高値	安値	終値")
        for f in range(0,len(jikeiretsuArray)):
            print(jikeiretsuArray[f].day,jikeiretsuArray[f].kopen,jikeiretsuArray[f].khigh,jikeiretsuArray[f].klow,jikeiretsuArray[f].kclose)
        print('+----------------------+')
        print("個人的出力順、CSVカンマ区切りで 桁区切りのカンマは削除、昇順day,High,Low,Open,Close,AdjClose")#("個人的な利用の出力順、昇順day,High,Low,Open,Close,AdjClose")    
        count=len(jikeiretsuArray)
        tmpstr=""    
        for n in reversed(range(count)):#).replace(',','') カンマを削除
            tmpstr=jikeiretsuArray[n].day+","+jikeiretsuArray[n].khigh.replace(',','')+","+jikeiretsuArray[n].klow.replace(',','')+","+\
                  jikeiretsuArray[n].kopen.replace(',','')+","+jikeiretsuArray[n].kclose.replace(',','')+","+\
                  jikeiretsuArray[n].kclose.replace(',','')
            print(tmpstr)

    #テスト用のメソッドなので実際は不要なメソッド        
    def getTimelineTest(self):
        print("test")
        #動作確認のためのメソッド
        # 仮想ブラウザ起動、URL先のサイトにアクセス
        driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
        #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
        url='https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O'
        #driver.get(url+str(code)+'.T')
        driver.get(url)
        time.sleep(1)
        #title = driver.title
        #print(title)
        main = driver.find_element_by_id("main")
        #el = main.find_element_by_id("stockinf")
        #nextClass = el.find_element_by_css_selector(".stocksDtl.clearFix")
        el = main.find_element_by_css_selector(".padT12.marB10.clearFix")
        tableElem = el.find_element_by_tag_name("table")
        trs = tableElem.find_elements_by_tag_name("tr")
        ths = trs[0].find_elements_by_tag_name("th")
        kabuka=""
        #thタグは1行目のTRにだけ存在する。
        for f in range(0,len(ths)):#日付	始値	高値	安値	終値
            ths[f].text
            kabuka+=ths[f].text+" "
        print(kabuka)
        kabuka=""
        for i in range(0,len(trs)):
            tds = trs[i].find_elements_by_tag_name("td")
            for m in range(0,len(tds)):
                kabuka+=tds[m].text+" "#ここはカプセルにしてクラスオブジェクトを配列に入れたほうがいいかも
                #print(kabuka)
            print(kabuka)
            kabuka=""
        time.sleep(1)    
        driver.close()#起動したウィンドウを閉じる
###START
print("START#####################################")
print("Japan yahoo financeの日経平均株価の時系列")
getstock=yahooFinanceTimeline()
getstock.getTimeline()

print("End#####################################")

 

出力例

START#####################################
Japan yahoo financeの日経平均株価の時系列
カプセルにして取得
日付 始値 高値 安値 終値 
tdsの数が足りない行があるので無視
通常出力日付	始値	高値	安値	終値
2021年2月16日 30,229.46 30,714.52 30,191.65 30,467.75
2021年2月15日 29,662.41 30,092.34 29,662.41 30,084.15
2021年2月12日 29,635.88 29,650.51 29,417.32 29,520.07
2021年2月10日 29,412.55 29,562.93 29,368.18 29,562.93
2021年2月9日 29,435.61 29,585.75 29,350.48 29,505.93
2021年2月8日 28,831.58 29,400.56 28,817.6 29,388.5
2021年2月5日 28,631.46 28,785.71 28,548.27 28,779.19
2021年2月4日 28,557.46 28,600.22 28,325.89 28,341.95
2021年2月3日 28,482.71 28,669.95 28,402.3 28,646.5
2021年2月2日 28,207.48 28,379.31 28,089.12 28,362.17
2021年2月1日 27,649.07 28,107.1 27,649.07 28,091.05
2021年1月29日 28,320.72 28,320.72 27,629.8 27,663.39
2021年1月28日 28,169.27 28,360.48 27,975.85 28,197.42
2021年1月27日 28,665.34 28,754.99 28,542 28,635.21
2021年1月26日 28,696.3 28,740.71 28,527.81 28,546.18
2021年1月25日 28,698.89 28,822.29 28,566.85 28,822.29
2021年1月22日 28,580.2 28,698.18 28,527.16 28,631.45
2021年1月21日 28,710.41 28,846.15 28,677.61 28,756.86
2021年1月20日 28,798.74 28,801.19 28,402.11 28,523.26
2021年1月19日 28,405.49 28,720.91 28,373.34 28,633.46
+----------------------+
個人的出力順、カンマを削除、昇順day,High,Low,Open,Close,AdjClose
2021年1月19日,28720.91,28373.34,28405.49,28633.46,28633.46
2021年1月20日,28801.19,28402.11,28798.74,28523.26,28523.26
2021年1月21日,28846.15,28677.61,28710.41,28756.86,28756.86
2021年1月22日,28698.18,28527.16,28580.2,28631.45,28631.45
2021年1月25日,28822.29,28566.85,28698.89,28822.29,28822.29
2021年1月26日,28740.71,28527.81,28696.3,28546.18,28546.18
2021年1月27日,28754.99,28542,28665.34,28635.21,28635.21
2021年1月28日,28360.48,27975.85,28169.27,28197.42,28197.42
2021年1月29日,28320.72,27629.8,28320.72,27663.39,27663.39
2021年2月1日,28107.1,27649.07,27649.07,28091.05,28091.05
2021年2月2日,28379.31,28089.12,28207.48,28362.17,28362.17
2021年2月3日,28669.95,28402.3,28482.71,28646.5,28646.5
2021年2月4日,28600.22,28325.89,28557.46,28341.95,28341.95
2021年2月5日,28785.71,28548.27,28631.46,28779.19,28779.19
2021年2月8日,29400.56,28817.6,28831.58,29388.5,29388.5
2021年2月9日,29585.75,29350.48,29435.61,29505.93,29505.93
2021年2月10日,29562.93,29368.18,29412.55,29562.93,29562.93
2021年2月12日,29650.51,29417.32,29635.88,29520.07,29520.07
2021年2月15日,30092.34,29662.41,29662.41,30084.15,30084.15
2021年2月16日,30714.52,30191.65,30229.46,30467.75,30467.75
End#####################################

 

今日のPythonエラー クラスを作ったときにtakes 0 positional arguments but 1 was given

Pythonで
クラスを作ってメソッドを作ったらエラーになった。
takes 0 positional arguments but 1 was given

https://qiita.com/matsuida55/items/4188430631353a7a1194
「pythonはクラスメソッドの引数1つ目に必ず self を取らなければならない。」

・結論
クラスのメソッドの引数は必要なくても、 引数selfを入れなくてはならない。

誤り:エラーになるtakes 0 positional arguments but 1 was given

#python class サンプル
class nikkeiClass: 
    def __init__(self, cindex, chigh):
        self.index = cindex 
        self.high = chigh 

    def sample():#引数はないのでブランクにした>> ここが誤り
        print(self.index)
        
##START
test=nikkeiClass("aa","bb")
test.sample()
>>>エラー発生 takes 0 positional arguments but 1 was given

正しい

#python class サンプル
class nikkeiClass: 
    def __init__(self, cindex, chigh):
        self.index = cindex 
        self.high = chigh 

    def sample(self):#引数にselfがないとエラーになる
        print(self.index)
        
##START
test=nikkeiClass("aa","bb")
test.sample()
出力結果
aa

 

Pythonを使ってヤフーファイナンス情報を取得、スクレイピング

#複数企業コード対応版 企業コードから企業名と株価を取得する
#Anaconda JupyterLabによる動作 Shift+Enterで実行になる

動作環境:MacOS 、Python、Anaconda JupyterLab

https://github.com/maseda1030/yahoofinance_python.git

面倒だった点は、複数タグが存在するタグ名tr,td,ddの扱い。複数の場合forで回して配列みたいにしてデータを取得する必要があるし、スペースが含まれるクラス名は別のプロパティ?で読み込む必要がある。

find_element_by_class_nameでスペースを含むクラス名はエラーとなるので、find_element_by_css_selectorとしてドット.で接続する。

誤り:el.find_element_by_class_name(‘stocksDtl clearFix’)

正:el.find_element_by_css_selector(“.stocksDtl.clearFix”)

以下はサンプルコード。使い方は、codelistに企業コードを入力すると、ヤフーファイナンスからスクレイピングして「コード、企業名、終値株価、前日比、日付」を半角スペース区切りで出力するだけ。ヤフーファイナンスに接続するときは、取得間隔を1,2秒程度空けている。連続で取得するとサーバ負荷が増えるから強制切断とかアクセスをブロックされてしまうかもしれない。

>>コード修正、Spanタグが存在しない時間帯があるみたいなので、存在するかどうかのチェックを追記した。2021年2月8日、12時06分

import time
from selenium import webdriver
import csv
import datetime
import os

codelist=[]
codelist=[6315,2207,6928,5724,2702]#企業コード、複数

def getName(code):
    # 仮想ブラウザ起動、URL先のサイトにアクセス
    driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
    #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
    url='https://stocks.finance.yahoo.co.jp/stocks/detail/?code='
    driver.get(url+str(code)+'.T')
    #time.sleep(1)
    #title = driver.title
    #print(title)
    main = driver.find_element_by_id("main")
    el = main.find_element_by_id("stockinf")

    #エラー、nextClass = el.find_element_by_class_name('stocksDtl clearFix') Classにスペースが含まれるとエラーになるので別のメソッドにする
    nextClass = el.find_element_by_css_selector(".stocksDtl.clearFix")
    subNextClass = nextClass.find_element_by_class_name("forAddPortfolio")
    tableElem = subNextClass.find_element_by_class_name("stocksTable")
    dlElem = subNextClass.find_element_by_css_selector(".stocksInfo.clearFix")
    
    dds = dlElem.find_elements_by_tag_name("dd")
    trs = tableElem.find_element_by_tag_name("tr")
    symbol = trs.find_element_by_class_name("symbol")
    name = symbol.find_element_by_tag_name("h1")
    stockinfo = []
    stockinfo.append(str(code))
    stockinfo.append(name.text)
    tds = trs.find_elements_by_tag_name("td")
    
    for j in range(0,len(tds)):
        if tds[j].text != "":
            stockinfo.append(tds[j].text)

    ##ddタグの中に spanタグがあって、他に文字がある。spanタグのテキストだけが取得したかった。
    ##>>追記 2021年2月8日エラー処理を追加
    if len(dds[1].find_elements_by_tag_name("span"))>0:#存在チェック elementでなくてelementsにする
        stockinfo.append(dds[1].find_element_by_tag_name("span").text)#日付
    output=stockinfo
    driver.close()#起動したウィンドウを閉じる
    return output

###START
print("START#####################################")
tmpStr=""
f=0
for i in codelist:
    outputStr=getName(i)
    #コード、企業名、終値株価,前日比、日付
    for m in outputStr:
        if f==2:
            tmpStr+=m+'円'+' '
        else:
            tmpStr+=m+' '
        f+=1
        #print(outputStr[0],outputStr[1],outputStr[2]+"円",outputStr[3],outputStr[4])
    print(tmpStr)
    tmpStr=""
    f=0
    time.sleep(2)
print("End#####################################")

 

更に修正した。メソッドをクラスにした。また始値、高値、安値を入れた。2021/02/12

#Python を使って#ヤフーファイナンス 情報を取得、#スクレイピング 
#複数企業コード対応版 企業コードから企業名と株価を取得する
#Anaconda JupyterLabによる動作 Shift+Enterで実行になる
#修正、クラスに変更
#修正2021/02/12、始値、高値、安値を入れた

#手作業はcodelistにコードを入れる
import time
from selenium import webdriver
import csv
import datetime
import os

codelist=[]
codelist=[6134,7952,6462
         ]#企業コード、複数
#これからは、どんなに小さなプログラムでもクラスを使用する。そのほうが汎用性がある。
#同じメソッド名でもクラス名が異なればコピペして使用できる
class yahooFinanceClass():
        def __init__(self):
            self.hello="yahoo Finace"
        
        def getName(self,code):
            # 仮想ブラウザ起動、URL先のサイトにアクセス
            driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
            #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
            url='https://stocks.finance.yahoo.co.jp/stocks/detail/?code='
            driver.get(url+str(code)+'.T')
            time.sleep(1)
            #title = driver.title
            #print(title)
            main = driver.find_element_by_id("main")
            el = main.find_element_by_id("stockinf")

            #エラー、nextClass = el.find_element_by_class_name('stocksDtl clearFix') Classにスペースが含まれるとエラーになるので別のメソッドにする
            nextClass = el.find_element_by_css_selector(".stocksDtl.clearFix")
            subNextClass = nextClass.find_element_by_class_name("forAddPortfolio")
            tableElem = subNextClass.find_element_by_class_name("stocksTable")
            dlElem = subNextClass.find_element_by_css_selector(".stocksInfo.clearFix")

            dds = dlElem.find_elements_by_tag_name("dd")
            trs = tableElem.find_element_by_tag_name("tr")
            symbol = trs.find_element_by_class_name("symbol")
            name = symbol.find_element_by_tag_name("h1")
            stockinfo = []
            stockinfo.append(str(code))
            stockinfo.append(name.text)
            tds = trs.find_elements_by_tag_name("td")

            for j in range(0,len(tds)):
                if tds[j].text != "":
                    stockinfo.append(tds[j].text)

            ##始値、高値、安値を取得
            detail = main.find_element_by_id("detail")
            innerDate = detail.find_element_by_class_name("innerDate")
            innerDate_divs = innerDate.find_elements_by_css_selector(".lineFi.clearfix")#S複数
            for n in range(0,len(innerDate_divs)):
                if len(innerDate_divs[n].find_elements_by_class_name("tseDtl"))>0:#存在確認は複数形
                    tseDtl = innerDate_divs[n].find_element_by_class_name("tseDtl")#こっちは単数
                    kubun=tseDtl.find_element_by_class_name("title").text
                    #共通の処理をまとめた
                    if kubun=="安値" or kubun=="高値" or kubun=="始値":
                        ymuiEditLink=tseDtl.find_element_by_css_selector(".ymuiEditLink.mar0")
                        kabuka=ymuiEditLink.find_element_by_tag_name("strong").text
                    #配列に追加    
                    if kubun=="安値":
                        stockinfo.append("安値:"+kabuka)
                    elif kubun=="高値":
                        stockinfo.append("高値:"+kabuka)
                    elif kubun=="始値":  
                        stockinfo.append("始値:"+kabuka)
                              
            ##ddタグの中に spanタグがあって、他に文字がある。spanタグのテキストだけが取得したかった。
            ##>>追記 2021年2月8日エラー処理を追加
            if len(dds[1].find_elements_by_tag_name("span"))>0:#存在チェック elementでなくてelements(複数S)にする
                stockinfo.append(dds[1].find_element_by_tag_name("span").text)#日付 こっちは単数のelement  
            output=stockinfo
            driver.close()#起動したウィンドウを閉じる
            return output
        
###START
print("START#####################################")
tmpStr=""
f=0
obj=yahooFinanceClass()
for i in codelist:
    outputStr=obj.getName(i)
    #コード、企業名、終値株価,前日比、日付
    for m in outputStr:
        if f==2:
            tmpStr+=m+'円'+' '
        else:
            tmpStr+=m+' '
        f+=1
        #print(outputStr[0],outputStr[1],outputStr[2]+"円",outputStr[3],outputStr[4])
    print(tmpStr)
    tmpStr=""
    f=0
    time.sleep(2)
print("End#####################################")    
'''出力例
START#####################################
6134 (株)FUJI 2,795円 前日比+51(+1.86%) 始値:2,794 高値:2,832 安値:2,777 14:08 
7952 (株)河合楽器製作所 3,510円 前日比+380(+12.14%) 始値:3,200 高値:3,540 安値:3,155 14:06 
6462 (株)リケン 2,400円 前日比+114(+4.99%) 始値:2,449 高値:2,449 安値:2,329 14:07 
End#####################################  
'''

 

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')

 

今日のエラー、Mysql、Can’t connect to local MySQL server

A・症状2021/01/06

iMacを再起動した後で、Anaconda NavigatorからPythonを実行した
するとエラーが発生。PythonでMysqlを使用しているエラーのようだ。
エラーの一部:Can’t connect to local MySQL server through
Mysqlサーバに接続できない

・対応

Mysqlを使用しているPythonでエラーが発生したとき、Can’t connect to local MySQL server through
たぶんMysqlが起動していないから(PCを起動した直後や再起動するとMysqlは停止しているからMysqlを起動する)
(1)mysqlサーバを起動する。ターミナルから実行する
$ mysql.server start
このrootはいつもの(秘密)パスワードで、CSV取り込みは、Test1030のパスワード

(2)Mysqlに接続する(以下は個別のアカウントmasedaを使用した場合。rootの場合はmysql -u root -p)
$ mysql -u maseda -p
Test1030(これは知られてもよい)のパスワード

(3)通常のMysqlコマンドやPythonから実行する
実行できた。

 

B SyntaxError

・症状

pythonを実行したらエラーメッセージが表示された

・エラーメッセージ

SyntaxError: invalid syntax

対応

指定された行の上の行の閉じカッコの数があっていなかった。
1個少なかったために、次の行でエラーが表示されていた。
test((a,a),(1,1,1)   <<<閉じカッコが足りない
testB()<<<ここでエラーが表示


test((a,a),(1,1,1))

python便利なコマンド使い方、備忘録チートメモ、pythonにはswitch case文はない

配列の要素数はlen(array)で数える

メソッドはdefを先頭に付ける。def funcname():。メソッドを外部ファイルにしたいときは、ファイル名:testfunc.pyだったらimport testfunc(ファイル名、拡張子を除く)とする。

if文でelse ifは pythonではelif(勝手にエリフと読んでる)。一致条件はイコール2つ== if :elif:
elseは同じ。中括弧は使わない。

pythonには、switch case文はない

1行コメントは先頭に#
コメントの複数行はシングルクォーテーション3つかダブルクォーテーション3つで囲む。”’ commnet ”’

改行(折返し)は行末にバックスラッシュ\を付けて改行できる(マックの場合はOptionキーと¥キー、Winの場合はAltキーと¥キー)

文字の結合はプラス+。’abc’+’def’ >>abcdef

print(‘Max:’,max(df))#配列dfに複数の数値が入ってるとしてmax()で最大値が取れる。最小値はmin()

c,mod=divmod(a,b) 商cと余りmodが同時に取得できる

ループ、途中の3から5の数字を使って計算したいときrangeを使う。
for i in range(3,6):で、rangeを使うと3,4,5のように途中から取得できる但し、6は出力されないので注意。ここでは5までが対象になる。6を対象にしたかったら1加算してrange(3,7)のようにする

ディレクトリのTXTファイル一覧を取得 import glob, files=glob.glob(path+’*.txt’)、pathにはディレクトリのパスを入れること。

Int moji=5(int型)を文字にしたいstr(moji)で文字5になる

インクリメントi++、デクリメントi–は存在しない。i+=1,i-=1とする

文字列の挿入は、文字列の2番めの文字(1の後ろ)にabc文字を挿入したい。
tmpstr=’0123456′
hoge=tmpstr[:2]+’abc’+tmpstr[2:]
print(hoge)#01abc23456
[:0][0:]だとabc0123456になる

正規表現はimport re 、re.compile,searchがある。#findで正規表現ができない(と思う)

置換はsub

年月日の取得例
from datetime import datetime
end = datetime.now()
start = datetime(end.year, end.month, end.day)
print(‘start:’,start.strftime(“%Y/%m/%d”))
print(‘today:’,end.strftime(“%Y/%m/%d”))
–月をまたいでもOKな記載は以下
from datetime import datetime,timedelta
end = datetime.now()
#start = datetime(end.year, end.month, end.day-8)#こっちだと月マタギでエラーになる。
start = end – timedelta(days=7)

pass で何もしない。!=を使いたくないときやとりあえずコードを書いて実行したいときに使える
if i==10:
pass
else:
a=20