楽天マーケットスピードII　RSSを使って株価を取得

# はじめに

以前、楽天証券のマーケットスピードII RSSを使って、市況情報(株価)リスト作成するプログラムをpythonで作りました。

https://qiita.com/heroshi/items/d6466e80eee5a463f111

が、パソコンを新しくしたところ、次のようなエラーがよく出るようになりました。

```python
pywintypes.com_error: (-2147418111, '呼び出し先が呼び出しを拒否しました。', None, None)
```

エクセルとのやり取りでエラーが出ているようでしたので、エラーが出てもプログラムが途中で止まらないように、while文とtry except文を追加しました。

```python
while True:
    try:
        xl.Cells(no+2, row+2).Formula = "=RssMarket("+str(stock_no)+","+"\""+item+"\")" 
        break
    except pywintypes.com_error:
        print("再試行中..")
        time.sleep(1) 
```

tryでエラーが出なかった場合、whileを抜け出します。
もしエラーが出たら、1秒待って、再度、tryします。
それでもエラーが出たら、1秒待って、tryというふうにエラーが出なくなるまで繰り返します。

あちこちに、これを入れることによって、最後までエラーを出さないで終わることができました。

# プログラムの変更について
株価のリストを作るプログラムを更新しました。
前回より変えたところは、上で示したエラー対策と、RSSで読み取る関数をリストに入れたことです。
また、全銘柄だと数が多すぎるため、プログラムの中で、次のような辞書とif文を入れています。
```python
sel_dic={'PBR':1, '購入可能額':50000, '配当利回り':3} #エクセルにリストとして残す選択条件　
```
```python
if sel_dic['購入可能額']<ws_new.cell(n+2, add_list.index("購入可能額")+2).value:
    ws_new.delete_rows(n+2)
elif sel_dic['配当利回り']>ws_new.cell(n+2, add_list.index("配当利回り")+2).value:
    ws_new.delete_rows(n+2)
elif sel_dic['PBR']<ws_new.cell(n+2, add_list.index("PBR")+2).value: 
    ws_new.delete_rows(n+2)
```
これを使って、PBRが1未満、購入可能額が5万円未満、配当利回りが3%より大きいものを選択したリストを作成しています。

# プログラム
プログラムを実行するうえで、次のことが必要ですので、ご注意ください。
1. 楽天証券のマーケットスピードIIのログイン
2. エクセルの起動とRSSへの接続

```python
#プログラム実行前に次の1～2が必要です

#1. マーケットスピードIIのログイン
#2. エクセルを起動　空白のブックを開く。RSS接続する。

#3. このプログラムを実行する
#4. プログラムが終了するまで待つ
#5. 終了したら、保存されたリストを確認する

#ライブラリのインポート
import win32com.client #RSSへ接続するためのエクセル用
from openpyxl import Workbook #エクセル保存用
import time #時間調整用
import pywintypes

#銘柄収集リスト
rss_list=['銘柄名称','現在日付','現在値','時価総額','単位株数','配当','PER','PBR'] #RSSの関数(例)
cal_list=['購入可能額','配当利回り'] #RSS関数から出た数値を使って計算する
add_list=rss_list+cal_list
sel_dic={'PBR':1, '購入可能額':50000, '配当利回り':3} #エクセルにリストとして残す選択条件　

#収集準備
try:
    xl = win32com.client.GetObject(Class="Excel.Application")   #2 開いている空白のブック
except pywintypes.com_error:
    print("エクセルが開いていません。")
xl.Visible=True    

#市場コード
start_no=1300 #開始番号
step_no=500 #RSSでは1度に500銘柄まで取得可能のため500
end_no=9999 #終了番号 

#エクセルファイルの作成
wb_new=Workbook()   
ws_new=wb_new.active 

#RSSのタイトル行を記入
xl.Cells(1, 1).value = "市場コード" 
for row, item in enumerate(rss_list):
    xl.Cells(1, row+2).Value = item 

#エクセル表のタイトル作成
ws_new.cell(1, 1).value =  "市場コード"
for row, item in enumerate(add_list):
    ws_new.cell(1, row+2).value = item

#RSSのデータ取得
n=0
for code_no in range(start_no, end_no, step_no):    #500件ずつ繰り返す
    xl.Range(xl.Cells(2,1), xl.Cells(step_no+2, len(rss_list)+1)).ClearContents() #表示をクリア

    #RSS表読み出し
    for no in range(step_no): #500件以下
        stock_no=code_no+no
        if stock_no<=end_no:        
            while True:
                try:
                    xl.Cells(no+2, 1).Value = str(stock_no)    #銘柄コード 行(no+2) 列(1)
                    break
                except pywintypes.com_error:
                    print("再試行中..")
                    time.sleep(1)  # エラーが出たら、指定時間（秒）待機して繰り返す

            for row, item in enumerate(rss_list):
                while True:
                    try:
                        xl.Cells(no+2, row+2).Formula = "=RssMarket("+str(stock_no)+","+"\""+item+"\")"    #銘柄コード
                        break
                    except pywintypes.com_error:
                        print("再試行中..")
                        time.sleep(1)    # エラーが出たら、指定時間（秒）待機して繰り返す
                        
    time.sleep(10) #rss 関数の表示待ち。 時間が短いと表示される前に、次に進んでしまうため。

    #エクセル表作成
    for no in range(step_no):  
        stock_no=code_no+no
        if stock_no<=end_no:        
            stock_name=xl.Cells(no+2, rss_list.index("銘柄名称")+2).Value #銘柄が空白かを調べる
            if stock_name!="": #空白以外を取り込む
                for row in range(len(add_list)):  
                    while True:
                        try:
                            ws_new.cell(n+2, row+1).value = xl.Cells(no+2,row+1).Value
                            break
                        except pywintypes.com_error:
                            print("再試行中..")
                            time.sleep(1)  # エラーが出たら、指定時間（秒）待機して繰り返す

                ws_new.cell(n+2,add_list.index("購入可能額")+2).value=ws_new.cell(n+2, add_list.index("現在値")+2).value*ws_new.cell(n+2, add_list.index("単位株数")+2).value
                try:
                    ws_new.cell(n+2, add_list.index("配当利回り")+2).value=ws_new.cell(n+2,add_list.index("配当")+2).value/ws_new.cell(n+2, add_list.index("現在値")+2).value*100
                except ZeroDivisionError:
                    ws_new.cell(n+2,add_list.index("配当利回り")+2).value=0
                
                if sel_dic['購入可能額']<ws_new.cell(n+2, add_list.index("購入可能額")+2).value:
                    ws_new.delete_rows(n+2)
                elif sel_dic['配当利回り']>ws_new.cell(n+2, add_list.index("配当利回り")+2).value:
                    ws_new.delete_rows(n+2)
                elif sel_dic['PBR']<ws_new.cell(n+2, add_list.index("PBR")+2).value: 
                    ws_new.delete_rows(n+2)
                else:
                    n=n+1
    print(str(int(stock_no/end_no*100))+"%"+"進行中")
#リストを保存 保存先やファイル名は適当に入力してください。
wb_new.save("C:\\○○○○\\銘柄収集.xlsx")

```

# 完成表
プログラムを実行すると、次のような表が作成されます。

![スクリーンショット 2023-07-09 001502.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3245171/87665e74-e9b9-9912-414a-8366e2d6fc88.png)