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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

2回答

1835閲覧

BeautifulSoupで「not readable」というエラーが出ます

fujiko20

総合スコア19

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2019/04/07 07:47

編集2019/04/18 23:30

前提・実現したいこと

プログラミング初心者です。国会会議録検索システムのAPIを利用し、年ごとに特定のキーワードで検索結果を取得し、ファイルに書き込みたいと考えています。しかし、同APIには「一度に取得できる発言(speech)の上限は100件」という制限があります。

100件までの発言をファイルに書き込むことには成功したのですが、その上限を超えて取得するには「nextRecordPosition」というパラメータで次開始位置を利用する必要があるようです。この部分を付け加えたところ、エラーが出てしまいました。

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

次のようなエラーが出ています。

UnsupportedOperation Traceback (most recent call last) <ipython-input-13-4bc2addc6e26> in <module>() 9 f = open('./thesis/sr'+ str(i) +'.txt', 'w', encoding="utf-8") 10 f.write(req.text) ---> 11 soup = BeautifulSoup(f, 'lxml') 12 if soup.find('nextRecordPosition') == True: 13 url = 'http://kokkai.ndl.go.jp/api/1.0/speech?nextRecordPosition%26101 ?maximumRecords\%3D100\%26any%3D自己責任%26from%3D' + str(i) +'-01-01%26 until%3D' + str(i) + '-12-31' ~\Anaconda3\lib\site-packages\bs4\__init__.py in __init__(self, markup, features, builder, parse_only, from_encoding, exclude_encodings, **kwargs) 243 244 if hasattr(markup, 'read'): # It's a file-type object. --> 245 markup = markup.read() 246 elif len(markup) <= 256 and ( 247 (isinstance(markup, bytes) and not b'<' in markup) UnsupportedOperation: not readable

該当のソースコード

(1)100件までの発言(speech)の検索結果を取得し、ファイルに書き込む
(2)100件までの発言を超えている(nextRecordPositionというタグがある)場合、該当ファイルに追記する

という2段構えでやろうとして失敗しています。

python3

1#「自己責任」というキーワードを含む発言を年ごとに取得し、 2#ファイルに保存するプログラム(対象期間は1945年から2019年) 3 4import requests 5from bs4 import BeautifulSoup 6 7#(1)100件までの発言(speech)の検索結果を取得し、ファイルに書き込む 8for i in range(1945, 2019+1): 9 url = 'http://kokkai.ndl.go.jp/api/1.0/speech?maximumRecords\%3D100\ 10 %26any%3D自己責任%26from%3D' + str(i) +'-01-01%26until%3D' + str(i) + '-12-31' 11 req = requests.get(url) 12 f = open('./thesis/sr'+ str(i) +'.txt', 'w', encoding="utf-8") 13 f.write(req.text) 14 soup = BeautifulSoup(f, 'lxml') 15 temp = soup.find('nextRecordPosition') 16#(2)100件までの発言を超えている(nextRecordPositionというタグがある)場合、該当ファイルに追記する 17 if temp == True: 18 url = 'http://kokkai.ndl.go.jp/api/1.0/speech?nextRecordPosition%26101\ 19 ?maximumRecords\%3D100\%26any%3D自己責任%26from%3D' + str(i) +'-01-01%26\ 20 until%3D' + str(i) + '-12-31' 21 req = requests.get(url) 22 f = open('./thesis/sr'+ str(i) +'.txt', 'a', encoding="utf-8") 23 f.write(req.text) 24 else: 25 break

試したこと

BeautifulSoupのところでエラーが出ているため、パーサをほかのもの(html.parser)に変えてみましたが、同様のエラーが出ました。

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

自分で気になっているのは、上記コードの次の部分です。

temp = soup.find('nextRecordPosition') if temp == True:

APIの仕様によると、発言件数が100件内に収まっている場合、「nextRecordPosition」というタグは表示されません。そこで「nextRecordPositionが見つかった場合、実行する」というif文を書きたいのですが、どう書くべきか迷ってこのようになりました。しかし、違うのでは、と……。

なお、国会会議録検索システムのAPIの仕様は以下にまとまっています。
http://kokkai.ndl.go.jp/api.html

自力ではここまでが精一杯でした。みなさまのお知恵を拝借できれば幸いです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

BeautifulSoup コンストラクタの第 1 引数は、対象のファイルではなく文字列を渡す必要があります。

python

1soup = BeautifulSoup(req.text, 'lxml')

投稿2019/04/07 10:05

nskydiving

総合スコア6500

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fujiko20

2019/04/07 22:31 編集

nskydivingさま、ご指摘感謝です! 今後は気をつけていきます。教えていただいたとおりの記述にしてみたところ、次のようなエラーメッセージが出てしまいました。 AttributeError: '_io.TextIOWrapper' object has no attribute 'text' もし原因を教えていただけるようでしたら、たいへんうれしいです。
fujiko20

2019/04/07 22:52 編集

おかげさまでこの件は解決できました。ありがとうございます! しかし、やはり100件を超えているかどうかを判断する条件の設定がおかしいようで、100件以上はデータが取得できていない状況です。現段階では、上のとおりのコードとなっています。もしまたお力をお借りできるようでしたら、非常に助かります。
nskydiving

2019/04/08 00:47

「総結果件数」「返戻件数」「次開始位置」が取得できるようなので、これらを使ってページごとにデータを取得できそうです。 また、1つの投稿で複数の質問は推奨されませんので、他の質問がある場合は、一旦この質問を「解決済み」にした後、新たに質問を投稿してください。
fujiko20

2019/04/09 01:14

質問に対してご教示くださり、ありがとうございます。そして、teratailの推奨ルールを破った点についても、ご指摘感謝いたします。使い方に慣れておらず、「一つの項目にまとめたほうがよい」と無意識のうちに思い込んでいました。今後は改めてまいります。
guest

0

自己解決

上記エラー(AttributeError: '_io.TextIOWrapper' object has no attribute 'text')については解決しました。ファイルを開くべきところでそうせず、処理を進めていたことが原因でした。(2)の部分の処理を変えています。ただし、やはり100件を超える発言は取得できない状況です。条件に関する記述に問題があるものと睨んでいます。

Python3

1#「自己責任」というキーワードを含む発言を年ごとに取得し、ファイルに保存するプログラム(対象期間は1945年から2019年) 2#デフォルトでとれる発言単位が100までなので、それを超えた場合の処理を書く 3 4import requests 5from bs4 import BeautifulSoup 6 7#(1)100件までの発言(speech)の検索結果を取得し、ファイルに書き込む 8for i in range(1945, 2019+1): 9 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' 10 req = requests.get(url) 11 f = open('./thesis/sr'+ str(i) +'.txt', 'w', encoding="utf-8") 12 f.write(req.text) 13 14#(2)100件までの発言を超えている(nextRecordPositionというタグがある)場合、該当ファイルに追記する 15for i in range(1945, 2019+1): 16 with open('./thesis/sr'+ str(i) +'.txt', 'r', encoding="utf-8-sig") as fr: 17 soup = BeautifulSoup(fr.text, 'lxml') 18 temp = soup.find('nextRecordPosition') 19 if temp == True: 20 url = 'http://kokkai.ndl.go.jp/api/1.0/speech?nextRecordPosition%26101?maximumRecords\%3D100\%26any%3D自己責任%26from%3D' + str(i) +'-01-01%26\ 21 until%3D' + str(i) + '-12-31' 22 req = requests.get(url) 23 f = open('./thesis/sr'+ str(i) +'.txt', 'a', encoding="utf-8") 24 f.write(req.text) 25 else: 26 break

投稿2019/04/07 22:40

編集2019/04/07 22:57
fujiko20

総合スコア19

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問