Python3でPycURLを用いてteratail APIのJSONからPythonタグつきの質問を取得
teratailというプログラミングQ&AサイトのAPIからJSON形式で質問取得を試みた際のメモです。Pythonで試みたのでPythonに関連する質問の取得を試みています。環境は Windows 7, Python 3.5.1 です。
必要なPythonモジュールを用意
PycURL
- PythonでcURLライブラリを使うモジュールを利用しています。
今回はHTTP(S)リクエストする際に用います。
PHPを使ったことがあれば、PHPのcurl関数のような感じで利用できるイメージです。 - この際にインストールしたバージョンは pycurl (7.43.0) です。
Windows
python -m pip install pycurl
LinuxやmacOS
pip install pycurl
コード
BEARER = ''
でteratailに登録後取得できるアクセストークンを設定します。- 無くても動作しますがteratailの仕様で1時間あたり30回までのアクセスになるそうです。アクセストークンがあれば1時間あたり300回までアクセス可能になるそうです。
# -*- encoding: utf-8 -*- import io, json, pycurl, sys, urllib.parse if __name__ != '__main__': sys.exit() # teratail登録後、 https://teratail.com/users/setting/tokens で取得 BEARER = '' class Teratail: API_URL = 'https://teratail.com/api/v1/tags/{}/questions?limit={}&page={}' __curl = None __tag = '' __limit = 20 __page = 1 __bearer = None __httpCode = 200 def __init__(self, tag='', limit=20, page=1): self.__tag = tag self.__limit = limit self.__page = page # インスタンス生成 self.__curl = pycurl.Curl() def __execute(self): json = None buf = io.BytesIO() headers = {} if self.__bearer: headers['Authorization'] = 'Bearer {}'.format(self.__bearer) self.__curl.reset() try: # Headerをセット headers = ['{}: {}'.format(*v) for v in headers.items()] self.__curl.setopt(pycurl.HTTPHEADER, headers) # リクエスト先をセット self.__curl.setopt(pycurl.URL, self.API_URL.format(self.__tag, self.__limit, self.__page)) # MethodをGETにセット(デフォルト) #self.__curl.setopt(pycurl.CUSTOMREQUEST, 'GET') # SSL証明書の有効性を確認しない self.__curl.setopt(pycurl.SSL_VERIFYPEER, False) # pycurlの結果を変数に格納 self.__curl.setopt(pycurl.WRITEDATA, buf) # 出力 self.__curl.perform() # 取得したjsonデータをUTF-8にデコード json = buf.getvalue().decode('UTF-8') except (pycurl.error, TypeError): pass self.__httpCode = self.__curl.getinfo(pycurl.HTTP_CODE) buf.close() return json def setBearer(self, bearer): self.__bearer = bearer def getHttpCode(self): return self.__httpCode # http://docs.teratailv1.apiary.io/#introduction def getJson(self, tag=None, limit=None, page=None): if tag is not None: self.__tag = tag if limit is not None: self.__limit = limit if page is not None: self.__page = page return self.__execute() tt = Teratail(limit=5) tt.setBearer(BEARER) # http://docs.teratailv1.apiary.io/#reference/(tag)/2/0 for tag in ('Python', 'Python 2.7', 'Python 3.x'): print(tag) jsonData = tt.getJson(tag=urllib.parse.quote_plus(tag)) if jsonData is None: continue data = json.loads(jsonData) if 'questions' not in data: if 'meta' in data and 'message' in data['meta']: print('HTTP Status Code: {}'.format(tt.getHttpCode())) print('Message: {message}'.format(**data['meta'])) continue print('Data:') for row in data['questions']: if 'id' not in row: continue # 質問ページ print('https://teratail.com/questions/{id}'.format(**row)) # 質問のタイトル print(row['title'] if 'title' in row else None) # 質問を投稿したユーザの名前 if 'user' in row and 'display_name' in row['user']: print(row['user']['display_name']) print() print()