LoginSignup
2
2

More than 5 years have passed since last update.

FRBの金利データをRSSから抜き出してみる-4

Posted at

 前回の記事で、URLを生成するプロセスに問題があることがわかった。
 そこで、今回はJSONによるサイトマップを作成した後、JSONの形式に合わせてURL取得プログラムを変更し、モジュールを実装して正常に動作することを確認した。

作業

JSON形式の変更

まず、JSONをこのようなサイトマップ形式にした。

{
    "Yield Curve":
    {
        "FF":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFSPFF_N.B.XML",
        "M01":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCM01_N.B.XML",
        "M03":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCM03_N.B.XML",
        "M06":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCM06_N.B.XML",
        "Y01":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY01_N.B.XML",
        "Y02":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY02_N.B.XML",
        "Y03":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY03_N.B.XML",
        "Y05":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY05_N.B.XML",
        "Y10":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY10_N.B.XML",
        "Y20":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY20_N.B.XML",
        "Y30":"https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY30_N.B.XML"
    }
}

プログラムの書き直し

そして、プログラムをこのように書き直した。

import json
import os
class site_map:
    def __init__(self, path,filename):
        #__変数で擬似ローカル変数になる
        #ファイルのあるフォルダまでのパスを取得
        __name = os.path.dirname(os.path.abspath(__name__)) 
        #変換対象のjsonファイルまでのパスを作成
        __path=__name+'/' + path + '/' + filename
        #絶対パスに変換
        __abspath=os.path.normpath(__path)

        #jsonファイルを開く
        __f = open(__abspath, 'r')
        __jsonData=json.load(__f)

        #urlの前半と後半の共通部分を取得
        #__prefix=__jsonData[idx0][prefix]
        #__suffix=__jsonData[idx0][suffix]

        #目次を取得
        __indexList = __jsonData.keys()
        #dict_keyをリストに変換
        __indexList=list(__indexList)


    def get_index(self):
        return __indexList

    def get_url(self,index):
        return self.urlList
        #戻り値となるリストを作成
        self.urlList=[]

        for __num in __indexList:
            #サイトマップに含まれるURLを一つづつ取得
            __url=__jsonData[index][num]

            #urlを生成してリストに
            self.urlList.append(__url)

        return self.ursList

    #JSONファイルを閉じるデストラクタ。不要か?
    def __del__(self):
        __f.close()

a=site_map("target","siteMap.json")

さて、実行して見よう。

Traceback (most recent call last):
  File "D:\Document\Visual Studio 2017\source\repos\PythonApplication2\PythonApplication2\modules\get_url.py", line 58, in <module>
    print(a.get_index())
  File "D:\Document\Visual Studio 2017\source\repos\PythonApplication2\PythonApplication2\modules\get_url.py", line 37, in get_index
    return __indexList
NameError: name '_site_map__indexList' is not defined
Exception ignored in: <bound method site_map.__del__ of <__main__.site_map object at 0x000001EFA3D2A9E8>>
Traceback (most recent call last):
  File "D:\Document\Visual Studio 2017\source\repos\PythonApplication2\PythonApplication2\modules\get_url.py", line 55, in __del__
NameError: name '_site_map__f' is not defined

動かない。どうやら、プライベート変数は同じクラス内でも関数が異なれば呼び出せないようだ。関数で呼び出す必要のある変数にselfをつけていく。あと、URLをリストに加える手続きに間違いがあったので直した。

import json
import os
class site_map:
    def __init__(self, path,filename):
        #__変数で擬似ローカル変数になる
        #ファイルのあるフォルダまでのパスを取得
        __name =str(os.path.dirname(os.path.abspath(__name__)) )
        #変換対象のjsonファイルまでのパスを作成
        __path=__name+'/' + path + '/' + filename
        #絶対パスに変換
        __abspath=os.path.normpath(__path)

        #jsonファイルを開く
        self.f = open(__abspath, 'r')
        self.jsonData=json.load(self.f)

        #urlの前半と後半の共通部分を取得
        #__prefix=__jsonData[idx0][prefix]
        #__suffix=__jsonData[idx0][suffix]

        #目次を取得
        __indexList = self.jsonData.keys()
        #dict_keyをリストに変換
        self.indexList=list(__indexList)


    def get_index(self):
        return self.indexList

    def get_url(self,index):
        #戻り値となるリストを作成
        self.urlList=[]
        __secIndex=list(self.jsonData[index].keys())
        for __key in __secIndex:
            #サイトマップに含まれるURLを一つづつ取得
            __url=self.jsonData[index][__key]

            #urlを生成してリストに
            self.urlList.append(__url)

        return self.urlList

    #JSONファイルを閉じるデストラクタ。不要か?
    def __del__(self):
        self.f.close()

a=site_map("target","siteMap.json")
b=a.get_index()
print(b)
print(a.get_url(b[0]))

出力

['Yield Curve']
['https://www.federalreserve.gov/feeds/Data/H15_H15_RIFSPFF_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCM01_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCM03_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCM06_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY01_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY02_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY03_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY05_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY10_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY20_N.B.XML', 'https://www.federalreserve.gov/feeds/Data/H15_H15_RIFLGFCY30_N.B.XML']

これでOKだ。

プログラムの実装

 これに合わせて、今回のメインモジュールである、getFFRateも少し改良した。

from time import sleep
from modules import XMLprocess
from modules import get_url
import sqlite3


class get_FFRate:
    #アクセスマップの入ったファイルを指定
    def __init__(self,path,filename,index):
        #アクセスするurlのリストを取得
        __scr=get_url.site_map(path,filename)
        self.urlList=__scr.get_url(index)
    #日付取得用の関数
    def get_date(self):   
        __XML=XMLprocess(self.urlList[0])
        __strdate=__XML.get_cutedData("dc:date",0,10)
        __XML=None
        return __strdate

    def get_rate(self,url):
        __XML=XMLprocess(url)
        __rate=__XML.get_floatData("cb:value")
        __XML=None
        return __rate
    #urlのリストに基づいてデータを取得していく
    def get_list(self):
        rateList=[]
        #日付をリストに入れる(主キーのつもり)
        rateList.append(self.get_date())

        for __url in self.urlList:
            __rate=self.get_rate(__url)
            rateList.append(__rate)
            #1秒間待つ
            sleep(1)
        __XML=None
        return rateList
a=get_url.site_map("target","siteMap.json")
b=a.get_index()
print(b)
for idx in b:
    #今後の発展性を持たせるためのテスト
    ff=get_FFRate("target","siteMap.json",idx)

print(ff.get_list())

出力:

['YieldCurve']
['2018-06-07', 1.7, 1.78, 1.94, 2.12, 2.31, 2.5, 2.63, 2.77, 2.93, 3.0, 3.08]

まとめ

 今回の改良のキモは、スクレイピングの対象をJSONファイルでコントロールできるようになったことだ。これで、getFFRateのもう一つ上位にモジュールを配置できるようになった。ただこのままだとgetFFRateのモジュールがちょっとごちゃごちゃしている気がする。
 少なくとも、親モジュールでsite_mapを呼び出しているならば、getFFRateでもう一度呼び出す理由がない。また、そのほうが他のデータを取得していく際にも使い勝手が良いだろう。モジュールをそのうち改良していきたい。
 今度は、データベースに接続してみたいと思う。
 ところで、そろそろソース管理が面倒になってきたので、今話題の「設計図管理ソフト」GitHubを使ってみたいと思っている。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2