質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.60%

繰り返し処理でAPIの上限を超える結果を取得したい

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 848

score 15

前提・実現したいこと

プログラミング初心者です。Python3でAPIを使い、国会会議録から該当キーワードの検索結果を年度ごとに取得し、ファイルに書き込みたいと考えています。このAPIは一度に取得できる検索結果の件数が100件と決まっているため、繰り返し処理を書きました。しかしエラーは出ないものの、上限設定を超えた結果は得られていません。

発生している問題・エラーメッセージ

エラーメッセージは出ず、取得した検索結果はファイルに書き込まれますが、確認すると取得できている検索結果はデフォルト上限設定の100件のみに留まっています。

該当のソースコード

import requests
from bs4 import BeautifulSoup

#検索結果の総件数を取得する関数
#総件数は<numberofrecords>の要素として返ってくる
def all_api(year):
    with open('../thesis/sr'+ str(year) +'.txt', 'r', encoding="utf-8-sig") as fr:
        soup = BeautifulSoup(fr, 'lxml')
        nor = int(soup.find("numberofrecords").string)
    fr.close
    return(nor)

#検索結果をファイルに書き込む
for i in range(1990, 1992+1):
    url = 'http://kokkai.ndl.go.jp/api/1.0/speech?maximumRecords%3D100%26any%3D責任%26from%3D' + str(i) +'-01-01%26until%3D' + str(i) + '-12-31' 
    req = requests.get(url)
    fw = open('../thesis/sr'+ str(i) +'.txt', 'w', encoding="utf-8")
    fw.write(req.text)
    res_num = all_api(i)
    fw.close

count = 1 #検索結果の開始位置「startRecord」を指定するためのカウンタ

#検索結果が100件を超える場合、urlで取得した検索結果を該当ファイルに追記する
for i in range(1990, 1992+1):
    while res_num > 0:
        with open('../thesis/sr'+ str(i) +'.txt', 'a', encoding="utf-8-sig") as fa:
       url = 'http://kokkai.ndl.go.jp/api/1.0/speech?startRecord%3D' + str(count) + '%26maximumRecords%3D100%26any%3D責任%26from%3D' + str(i) + '-01-01%26until%3D' + str(i) + '-12-31'
            req = requests.get(url)
            fa.write(req.text)
            res_num = res_num - 100
            count += 1

試したこと

国会会議録APIの仕様を確認し、<numberofrecords>以外の返戻タグを使って同じ処理を書こうとしました。しかし、うまくいきませんでした。

補足情報(FW/ツールのバージョンなど)

国会会議録APIの仕様は以下のとおりです。

・国会会議録検索システム -国会会議録検索システム検索用APIについて-
http://kokkai.ndl.go.jp/api.html

※teratailの使い方にも慣れていないため、何かおかしなことをしていたら、お手数ですがご指摘ください。至らぬ点は改めていきます。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

国会会議録検索システム検索用APIについて のページの表"指定可能な検索パラメータ"の1項目に"開始位置"の説明があり、パラメータ名がstartRecordであることと、以下の備考が書かれています。
『総結果件数の中の出現位置を指定する。(※4)
省略時のデフォルト値は発言単位、会議単位ともに「1」』

そして表の下に以下の説明があります。
『(※4)総結果件数が一回の最大取得件数を超える場合、開始位置を変えて繰り返し取得することで、一回の最大取得件数を超えるレコードを取得できます。』

==
これらを総合して考えると
・同じ100件のデータしか取得できないのは、開始位置(startRecord)の設定をしていないため。(開始位置が毎回デフォールト値の1となっているので、毎回1~100番目の結果が得られている)
・2回目の取得時はstartRecordを101にする、3回目の取得はstartRecordを201にする、というように開始位置を変えて繰り返し取得すれば、「一回の最大取得件数を超えるレコードを取得できます」という事になるのではないか。

と思われます。 試してみてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/20 07:13

    丁寧にご教示くださり、感謝です! 開始位置(startRecord)の意味合いを完全に勘違いしておりました。こちらを変更してみたら、問題なく動くようになりました。本当にありがとうございます!

    キャンセル

+1

ぱっと見でわかる問題点として「res_num」がファイルごとに分けられておりませんが、どのファイルも100件までしかないのでしょうか?

import requests
from bs4 import BeautifulSoup

#検索結果の総件数を取得する関数
#総件数は<numberofrecords>の要素として返ってくる
def all_api(year):
    with open('../thesis/sr'+ str(year) +'.txt', 'r', encoding="utf-8-sig") as fr:
        soup = BeautifulSoup(fr, 'lxml')
        nor = int(soup.find("numberofrecords").string)
    #fr.close ← with構文なのでいらない
    return(nor)

res = {} #resをファイルごとに分ける。
#検索結果をファイルに書き込む
for i in range(1990, 1992+1):
    url = 'http://kokkai.ndl.go.jp/api/1.0/speech?maximumRecords%3D100%26any%3D責任%26from%3D' + str(i) +'-01-01%26until%3D' + str(i) + '-12-31' 
    req = requests.get(url)
    with open('../thesis/sr'+ str(i) +'.txt', 'w', encoding="utf-8-sig") as fw:
        fw.write(req.text)
    res_num[i] = all_api(i)

count = 1 #検索結果の開始位置「startRecord」を指定するためのカウンタ

#検索結果が100件を超える場合、urlで取得した検索結果を該当ファイルに追記する
for i in range(1990, 1992+1):
    while res_num[i] > 0:
        with open('../thesis/sr'+ str(i) +'.txt', 'a', encoding="utf-8-sig") as fa:
       url = 'http://kokkai.ndl.go.jp/api/1.0/speech?startRecord%3D' + str(count) + '%26maximumRecords%3D100%26any%3D責任%26from%3D' + str(i) + '-01-01%26until%3D' + str(i) + '-12-31'
            req = requests.get(url)
            fa.write(req.text)
            res_num[i] = res_num[i] - 100
            count += 1


下の方の話の通り、もしこれでうまくいかないのであれば、
res_numとreq.textを途中でprintで出力して中身を確認してみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/20 07:16

    丁寧にご教示くださいまして、本当にありがとうございます! 「res_num」がファイルごとに分けられていない問題、恥ずかしながらご指摘を受けて初めて気づきました。この部分を関数にするのではなく、for文の中に記述することで結果が取得できるようになりました!

    キャンセル

-2

単に元サイトでの取得制限に引っかかってるだけでは。
その繰り返し処理中でどんな結果が得られてるのかみてみればどうでしょう、

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/20 07:19

    ご教示ありがとうございます。おっしゃるとおり取得制限の問題で、繰り返し処理が書ければ回避できることなのですが、そこがうまくいかずに悩んでおりました。基本をもっと頑張ります!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る