【Python】画像の表からテキストを取り出しCSVファイルにする
まえがき
先日、以下のようなツイートをしました。
まとめると以下のような感じせっかく実現できたのを自分だけ満足してもったいない。
そこで記事にアウトプットしてみなさんと共有したいと思います。
目的
以下の画像の表からテキストを取り出しCSVファイルに編集します。
ファイル名はimage.jpg
とします。
ちなみに今回扱う画像は米国株の高配当銘柄の一覧を表示しています。
1行目にタイトルがあります。
2行目から2行ごとの表になっています。
表の数値は適当です。
各項目は以下の通りです。
① 銘柄名
② ティッカー | 株式 | 普通株
③ 配当利回り
④ 年間配当額
⑤ 配当権利落日
⑥ 配当権利落年
⑦ 配当額
⑧ 前回配当額
CSVファイルでは1行にまとめる必要があります。
まずはテキストを取り出しCSVファイルに保存します。
CSVファイル上で2行を1行にまとめていきます。
環境構築
開発環境
VS Codeでコーディングします。
VS Codeの拡張機能Jupyterをインストールします。
そして、VS Code上のJupyter notebookの環境を使います。
開発環境の構築が済んでない方は以下の記事を参考にしてみてください。
仮想環境
標準ライブラリであるvenv
を使ってPythonの仮想環境を構築します。
まずはプロジェクトのディレクトリを作成します。
ディレクトリ名はpyhon-image-ocr-yt
とします。
ディレクトリ名は適当につけていただいて結構です。
次に作成したディレクトリ内に移動して以下のコマンドを実行します。
python3 -m venv .venv
実行すると、新たにディレクトリ.venv
が作成されます。
仮想環境が構築できたら、仮想環境を有効化するために以下のコマンドを実行します。
source .venv/bin/activate
また、仮想環境を終わらせる時は、以下のコマンドを実行して終了します。
deactivate
ライブラリなどをインストール
必要なライブラリを仮想環境内にインストールします。
忘れないように、仮想環境を有効化しておきます。
source .venv/bin/activate
ひとつづつインストールしても良いですが、複数ある場合にはファイルrequirements.txt
を使う方法があります。
ファイルrequirements.txt
にインストールするパッケージを記入します。
今回は画像処理ライブラリPillowとOCRのライブラリPyOCRとtesseractを使用します。
# Jupyter Notebook
ipykernel
# 画像処理ライブラリ
Pillow
# OCRのライブラリ
PyOCR
tesseract
ファイルrequirements.txt
が用意できたら、以下のコマンドを実行して一括してインストールします。
pip3 install -r requirements.txt
ファイルを作成
新しいJupyter notebookのファイルを作成します。
ファイル名はimage-ocr.ipynb
とします。
このファイル名も適当につけていただいて結構です。
touch image-ocr.ipynb
画像を読み込む
画像を読み込むために、先ほどインストールした画像処理ライブラリPillowを使います。
まずはパッケージPIL
からImage
をインポートします。
from PIL import Image
image.jpg
をImage.open()
で取得して変数img
に渡します。
img = Image.open("image.jpg")
img
を実行すると読み込んだ画像が表示されます。
読み込んだ画像をOCRする
OCRのライブラリPyOCRとtesseractを使用します。
pyocr
をインポートします。
import pyocr
pyocr.get_available_tools()
でモジュールを取得して変数tools
に渡します。
tools = pyocr.get_available_tools()
tools
変数tools
に以下の2つのモジュールが入っています。
[<module 'pyocr.tesseract'>,
<module 'pyocr.libtesseract'>]
今回はtools
の中の1つ目のモジュールを使います。
変数tool
に渡します。
プログラミングでは0から始まるので慣れないうちは気をつけましょう。
tool = tools[0]
tool.image_to_string()
で画像データからテキストを読み込んで変数txt
に渡します。
tool.image_to_string()
の引数が3つあります。
1つ目の引数img
が先ほど取得した画像データimg
です。
2つ目の引数lang
には言語を指定します。今回は英数字を読み込むので値を"eng"
を渡します。
3つ目の引数builder
にはpyocr.builders.TextBuilder(tesseract_layout=3)
を渡します。
pyocr.builders.TextBuilder()
の引数tesseract_layout
にはレイアウト解析のオプションを指定します。
オプションは13種類ありデフォルトの値が3になっています。
読み込んでみて求めた結果でない時は数値を変えてみるといいでしょう。
txt = tool.image_to_string(
img,
lang = "eng",
builder = pyocr.builders.TextBuilder(tesseract_layout=3)
)
print()
を使ってtxt
の内容を確認します。
print(txt)
結果は以下のようになります。
name dividend-yield ex-date amount
CHEVRON CORP 3.56% 2/15 $1.51
CVX | stock | common $6.04 2023 Last $1.42
INTEL CORP. 4.82% 2/06 $0.37
INTC | stock | common $1.46 2023 Last $0.37
Pioneer Natural Resources Co. 0.60% 2/10 $0.23
PXD | stock | common $0.92 2023 Last $0.23
結果を見ると行の間に空の行があります。
そこでprint()
を使わずにtxt
の内容を確認します。
txt
確認すると1行目と6行目の行末に改行\n
が2つ連続あります。
'name dividend-yield ex-date amount\n\n
CHEVRON CORP 3.56% 2/15 $1.51\n
CVX | stock | common $6.04 2023 Last $1.42\n
INTEL CORP. 4.82% 2/06 $0.37\n
INTC | stock | common $1.46 2023 Last $0.37\n
Pioneer Natural Resources Co. 0.60% 2/10 $0.23\n\n
PXD | stock | common $0.92 2023 Last $0.23'
2度改行されることで結果的に空の行ができています。
そこで2つの改行\n
を1つにします。
replace()
を使って'\n\n'
を'\n'
に書き換えます。
txt = txt.replace('\n\n', '\n')
再びprint()
を使ってtxt
の内容を確認します。
print(txt)
空の行がなくなりました。
name dividend-yield ex-date amount
CHEVRON CORP 3.56% 2/15 $1.51
CVX | stock | common $6.04 2023 Last $1.42
INTEL CORP. 4.82% 2/06 $0.37
INTC | stock | common $1.46 2023 Last $0.37
Pioneer Natural Resources Co. 0.60% 2/10 $0.23
PXD | stock | common $0.92 2023 Last $0.23
今回は単純な原因でしたが、複雑な原因になるかもしれません。
その時はまた原因を見極めて対処します。
OCRしたテキストデータをファイルに保存する
OCRしたテキストデータをtest.csv
に保存します。
pathlib
をインポートします。
import pathlib
空のファイルtest.csv
のパスを指定します。
pathlib.Path()
を使って引数test.csv
を渡して、変数new_csv_file
に代入します。
ここではtest.csv
自体は作成されていません。
new_csv_file = pathlib.Path("test.csv")
空のファイルtest.csv
にOCRしたテキストをwrite_text()
を使って保存します。
write_text()
にOCRしたテキストを持つ引数txt
を渡します。
ここでOCRしたテキストがtest.csv
に保存されました。
new_csv_file.write_text(txt)
CSVファイルの中を処理する
ここからメインイベントです。
大変なのでじっくり読み進めてください。
多分、これが俗に言う「前処理」だと思います。
改めてtest.csv
の内容を見てみます。
name dividend-yield ex-date amount
CHEVRON CORP 3.56% 2/15 $1.51
CVX | stock | common $6.04 2023 Last $1.42
INTEL CORP. 4.82% 2/06 $0.37
INTC | stock | common $1.46 2023 Last $0.37
Pioneer Natural Resources Co. 0.60% 2/10 $0.23
PXD | stock | common $0.92 2023 Last $0.23
単語はスペースで区切られています。
そこで区切り文字をスペースでtest.csv
から文字列を取り出します。
csv
をインポートします。
import csv
空の配列を持つ変数lines
を準備します。
次にtest.csv
を開いてスペースで区切った単語を格納して変数reader
に取得します。
最後に変数reader
から各要素を変数row
に取り出して変数lines
に追加します。
それではprint()
と使って変数lines
の中を確認します。
lines = []
with open ("test.csv", 'r') as f :
reader = csv.reader(f, delimiter=' ')
for row in reader:
lines.append(row)
print(lines)
f.close()
実行すると以下のような結果になります。
7個の配列がありますね。
['name', 'dividend-yield', 'ex-date', 'amount'],
['CHEVRON', 'CORP', '3.56%', '2/15', '$1.51'],
['CVX', '|', 'stock', '|', 'common', '$6.04', '2023', 'Last', '$1.42'],
['INTEL', 'CORP.', '4.82%', '2/06', '$0.37'],
['INTC', '|', 'stock', '|', 'common', '$1.46', '2023', 'Last', '$0.37'],
['Pioneer', 'Natural', 'Resources', 'Co.', '0.60%', '2/10', '$0.23'],
['PXD', '|', 'stock', '|', 'common', '$0.92', '2023', 'Last', '$0.23']
各要素を確認するとわかりにくいですが、4行目の2つ目の要素にドット.
が含まれています。
せっかくなので確認してみます。
lines[3][1]
今回は4行目の2個目なので3
と1
で指定しています。
実行すると以下のような結果になります。
'CORP.'
CSVの区切り文字でよく使われるのはカンマ,
ですが、今回はわかりやすいようにコロン:
を使います。
出力した結果の各配列を見ると要素数がバラバラです。
そこで各配列の要素数を調べます。
len()
にlines
を渡して実行すると配列の数がわかります。
ここではlines
の中の配列の数を調べることになります。
len(lines)
実行すると以下のような結果になります。
7
先ほど出力した結果を確認すると7個の配列があるので合っています。
7個の各配列の要素数を調べます。
まずは1行目の配列の要素数lines[0]
を調べましょう。
len(lines[0])
実行すると結果が4
と表示されます。
1行目の配列は['name', 'dividend-yield', 'ex-date', 'amount']
なので合っています。
残りの配列も同様に調べてもいいんですが、配列の数が多くなればとても大変です。
for文
を使って繰り返し調べるようにします。
先ほど配列の数を調べた方法を利用します。
in
の後に繰り返す回数を指定します。
この場合は配列の数から繰り返す回数を指定できます。
for
の後のi
に0から順番に入れていきます。
結果はprint()
と使って表示します。
ただ数字だけだとわかりにくいのでf文字列
を使ってみます。
引数に渡す文字列""
の前にf
をつけます。
文字列の中で変数を{}
で囲うと値を代入して表示してくれます。
言葉で説明してもわかりにくいので実行してみましょう。
for i in range(len(lines)):
print(f"{i+1}行目の要素数は{len(lines[i])}個です")
実行すると以下のような結果になります。
1行目の要素数は4個です
2行目の要素数は5個です
3行目の要素数は9個です
4行目の要素数は5個です
5行目の要素数は9個です
6行目の要素数は7個です
7行目の要素数は9個です
今回は要素数がどういう状態なのかを調べるだけなのでf文字列
は使わなくても大丈夫です。
この後f文字列
を使うので頭の片隅に置いておいてください。
1行目は項目名なので無視します。
2行目から見ていくと偶数行は要素数が違いますが奇数行は要素数が9個と一定です。
偶数行
まずは要素数が違う偶数行に注目します。
以下のように偶数行だけ取り出します。
['CHEVRON', 'CORP', '3.56%', '2/15', '$1.51'],
['INTEL', 'CORP.', '4.82%', '2/06', '$0.37'],
['Pioneer', 'Natural', 'Resources', 'Co.', '0.60%', '2/10', '$0.23'],
銘柄名の単語数が異なることで要素数が違っています。
逆に後ろから3個の要素はいずれの配列でも同様な項目内容となっています。
よって後ろから要素を取り出します。
6行目を使って各要素を取り出して見ましょう。
lines[5]
実行すると以下のように表示されます。
['Pioneer', 'Natural', 'Resources', 'Co.', '0.60%', '2/10', '$0.23']
一番後ろの配当額を変数amount
に代入、
後ろから2番目の配当権利落日を変数ex_date
に代入、
後ろから3番目の配当利回りを変数dividend_yield
に代入します。
amount = lines[5][-1] # 配当額
ex_date = lines[5][-2] # 配当権利落日
dividend_yield = lines[5][-3] # 配当利回り
コードを見るとわかりやすいですが、配列の要素はマイナス値で指定すると後ろから取り出すことができます。
[-1]
は1番後ろ、[-2]
は後ろから2番目・・・のようにです。
想定通りか確認しておきます。
print(amount)
print(ex_date)
print(dividend_yield)
実行すると以下のような結果になります。
ここまでは問題ありません。
$0.23
2/10
0.60%
残りは単語単位で分かれている銘柄名のみとなります。
これは1つの要素にまとめます。
まずは最初の要素は確実に銘柄名の最初に単語なので変数company
を用意してlines[5][0]
を代入します。
company = lines[5][0]
残りの必要な要素を取り出します。
再び要素を取り出す配列を見ます。
['Pioneer', 'Natural', 'Resources', 'Co.', '0.60%', '2/10', '$0.23'],
この場合は銘柄名に必要な残りの要素は3つです。
その要素はlines[5][1]
、lines[5][2]
、lines[5][3]
で取り出せます。
3つの要素を取り出すためにここでもfor文
を使います。
for文
を使えば単語数が増えても簡単に対応できます。
要素数の値が必要なのでlen(lines[5])
を参考に考えていきます。
銘柄名に必要な最後の要素は後ろから数えると4個目の要素となります。
これは銘柄名の単語数には影響されません。
と言うことはlen(lines[5])
から4
引けばfor文
で使えそうです。
それでは百聞は一見に如かずなのでコードを書いていきます。
for i in range(len(lines[5])-4):
print(i)
実行すると以下のような結果になります。
0
1
2
lines[5][1]
、lines[5][2]
、lines[5][3]
と同様に値を得るためには結果の値に1を足せばいいですね。
for i in range(len(lines[5])-4):
print(i+1)
実行すると以下のような結果になります。
1
2
3
print()
を使ってlines[5][i]
として実行します。
ここでは要素の値ではなくて要素の変数自体をf文字列
を使って表示します。
for i in range(len(lines[5])-4):
print(f"lines[5][{i+1}]")
実行すると以下のような結果になります。
lines[5][1]
lines[5][2]
lines[5][3]
後はf文字列
を外せば変数に値自体を受け取れます。
for i in range(len(lines[5])-4):
print(lines[5][i+1])
実行すると以下のような結果になります。
Natural # lines[5][1]の値
Resources # lines[5][2]の値
Co. # lines[5][3]の値
後は繋げ合わせれば完成です。
銘柄名の最初の単語が入った変数company
に加えていきます。
company = lines[5][0]
for i in range(len(lines[5])-4):
company = company + lines[5][i+1]
company
実行すると以下のような結果になります。
'PioneerNaturalResourcesCo.'
これでは単語が詰まって繋がっています。
単語の間にスペースを入れます。
ここで便利なのがf文字列
です。
for文
の中で変数company
にf文字列
を使って都度代入します。
company = lines[5][0]
for i in range(len(lines[5])-4):
company = f"{company} {lines[5][i+1]}"
company
実行すると以下のような結果になります。
'Pioneer Natural Resources Co.'
今度こそ上手くいきました。
f文字列
を使うことでうまい具合にスペースを入れることができました。
ここでいったんまとめると以下のコードになります。
company = lines[5][0]
for i in range(len(lines[5])-4):
company = f"{company} {lines[5][i+1]}"
company # 銘柄名
amount = lines[5][-1] # 配当額
ex_date = lines[5][-2] # 配当権利落日
dividend_yield = lines[5][-3] # 配当利回り
これで偶数行の「前処理」を終えました。
奇数行
次は奇数行の「前処理」です。
ここまで6行目に処理をしたので相方の7行目を使います。
まずは7行目の要素を表示します。
lines[6]
実行すると以下のように表示されます。
['PXD', '|', 'stock', '|', 'common', '$0.92', '2023', 'Last', '$0.23']
画像の表では1つの項目だった要素が分かれています。
具体的には②の値は5個の要素、⑧の値も2個の要素に分かれています。
ただ問題ないのでこのまま進めていきます。
'|'
、'stock'
、'common'
、'Last'
が必要ありません。
あとは適宜変数を決めて必要な要素を一気に代入します。
そしてprint()
を使って確認します。
ticker = lines[6][0] # ティッカー
year_dividend = lines[6][5] # 年間配当額
year_pay_date = lines[6][6] # 配当権利落年
last_amount = lines[6][8] # 前回配当額
print(ticker)
print(year_dividend)
print(year_pay_date)
print(last_amount)
実行すると以下のように表示されます。
PXD
$0.92
2023
$0.23
奇数行と偶数行の要素をまとめる
奇数行と偶数行で取り出した要素を1つにまとめます。
再び要素を取り出したコードをまとめておきます。
# 偶数行
company = lines[5][0]
for i in range(len(lines[5])-4):
company = f"{company} {lines[5][i+1]}"
company # 銘柄名
amount = lines[5][-1] # 配当額
ex_date = lines[5][-2] # 配当権利落日
dividend_yield = lines[5][-3] # 配当利回り
# 奇数行
ticker = lines[6][0] # ティッカー
year_dividend = lines[6][5] # 年間配当額
year_ex_date = lines[6][6] # 配当権利落年
last_amount = lines[6][8] # 前回配当額
ここで1つ問題があります。
配当権利落日が月日と年で分かれています。
f文字列
を使って結合します。
ex_date = f"{year_ex_date}/{ex_date}"
ex_date
に月日と年が結合して代入されました。
f文字列
を使って1つにまとめていきます。
最初に区切り文字をコロン:
にすることを忘れないようにします。
f"{company}:{ticker}:{amount}:{dividend_yield}:{ex_date}:{year_dividend}\n"
実行すると以下のように表示されます。
'Pioneer Natural Resources Co.:PXD:$0.23:0.60%:2023/2/10:$0.92\n'
少しわかりにくいですが、これで2行を1行にできました。
残りの複数の2行ごとも1行にしなければいけません。
そこで再びfor文
で回して2行を1行にします。
コードを見ながら考えて見ましょう。
# 偶数行
company = lines[5][0]
for i in range(len(lines[5])-4):
company = f"{company} {lines[5][i+1]}"
company # 銘柄名
amount = lines[5][-1] # 配当額
ex_date = lines[5][-2] # 配当権利落月日
dividend_yield = lines[5][-3] # 配当利回り
# 奇数行
ticker = lines[6][0] # ティッカー
year_dividend = lines[6][5] # 年間配当額
year_ex_date = lines[6][6] # 配当権利落年
last_amount = lines[6][8] # 前回配当額
ex_date = f"{year_ex_date}/{ex_date}" # 配当権利落年月日
奇数と偶数を求める必要があります。
奇数と偶数を求めるには変数に2をかければ偶数、2をかけて1を足せば奇数になります。
それを踏まえて偶数行を求めたインデックス番号と奇数行を求めたインデックス番号を変数j
を使って変更します。
変数i
はもう使っているので気をつけましょう。
具体的には偶数行に[2*j-1]
、奇数行は[2*j]
に変更します。
今回は偶数と奇数が交差してわかりにくいですが混同しないように気をつけます。
# 偶数行
company = lines[2*j-1][0]
for i in range(len(lines[2*j-1])-4):
company = f"{company} {lines[2*j-1][i+1]}"
company # 銘柄名
amount = lines[2*j-1][-1] # 配当額
ex_date = lines[2*j-1][-2] # 配当権利落月日
dividend_yield = lines[2*j-1][-3] # 配当利回り
# 奇数行
ticker = lines[2*j][0] # ティッカー
year_dividend = lines[2*j][5] # 年間配当額
year_ex_date = lines[2*j][6] # 配当権利落年
last_amount = lines[2*j][8] # 前回配当額
ex_date = f"{year_ex_date}/{ex_date}" # 配当権利落年月日
これで変数j
を回せるようになりました。
次は回す回数を考えます。
改めて「前処理」するデータを見ます。
['name', 'dividend-yield', 'ex-date', 'amount'],
['CHEVRON', 'CORP', '3.56%', '2/15', '$1.51'],
['CVX', '|', 'stock', '|', 'common', '$6.04', '2023', 'Last', '$1.42'],
['INTEL', 'CORP.', '4.82%', '2/06', '$0.37'],
['INTC', '|', 'stock', '|', 'common', '$1.46', '2023', 'Last', '$0.37'],
['Pioneer', 'Natural', 'Resources', 'Co.', '0.60%', '2/10', '$0.23'],
['PXD', '|', 'stock', '|', 'common', '$0.92', '2023', 'Last', '$0.23']
1行目lines[0]
は項目名でした。
2行目lines[1]
は1個目のデータの偶数行です。
3行目lines[2]
は1個目のデータの奇数行です。
2行目と3行目を処理して1個の配列にまとめます。
後は同様に繰り返します。
そして配列数len(lines)
は7になります。
ただここで単純にlen(lines)
で変数j
を回していくとエラーになります。
回数がオーバーしてしまうからです。
そこでオーバーしないように計算式を考えます。
今回の場合は3
を求めることになります。
いろいろ求め方はありますが今回は2
で割って小数点以下を切り捨てるようにします。
小数点以下を切り捨てるにはmath
モジュールのfloor()
を使います。
import math
math.floor(len(lines)/2)
実行すると以下のように表示されます。
3
これで準備ができたのでコードを書いていきます。
for j in range(math.floor(len(lines)/2)):
# 偶数行
company = lines[2*j-1][0]
for i in range(len(lines[2*j-1])-4):
company = f"{company} {lines[2*j-1][i+1]}"
company # 銘柄名
amount = lines[2*j-1][-1] # 配当額
ex_date = lines[2*j-1][-2] # 配当権利落月日
dividend_yield = lines[2*j-1][-3] # 配当利回り
# 奇数行
ticker = lines[2*j][0] # ティッカー
year_dividend = lines[2*j][5] # 年間配当額
year_ex_date = lines[2*j][6] # 配当権利落年
last_amount = lines[2*j][8] # 前回配当額
ex_date = f"{year_ex_date}/{ex_date}" # 配当権利落年月日
print(f"{company}:{ticker}:{amount}:{dividend_yield}:{ex_date}:{year_dividend}")
実行しましたがエラーになりました。
for文
で回しているj
の値を確認します。
for j in range(math.floor(len(lines)/2)):
print(j)
実行すると以下のように表示されます。
0
1
2
うっかりしていました。
0
から回してしまうと最初がlines[-1]
とインデックスが-1
になってしまいます。
lines[1]
とlines[2]
から処理できるようにインデックスを指定する数式を変更します。
for j in range(math.floor(len(lines)/2)):
# 偶数行
company = lines[2*j+1][0]
for i in range(len(lines[2*j+1])-4):
company = f"{company} {lines[2*j+1][i+1]}"
company # 銘柄名
amount = lines[2*j+1][-1] # 配当額
ex_date = lines[2*j+1][-2] # 配当権利落月日
dividend_yield = lines[2*j+1][-3] # 配当利回り
# 奇数行
ticker = lines[2*(j+1)][0] # ティッカー
year_dividend = lines[2*(j+1)][5] # 年間配当額
year_ex_date = lines[2*(j+1)][6] # 配当権利落年
last_amount = lines[2*(j+1)][8] # 前回配当額
ex_date = f"{year_ex_date}/{ex_date}" # 配当権利落年月日
print(f"{company}:{ticker}:{amount}:{dividend_yield}:{ex_date}:{year_dividend}")
実行すると以下のように表示されます。
CHEVRON CORP:CVX:$1.51:3.56%:2023/2/15:$6.04
INTEL CORP.:INTC:$0.37:4.82%:2023/2/06:$1.46
Pioneer Natural Resources Co.:PXD:$0.23:0.60%:2023/2/10:$0.92
やっと想定通りに表示できました。
後はファイルに保存するだけです。
あと一息なのでがんばりましょう。
前のコードに少し手を加えます。
まずはfor文
の前に保存するテキストを格納する空の変数out
を設定します。
次にfor文
の中の最後に空の変数out
に出力した文字列を追加します。
最後にprint(out)
で想定通りなのか確認します。
out = ""
for j in range(math.floor(len(lines)/2)):
# 偶数行
company = lines[2*j+1][0]
for i in range(len(lines[2*j+1])-4):
company = f"{company} {lines[2*j+1][i+1]}"
company # 銘柄名
amount = lines[2*j+1][-1] # 配当額
ex_date = lines[2*j+1][-2] # 配当権利落月日
dividend_yield = lines[2*j+1][-3] # 配当利回り
# 奇数行
ticker = lines[2*(j+1)][0] # ティッカー
year_dividend = lines[2*(j+1)][5] # 年間配当額
year_ex_date = lines[2*(j+1)][6] # 配当権利落年
last_amount = lines[2*(j+1)][8] # 前回配当額
ex_date = f"{year_ex_date}/{ex_date}" # 配当権利落年月日
out += f"{company}:{ticker}:{amount}:{dividend_yield}:{ex_date}:{year_dividend}\n"
print(out)
実行すると以下のような結果になります。
変数out
の内容が想定通り表示されました。
CHEVRON CORP:CVX:$1.51:3.56%:2023/2/15:$6.04
INTEL CORP.:INTC:$0.37:4.82%:2023/2/06:$1.46
Pioneer Natural Resources Co.:PXD:$0.23:0.60%:2023/2/10:$0.92
変数out
の内容をtest.csv
に保存します。
open()
を使って第1引数は開くファイル"test.csv"
、第2引数には書き込み可能にする"w"
を渡します。
test.csv
を開いたらまずファイル内をtruncate()
で空にします。
変数out
を引数にしてwrite()
で保存します。
最後はclose()
してファイルを閉じます。
with open("test.csv", "w") as f:
f.truncate()
f.write(out)
f.close()
実行してtest.csv
を確認します。
CHEVRON CORP:CVX:$1.51:3.56%:2023/2/15:$6.04
INTEL CORP.:INTC:$0.37:4.82%:2023/2/06:$1.46
Pioneer Natural Resources Co.:PXD:$0.23:0.60%:2023/2/10:$0.92
やっとこれで完成しました。
長丁場でしたがおつかれさまでした。
あとがき
データを取り出して保存するところまでは面倒でありませんでした。
CSVファイルのデータを処理していくのはとても大変でした。
ただ、面倒でも一度だけプログラミングを頑張ってみてください。
プログラムで実現できれば、次からは代わりにやってくれます。
CSVファイルにすればいろんなことに展開できます。
CSVファイルからデータベースに登録するとか。
私の場合はツイートしたように、CSVファイルからHTMLファイルにしました。
アウトプットしたことで思っていた改善点を解決するヒントも得ることができました。
Discussion