【Python】スクレイピングで株価データを取得する

スクレイピング
この記事は約17分で読めます。

株をやっていると自分で過去の株価データを分析したくなると思います。ここでは、株価データを提供しているサイトからスクレイピングするプログラムを紹介します。

スクレイピングのプログラムを書く前に、スクレイピングの手順や注意点、テクニックをこちらのページに纏めているので、こちらも参考にしてください。

スポンサーリンク

株価データ提供サイト

まずは株価データを提供しているサイトについてです。昔はyahooから取得できたのですが、現在はスクレイピングが禁止されているので、別を探しました。
ありがたいことにこちらのサイトで株価データを提供してくださっているので、こちらを利用させていただきたいと思います。

robots.txtの確認

サイトによっては、スクレイピングが禁止されているものがあります。
スクレイピングをしてよいかどうかを確認するためには、各サイトのrobots.txtを見ることで確認できます。

robots.txtの見方をご存じない方はこちらのサイトで詳細がわかるので確認してください。

念の為、https://kabuoji3.com/robots.txtにアクセスし、robots.txtを確認したところ、rootからスクレイピングを許可してくれているので、ありがたくスクレイピングさせていただきます。(2019年7月14日時点)

User-Agent: * 
Allow:/
Sitemap:http://kabuoji3.com/sitemap/sitemap-index.xml

必要なモジュールのインストール

pythonにはスクレイピングを簡単に行えるBeautifulSoupという便利なモジュールがあります。今回はこのBeautifulSoupというモジュールを利用したいと思います。
ただし、BeautifulSoup以外にも必要なモジュールがいくつかありますので、以下のモジュールがインストールされていない方は、pip installでインストールしてください。versionは最新のもので良いので特に指定しなくて良いです。
pipがよくわからない方はこちらをご参照ください。
Pythonの始め方④ pipとは?Pythonを便利に利用するためのpipの理解

  • bs4(BeautifulSoupのこと)
  • pandas
  • requests

PythonのBeautifulSoupを使って株価データをスクレイピング

モジュールのインポート

モジュールをインポートします。datetimeというモジュールをインポートしていますが、これはpythonの標準モジュールなので、pip installしなくてもpythonをインストールした時点ですでに存在しているはずです。

from bs4 import BeautifulSoup
import pandas as pd
import requests
from datetime import datetime

ページのhtmlを取得

取得したい銘柄の株価データは、https://kabuoji3.com/stock/以下に”/銘柄コード/年”という形式で存在しているようです。

y = 2019 #2019年
stock_number = 6577 #好きな銘柄コード、今回はベスト・ワンドットコム
url = 'https://kabuoji3.com/stock/{}/{}/'.format(stock_number,y)
soup = BeautifulSoup(requests.get(url).content,'html.parser')

上記のようにBeautifulSoupでページのHTMLソースを取得すると以下のようなHTMLが得られます。

<!DOCTYPE HTML>

<html class="no-js" lang="ja">
<head>
<meta charset="utf-8"/>
<!--[if IE]>
<meta http-equiv="X-UA-Compatible" content="requiresActiveX=true">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<![endif]--><title>6577 (株)ベストワンドットコム 2019年度の株価データ・株価データ、CSVダウンロード | 株式投資メモ・株価データベース</title>
<meta content="6577 (株)ベストワンドットコム 2019年度の株価推移を時系列で確認できます。株価データのCSVダウンロードも可能です。株式投資、システムトレードや株価分析に有益な情報を多数配信!" name="description">
<meta content="6577,(株)ベストワンドットコム,マザーズ,サービス業,2019年,株式投資,株価,株価推移,時系列データ,CSVデータ,CSVダウンロード" name="keywords"/>
<meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"/>
<meta content="#fff" name="msapplication-TileColor"/>
<meta content="images/mstile-144x144.png" name="msapplication-TileImage"/>
<meta content="telephone=no" name="format-detection"/>
<link href="https://kabuoji3.com/images/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon"/>
<link href="https://kabuoji3.com/images/favicon.ico" rel="icon" type="image/vnd.microsoft.icon"/>
<link href="https://kabuoji3.com/images/apple-touch-icon-57x57.png" rel="apple-touch-icon" sizes="57x57"/>
<link href="https://kabuoji3.com/images/apple-touch-icon-60x60.png" rel="apple-touch-icon" sizes="60x60"/>
<link href="https://kabuoji3.com/images/apple-touch-icon-72x72.png" rel="apple-touch-icon" sizes="72x72"/>
<link href="https://kabuoji3.com/images/apple-touch-icon-76x76.png" rel="apple-touch-icon" sizes="76x76"/>
<link href="https://kabuoji3.com/images/apple-touch-icon-114x114.png" rel="apple-touch-icon" sizes="114x114"/>
<link href="https://kabuoji3.com/images/apple-touch-icon-120x120.png" rel="apple-touch-icon" sizes="120x120"/>
<link href="https://kabuoji3.com/images/apple-touch-icon-144x144.png" rel="apple-touch-icon" sizes="144x144"/>
...

もし上記のコードでデータ得られない場合は、BeautifulSoupのrequestを投げる際にheaderを入れる必要があるかもしれません。その方法に関しては別途記事を書いていますのでそちらをご参照ください。

株価データをデータフレーム化

ページのHTMLの構成を頑張って調べていきます。
調べると割と整ったテーブルになっており、trタグの中のthタグにテーブルのヘッドがあり、trタグの中のtdタグにデータが入っている構成でした。

tag_tr = soup.find_all('tr')
head = [h.text for h in tag_tr[0].find_all('th')] #テーブルのヘッドの取得

#テーブルの各データの取得
data = []
for i in range(1,len(tag_tr)):
    data.append([d.text for d in tag_tr[i].find_all('td')])
    df = pd.DataFrame(data, columns = head)

テキストデータを数値、タイムスタンプに変換

上で作成したdfを表示すると以下のようになっており、無事データフレーム化できたように思うのですが、見た目にはわからないのですが、実はすべてテキストデータなので、このままだとグラフを書いたりする時に扱いづらいままです。

したがって、数字をfloatに、日付をタイムスタンプに変換します。

col = ['始値','高値','安値','終値','出来高','終値調整']
for c in col:
    df[c] = df[c].astype(float)
df['日付'] = [datetime.strptime(i,'%Y-%m-%d') for i in df['日付']]

dfを再度表示すると以下のように数字の後ろに小数点が現れていると思います。(今回はわかりやすいようにfloatにしましたが、実際はintでも問題ありません)
見た目ではわかりませんが、日付もタイムスタンプに変換されているはずです。

複数年のデータの取得

このサイトでは株価データが年ごとに別ページにわかれているので、ページをfor文で繰り返して取得する必要があります。あと、最終的にはすべての年を1つのデータフレームにしたいので、結合したほうが良いと思います。ということで以下のようなコードになります。

#複数年のデータフレームの作成
dfs = []
year = [2018,2019]
for y in year:
    url = 'https://kabuoji3.com/stock/{}/{}/'.format(stock_number,y)
    soup = BeautifulSoup(requests.get(url).content,'html.parser')
    tag_tr = soup.find_all('tr')
    head = [h.text for h in tag_tr[0].find_all('th')]
    data = []
    for i in range(1,len(tag_tr)):
        data.append([d.text for d in tag_tr[i].find_all('td')])
    df = pd.DataFrame(data, columns = head)

    col = ['始値','高値','安値','終値','出来高','終値調整']
    for c in col:
        df[c] = df[c].astype(float)
    df['日付'] = [datetime.strptime(i,'%Y-%m-%d') for i in df['日付']]
    dfs.append(df)
 
#複数年のデータフレームの結合
data = pd.concat(dfs,axis=0)
data = data.reset_index(drop=True)

取得した株価の銘柄リストを作成する

自分が取得したい株価の銘柄リストを作成します。私が取得したい銘柄は10倍株検索をした以下の銘柄になります。
10倍株検索に関してはこちらを参照ください。
「いま仕込んでおくべき10倍株教えます!」に従って銘柄検索してみた

codename
2424ブラス
2820やまみ 
2970グッドライフC
3134Hamee
3172ティーライフ
3180ビューティガレージ
3189ANAP
3276日本管理
3457ハウスドゥ 
3474G-FAC
3480ジェイ・エス・ビー
3496アズーム
3566ユニネク
3674オークファン 
3695GMOリサーチ
3696セレス
3965CAP
3985テモナ
3986ビーブレイク
3992ニーズウェル
3997トレードワークス
6036KeePer技研
6038イード
6044三機サービス
6048デザインワン
6061ユニバ園芸
6087アビスト
6171土木管理総合試験所
6175ネットマーケティング
6199セラク
6558クックビズ
6577ベストワンドット
7042アクセスグループ
7813プラッツ
9270SOU

このテーブルをcsvにして以下のコードで読み込みます。

code_list = pd.read_csv('code_list.csv')
code_list.head(10)

表示すると以下のようなcode listが得られているはずです。

まとめコード

最後に上記のコードを関数化し、複数の銘柄コードを取得するコードにしておきます。
古い年月まで含めるとデータがないですよと怒られることがあるので、try文を使ってエラー回避しています。最後にcsvで保存しておきます。

from bs4 import BeautifulSoup
import pandas as pd
import requests
from datetime import datetime

def get_dfs(stock_number):
    dfs = []
    year = [2018,2019] #2017〜2019年までの株価データを取得
    for y in year:
        try:
            print(y)
            url = 'https://kabuoji3.com/stock/{}/{}/'.format(stock_number,y)
            soup = BeautifulSoup(requests.get(url).content,'html.parser')
            tag_tr = soup.find_all('tr')
            head = [h.text for h in tag_tr[0].find_all('th')]
            data = []
            for i in range(1,len(tag_tr)):
                data.append([d.text for d in tag_tr[i].find_all('td')])
            df = pd.DataFrame(data, columns = head)

            col = ['始値','高値','安値','終値','出来高','終値調整']
            for c in col:
                df[c] = df[c].astype(float)
            df['日付'] = [datetime.strptime(i,'%Y-%m-%d') for i in df['日付']]
            dfs.append(df)
        except IndexError:
            print('No data')
    return dfs

def concatenate(dfs):
    data = pd.concat(dfs,axis=0)
    data = data.reset_index(drop=True)
    col = ['始値','高値','安値','終値','出来高','終値調整']
    for c in col:
        data[c] = data[c].astype(float)
    return data

#作成したコードリストを読み込む
code_list = pd.read_csv('code_list.csv')

#複数のデータフレームをcsvで保存
for i in range(len(code_list)):
    k = code_list.loc[i,'code']
    v = code_list.loc[i,'name']
    print(k,v)
    dfs = get_dfs(k)
    data = concatenate(dfs) 
    data.to_csv('{}-{}.csv'.format(k,v))

得られた株価データをローソク足チャートで可視化したい方はこちらの記事に可視化方法を書いていますので、御覧ください。

おすすめ書籍

スクレイピングに関してはこちらの書籍がおすすめです。

コメント

  1. Wiki より:

    はじめまして、
    スクリプトシェアしてありがとうございます。記事を拝見して試してみたんですが、
    最後のまとめコードを直接python3.6にコピーして実行すると、dfが未定義というエラーが出でいました。

    それで、
    df=pd.read_csv(‘code list.csv’)
    df.head(10)
    を入れて、
    そのdf未定義エラーがなくなりましたが、
    no dataというエラーが出で失敗しました。

    問題はどの辺でしょうか?

    以上
    よろしくお願いいたします。

    • topixtopix より:

      コメントありがとうございます。
      dfの定義のところ抜けておりました。ご指摘ありがとうございます。修正しておきます。

      コードを実行する前に、code_list.csvファイルを作成して、実行ファイルと同じフォルダに入れておく必要があります。
      code_list.csvの中身は以下のように自分が取得したい銘柄のコードと名称を、1列目に銘柄コード、2列目に銘柄名称がくるようにして作成すれば大丈夫です。
      エクセルで表を作って、csvで保存しても大丈夫です。

      code, name
      2424,ブラス
      2820,やまみ
      2970,グッドライフC
      3134,Hamee
      3172,ティーライフ
      3180,ビューティガレージ

      それでも動かない場合は、BeautifulSoupのrequestを投げる際にheaderを入れる必要があるかもしれません。
      それに関してはこちらの記事を参考にしてください。
      https://non-dimension.com/solution-403forbidden/

      わからなければまたご連絡ください。

  2. ise より:

    ひとまず上記のソース、list_csvをコピペして実行を試みましたが、出力結果が何もなく困っております。
    エラーメッセージはなく、正常終了しているように見えますが。
    本来であれば、スクレイピングした数値の.csvファイルを同じディレクトリに吐き出すのでしょうか?
    pythonのバージョンは3.8.2です

    • topixtopix より:

      一度こちらを試していただけますか?
      soupの部分を少し書き換えるだけです。
      https://non-dimension.com/solution-403forbidden/

      • ise より:

        13行目から15行目から以下のように書き換えましたが何も変わりません。
        スクレイピング先のサイト情報がかわりましたでしょうか?

        url = ‘https://kabuoji3.com/stock/{}/{}/’.format(stock_number,y)
        headers = {“Mozilla/5.0(長いので省略) }
        soup = BeautifulSoup(requests.get(url, headers = headers).content,’html.parser’)

        • topixtopix より:

          なにかエラーは出ていないでしょうか?
          try文を削除してみたらエラーが出てくるかもしれません。

          • ise より:

            11,30,31行目をコメントアウトしてみましたが、実行結果何も変わりません
            特にエラーなく、CSVも吐き出さない状態でした

          • topixtopix より:

            以下のようにprint文を入れて、変数dfs、dataをprintした場合、なにか表示されるでしょうか?

            for i in range(len(code_list)):
            k = code_list.loc[i,'code']
            v = code_list.loc[i,'name']
            print(k,v)
            dfs = get_dfs(k)
            print(dfs) #<=挿入 data = concatenate(dfs) print(data) #<=挿入 data.to_csv('{}-{}.csv'.format(k,v))

          • ise より:

            お世話になっております。
            以下が実行結果です。

            一点解決したのですが、csvファイルの文字コードがutf-8ではなくsjisだったためcsvが読み込めずループが実行されていなかったようでした。
            ただ、今度は以下のようなエラーになっております。

            2424 ブラス <=これは追加したprint文で変数dfs、dataが見えてるようです。
            2018
            Traceback (most recent call last):
            File "get.py", line 52, in
            dfs = get_dfs(k)
            File “get.py”, line 17, in get_dfs
            soup = BeautifulSoup(requests.get(url, headers = headers).content,’html.parser’)
            File “C:\中略\Python38-32\lib\site-packages\requests\api.py”, line 76, in get
            return request(‘get’, url, params=params, **kwargs)
            File “C:\中略\Python\Python38-32\lib\site-packages\requests\api.py”, line 61, in request
            return session.request(method=method, url=url, **kwargs)
            File “C:\中略\Python\Python38-32\lib\site-packages\requests\sessions.py”, line 516, in request
            prep = self.prepare_request(req)
            File “C:\中略\Python\Python38-32\lib\site-packages\requests\sessions.py”, line 449, in prepare_request
            p.prepare(
            File “C:\中略\Python38-32\lib\site-packages\requests\models.py”, line 315, in prepare
            self.prepare_headers(headers)
            File “C:\中略\Python38-32\lib\site-packages\requests\models.py”, line 447, in prepare_headers
            for header in headers.items():
            AttributeError: ‘set’ object has no attribute ‘items’

          • topixtopix より:

            headers = {“Mozilla/5.0(長いので省略) }と書かれていましたが、
            Mozillaの前に以下のように「”User-Agent”:」をいれて見てはいかがでしょうか?

            headers = {“User-Agent”: “Mozilla/5.0(長いので省略) }

          • ise より:

            >headers = {“Mozilla/5.0(長いので省略) }と書かれていましたが、
            >Mozillaの前に以下のように「”User-Agent”:」をいれて見てはいかがでしょうか?

            ありがとうございました。こちらで解決できました。
            ご指摘の通りuser-agentのところが抜けていたのが原因でした。

            この度は一通りのご対応いただき、ありがとうございました。
            pythonにはなじみが無いもので、エラーやらなにやら聞いてしまった次第です。

  3. u7ss より:

    はじめまして、とても参考になる、分かりやすい資料をシェアいただきましてありがとうございます。

    ただ、さっそく試し、うまくいきませんでした。コメント部分のheadersは追記しております。

    返されるエラーは以下の通りです。(headersを追記しているので、line番号に違いがあるかと思います。csvにもうまくアクセスできておりますが…)

    エラー内容は以下の通りです。(tryとexceptをコメントアウトしております):
    2424 ブラス
    2018
    []
    Traceback (most recent call last):
    File “d:\xxx\xxx\Desktop\kabuka.py”, line 50, in
    dfs = get_dfs(k)
    File “d:\xxx\xxx\Desktop\kabuka.py”, line 19, in get_dfs
    head = [h.text for h in tag_tr[0].find_all(‘th’)]
    IndexError: list index out of range

    ちなみに、記載したスクリプトは以下の通りです。(headers3行とprint(tag_tr)1行の計4行追記、tag_trが[]なのまではわかりました。)
    from bs4 import BeautifulSoup
    import pandas as pd
    import requests
    from datetime import datetime

    def get_dfs(stock_number):
    dfs = []
    year = [2018,2019] #2017〜2019年までの株価データを取得
    for y in year:
    # try:
    print(y)
    url = ‘https://kabuoji3.com/stock/{}/{}/’.format(stock_number,y)
    soup = BeautifulSoup(requests.get(url).content,’html.parser’)
    headers = {
    “User-Agent”: “Mozilla/5.0 xxx”
    }
    tag_tr = soup.find_all(‘tr’)
    print(tag_tr)
    head = [h.text for h in tag_tr[0].find_all(‘th’)]
    data = []
    for i in range(1,len(tag_tr)):
    data.append([d.text for d in tag_tr[i].find_all(‘td’)])
    df = pd.DataFrame(data, columns = head)

    col = [‘始値’,’高値’,’安値’,’終値’,’出来高’,’終値調整’]
    for c in col:
    df[c] = df[c].astype(float)
    df[‘日付’] = [datetime.strptime(i,’%Y-%m-%d’) for i in df[‘日付’]]
    dfs.append(df)
    # except IndexError:
    # print(‘No data’)
    return dfs

    def concatenate(dfs):
    data = pd.concat(dfs,axis=0)
    data = data.reset_index(drop=True)
    col = [‘始値’,’高値’,’安値’,’終値’,’出来高’,’終値調整’]
    for c in col:
    data[c] = data[c].astype(float)
    return data

    #作成したコードリストを読み込む
    code_list = pd.read_csv(‘code_list.csv’)

    #複数のデータフレームをcsvで保存
    for i in range(len(code_list)):
    k = code_list.loc[i,’code’]
    v = code_list.loc[i,’name’]
    print(k,v)
    dfs = get_dfs(k)
    data = concatenate(dfs)
    data.to_csv(‘{}-{}.csv’.format(k,v))

  4. u7ss より:

    先ほどのコメントですが、解決しました。headersをrequestsの引数に入れておりませんでした。
    お手数おかけして恐縮です。

  5. N1370 より:

    初めまして、いつもサイト拝見させていただいております。
    webスクレイピングについて自分なりのアレンジを加えて作ってみたのですが、最後のcsvファイルに変換する際にエラーが出てしまって困り果てており、お力添えをお願いできればとメールさせていただきました。
    スクリプトは以下の通りです。
    from bs4 import BeautifulSoup
    import pandas as pd
    import requests
    from datetime import datetime

    def get_dfs(stock_number):
    dfs = []
    url = ‘https://kabuoji3.com/stock/{}/’.format(stock_number)
    headers = { “User-Agent”: “※※”}
    soup = BeautifulSoup(requests.get(url, headers = headers).content, ‘html.parser’)
    tag_tr = soup.find_all(‘tr’)
    head = [h.text for h in tag_tr[0].find_all(‘th’)]
    data = []
    for i in range(1,len(tag_tr)):
    data.append([d.text for d in tag_tr[i].find_all(‘td’)])
    df = pd.DataFrame(data, columns = head)
    col = [‘始値’,’高値’,’安値’,’終値’,’出来高’,’終値調整’]
    for c in col:
    df[c] = df[c].astype(float)
    df[‘日付’] = pd.to_datetime(df[‘日付’])
    dfs.append(df)
    return data

    code_list = pd.read_csv(‘stocklist.csv’)

    for i in range(len(code_list)):
    k = code_list.loc[i,’銘柄コード’]
    v = code_list.loc[i,’銘柄名’]
    print(k,v)
    dfs = get_dfs(k)
    data = dfs
    data.to_csv(‘{}-{}.csv’.format(k,v))

    1301 (株)極洋
    —————————————————————————
    AttributeError Traceback (most recent call last)
    in
    6 dfs = get_dfs(k)
    7 data1 = dfs
    —-> 8 data1.to_csv(‘{}-{}.csv’.format(k,v))

    AttributeError: ‘list’ object has no attribute ‘to_csv’

    となっており、2年分のデータ取得を最新の300日のみにしたことで最後の
    data = ※※
    の部分を変えており、リスト属性のエラーが出ているのはわかるのですが、どこをいじったらいいのか全く分からず困っています。

    どうかよろしくお願いします。

    • topixtopix より:

      data1 = concatenate(dfs) を記述するか、
      data1=dfs[0]としてみてはいかがでしょうか?

      dfsはデータフレームをたくさん含むリストになっています。
      concatenateは複数のデータフレームを結合する処理をしています。
      データフレームが300日分の1テーブルしかないのであれば、dfsのリストの0番目のものをdfs[0]で取り出せると思います。

      • N1370 より:

        早速のご返答ありがとうございます。

        無事にCSVファイル出てきました!!

        ここ一週間ほど悩んでいたので本当に助かりました。

  6. […] […]

  7. M54 より:

    こんにちは。とても有益な情報をシェアして下さりありがとうございます。
    Python初心者でしたが、なんとか試行錯誤の末、CSVファイルの書き出しまでできるようになりました!

    一点、もし可能であれば、の話ですが、各銘柄のデータフレームを縦一つに繋げてCSVにするにはどのようなコーディングになるか、、を教えて頂きたいのです。

    紹介いただいている

    #複数のデータフレームをcsvで保存
    for i in range(len(code_list)):
    k = code_list.loc[i,’code’]
    v = code_list.loc[i,’name’]
    print(k,v)
    dfs = get_dfs(k)
    data = concatenate(dfs)
    data.to_csv(‘{}-{}.csv’.format(k,v))

    この部分を一部改変することになるかと思い、あれこれ調べてトライしてみたのですが、
    データフレームの組み立て方が悪いのか、関数の選び方(concatenate,append)が悪いのか、ここ数週間何も解決できてません、、センスのない質問ですみませんが、お知恵を貸していただけないでしょうか。

    • topixtopix より:

      pandasでデータフレームを結合する場合、merge, join, concatの3つの方法が使えます。
      どれを用いても良いですが、私はconcatをよく使います。

      2つのデータフレームdf1, df2があった場合、以下のように記述すれば縦方向に繋げられると思います。
      new_data = pd.concat([df1,df2], axis=0)

      axis = 0は縦方向、axis = 1とすると横方向に結合します。
      [df1,df2]のところはデータフレームのリストであれば、2つ以上でも結合可能です。
      上記の記事ではconcatenateという関数の中で、dfsというデータフレームのリストをpd.concat(dfs, axis=0)で結合しています。

      ただし、df1, df2が別の列名になっていたりうまく結合できなかったりするので注意が必要です。うまく行かない場合はまたご連絡いただければ。
      参考のリンクを張っておきます。
      https://note.nkmk.me/python-pandas-concat/

      • M54 より:

        topix様
        お礼が遅くなってしまいすみません。丁寧に回答下さり、またリンク先も貼って頂きありがとうございます。

        あれこれ頑張ってやってみたのですが、、どうも私のセンスが悪く…うまくできません。

        やろうとしていること:銘柄2970-グッドライフC,2820-やまみ,2424-プラス・・・の時系列データを、一つのCSVファイル内で縦に連結表示したい。
        最終的には行列の入替えをして縦列に銘柄、行に時系列データ、という形にしていきたい。

        ご教示頂いた
        >new_data = pd.concat([****], axis=0) の「***」の所にデータフレームのリストを渡してあげる、というイメージだと思うのですが、私のリストの作り方が的外れなのか、エラーを食らっております。
        ・testdata = []
        ・new_data = pd.concat([testdata], axis=0)を付け加えてみました。
        ___________________________________________________________
        #複数のデータフレームをcsvで保存
        testdata = []
        for i in range(len(code_list)):
        k = code_list.loc[i,’code’]
        dfs = get_dfs(k)
        data = concatenate(dfs)
        new_data = pd.concat([testdata], axis=0)
        new_data.to_csv(‘連結データ.csv’, encoding=’shift_jis’)
        ___________________________________________________________

        TypeError: cannot concatenate object of type ”; only Series and DataFrame objs are valid

        また、以下のパターン
        ・new_data = pd.concat([data], axis=0)を追加
        _____________________________
        #複数のデータフレームをcsvで保存
        for i in range(len(code_list)):
        k = code_list.loc[i,’code’]
        dfs = get_dfs(k)
        data = concatenate(dfs)
        new_data = pd.concat([data], axis=0)
        new_data.to_csv(‘連結データ.csv’, encoding=’shift_jis’)
        _____________________________
        この場合、エラーなく完了するものの、code_listの先頭にある2970-グッドライフCのデータのみが出力されてくる状態です。

        何とも面倒な質問ですみませんが、アドバイス頂けませんでしょうか。。

        • topixtopix より:

          以下のコードでいけませんでしょうか?

          for i in range(len(code_list)):
           k = code_list.loc[i,’code’]
           dfs = get_dfs(k)

          new_data = pd.concat(dfs, axis=0)
          new_data.to_csv(‘連結データ.csv’, encoding=’shift_jis’)

          • M54 より:

            topix様
            早速のご返答ありがとうございます。やってみますと、エラーなく完了はするのですが、グッドライフのみのデータが生成される。といった具合です。

            別パターンで
            new_data = pd.concat([dfs], axis=0)
            のようにdfsを[]で囲って実行すると、TypeError: cannot concatenate object ~のエラーになりました。

            別途、for文を入れ込む必要があるのでしょうかね。。

          • topixtopix より:

            dfsはすでにリストなので、dfsを[]で囲ってはいけません。
            書いているコードを直接貼り付けていただいたほうが良いですね。

          • M54 より:

            topixさま。お世話になります。
            現在のコードは以下の通りです。encoding=’shift_jis’のところは追記しています。コードリストの並びは、
            code name
            2424 ブラス
            2820 やまみ
            2970 グッドライフC
            なお、下記プログラム実行後は、グッドライフのデータのみ残るといった出来上がりです。

            from bs4 import BeautifulSoup
            import pandas as pd
            import requests
            from datetime import datetime

            def get_dfs(stock_number):
            dfs = []
            year = [2019,2020]
            for y in year:
            try:
            print(y)
            url = ‘https://kabuoji3.com/stock/{}/{}/’.format(stock_number,y)
            headers = { “User-Agent”:”Mozilla/5.0 **略**”}
            soup = BeautifulSoup(requests.get(url, headers = headers).content, ‘html.parser’)
            tag_tr = soup.find_all(‘tr’)
            head = [h.text for h in tag_tr[0].find_all(‘th’)] #テーブルのヘッドの取得
            #テーブルの各データの取得
            data = []
            for i in range(1,len(tag_tr)):
            data.append([d.text for d in tag_tr[i].find_all(‘td’)])
            df = pd.DataFrame(data, columns = head)
            col = [‘始値’,’高値’,’安値’,’終値’,’出来高’,’終値調整’]
            for c in col:
            df[c] = df[c].astype(float)
            df[‘日付’] = [datetime.strptime(i,’%Y-%m-%d’) for i in df[‘日付’]]
            dfs.append(df)

            except IndexError:
            print(‘No data’)
            return dfs

            def concatenate(dfs):
            data = pd.concat(dfs,axis=0)
            data = data.reset_index(drop=True)
            col = [‘始値’,’高値’,’安値’,’終値’,’出来高’,’終値調整’]
            for c in col:
            data[c] = data[c].astype(float)
            return data

            #作成したコードリストを読み込む
            code_list = pd.read_csv(‘code_list.csv’, encoding=’shift_jis’)

            #複数のデータフレームをcsvで保存
            for i in range(len(code_list)):
            k = code_list.loc[i,’code’]
            dfs = get_dfs(k)
            data = concatenate(dfs)

            new_data = pd.concat(dfs, axis=0)
            new_data.to_csv(‘連結データ.csv’, encoding=’shift_jis’)

タイトルとURLをコピーしました