PythonでのHTTPリクエストは多くのアプリケーションで重要な役割を果たします。Webサービスのクライアント、APIの呼び出し、データ取得など、さまざまなシナリオで使用されます。しかし、HTTPリクエストが遅いとアプリケーション全体のパフォーマンスが低下し、ユーザーエクスペリエンスに悪影響を及ぼします。本記事では、Pythonを使用してHTTPリクエストのパフォーマンスと速度を改善するための具体的な手法を紹介します。非同期処理、接続の再利用、高速ライブラリの選定など、実践的なテクニックを駆使して効率化を図りましょう。
HTTPリクエストの基礎知識
HTTPリクエストは、Web上のリソースを取得するための通信プロトコルです。Pythonでは、標準ライブラリのrequests
モジュールを使用して簡単にHTTPリクエストを送信できます。ここでは、HTTPリクエストの基本的な概念とPythonでの実装方法について解説します。
HTTPリクエストの基本
HTTPリクエストは、クライアントとサーバー間の通信で行われ、主に以下のメソッドが使用されます:
GET
: リソースの取得POST
: データの送信PUT
: リソースの更新DELETE
: リソースの削除
PythonでのHTTPリクエストの実装
Pythonのrequests
モジュールを使用すると、以下のようにシンプルにHTTPリクエストを送信できます。
import requests
response = requests.get('https://api.example.com/data')
print(response.status_code)
print(response.json())
GETリクエストの例
response = requests.get('https://api.example.com/data')
if response.status_code == 200:
data = response.json()
print(data)
else:
print('Failed to retrieve data')
POSTリクエストの例
payload = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://api.example.com/data', json=payload)
print(response.status_code)
print(response.json())
これらの基本的な知識をもとに、次のセクションではHTTPリクエストのパフォーマンスを向上させる具体的な手法について説明します。
非同期処理を活用したパフォーマンス向上
非同期処理は、同時に複数のHTTPリクエストを並行して処理することで、全体のパフォーマンスを向上させる強力な手法です。Pythonでは、asyncio
やaiohttp
といったライブラリを使用して非同期処理を簡単に実装できます。
非同期処理の基本
非同期処理は、I/O操作(ネットワーク通信やファイル操作など)を待っている間に他のタスクを進めることで、効率的にリソースを利用します。これにより、待ち時間を最小限に抑えることができます。
asyncioとaiohttpの使用方法
Pythonの標準ライブラリであるasyncio
と、HTTPクライアントライブラリであるaiohttp
を使用して非同期HTTPリクエストを送信する方法を説明します。
非同期GETリクエストの例
以下のコードは、aiohttp
を使用して複数のGETリクエストを非同期に送信する例です。
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
urls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3',
]
tasks = [fetch(session, url) for url in urls]
responses = await asyncio.gather(*tasks)
for response in responses:
print(response)
# 非同期イベントループを実行
asyncio.run(main())
非同期POSTリクエストの例
以下のコードは、aiohttp
を使用して非同期にPOSTリクエストを送信する例です。
import aiohttp
import asyncio
async def post_data(session, url, data):
async with session.post(url, json=data) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
url = 'https://api.example.com/data'
payload = {'key1': 'value1', 'key2': 'value2'}
response = await post_data(session, url, payload)
print(response)
# 非同期イベントループを実行
asyncio.run(main())
これらの非同期処理を利用することで、HTTPリクエストのパフォーマンスを大幅に向上させることができます。次のセクションでは、接続の再利用による効率化について説明します。
接続の再利用による効率化
HTTPリクエストの効率を上げるための重要な手法の一つに、接続の再利用(キープアライブ)があります。これにより、新しいリクエストごとに接続を確立するオーバーヘッドを削減し、パフォーマンスを向上させることができます。
接続の再利用とは
接続の再利用(キープアライブ)は、一度確立したTCP接続を複数のリクエストで共有する技術です。これにより、リクエストごとに新しい接続を確立する必要がなくなり、ネットワークの負荷が軽減され、レスポンスタイムが短縮されます。
Pythonでの接続再利用の実装
Pythonのrequests
モジュールを使用して接続を再利用する方法について説明します。
Sessionオブジェクトの使用
requests.Session
オブジェクトを使用すると、接続の再利用が自動的に行われます。以下のコード例では、Sessionオブジェクトを使用して複数のリクエストを送信します。
import requests
session = requests.Session()
# 複数のGETリクエストを送信
response1 = session.get('https://api.example.com/data1')
response2 = session.get('https://api.example.com/data2')
response3 = session.get('https://api.example.com/data3')
print(response1.status_code)
print(response2.status_code)
print(response3.status_code)
# セッションを閉じる
session.close()
aiohttpでの接続再利用
aiohttp
を使用する場合も、セッションオブジェクトを再利用することで同様の効果が得られます。以下の例では、非同期リクエストで接続を再利用する方法を示します。
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
urls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3',
]
tasks = [fetch(session, url) for url in urls]
responses = await asyncio.gather(*tasks)
for response in responses:
print(response)
# 非同期イベントループを実行
asyncio.run(main())
接続の再利用を適切に設定することで、HTTPリクエストのパフォーマンスが向上し、アプリケーションの応答性が改善されます。次のセクションでは、高速なライブラリの選定について説明します。
高速なライブラリの選定
HTTPリクエストのパフォーマンスを向上させるためには、最適なライブラリを選定することが重要です。PythonにはさまざまなHTTPクライアントライブラリがありますが、それぞれに特徴があります。本セクションでは、高速なライブラリの選び方と使用例を紹介します。
主要なHTTPライブラリの比較
以下の主要なHTTPライブラリの特徴とパフォーマンスを比較します。
Requests
最も広く使用されているHTTPライブラリで、使いやすさと豊富な機能が特徴です。ただし、同期的に動作するため、非同期処理が必要な場合には適しません。
Aiohttp
非同期処理に対応したHTTPクライアントで、高いパフォーマンスを発揮します。非同期処理が必要なシナリオに最適です。
Httpx
同期および非同期の両方に対応した最新のライブラリで、Requestsに似た使いやすさを持ちながら、非同期処理も可能です。
各ライブラリの使用例
実際に各ライブラリを使用してHTTPリクエストを送信する例を示します。
Requestsの使用例
import requests
response = requests.get('https://api.example.com/data')
if response.status_code == 200:
data = response.json()
print(data)
else:
print('Failed to retrieve data')
Aiohttpの使用例
import aiohttp
import asyncio
async def fetch_data():
async with aiohttp.ClientSession() as session:
async with session.get('https://api.example.com/data') as response:
data = await response.json()
print(data)
asyncio.run(fetch_data())
Httpxの使用例
import httpx
import asyncio
async def fetch_data():
async with httpx.AsyncClient() as client:
response = await client.get('https://api.example.com/data')
print(response.json())
asyncio.run(fetch_data())
ライブラリ選定のポイント
ライブラリを選定する際のポイントは以下の通りです:
- パフォーマンス: 高速な応答が求められる場合は、非同期処理に対応したライブラリ(
aiohttp
やhttpx
)を選ぶ。 - 使いやすさ: シンプルなHTTPリクエストを迅速に実装したい場合は、
requests
やhttpx
が適している。 - 機能: 特殊な要件(例えば、接続プールの管理やカスタム認証など)がある場合、それらをサポートするライブラリを選ぶ。
適切なライブラリを選定することで、HTTPリクエストのパフォーマンスを最適化し、アプリケーション全体の効率を向上させることができます。次のセクションでは、リクエストのバッチ処理について説明します。
リクエストのバッチ処理
リクエストのバッチ処理は、複数のHTTPリクエストを一度にまとめて送信することで効率化を図る手法です。これにより、ネットワークのオーバーヘッドを減らし、全体のパフォーマンスを向上させることができます。
バッチ処理の基本
バッチ処理は、特定のタイミングで複数のリクエストを一括して処理することで、リソースの利用効率を最大化する方法です。これにより、個別にリクエストを送信する場合に比べて、総処理時間を短縮できます。
Pythonでのバッチ処理の実装
Pythonでリクエストのバッチ処理を実装する方法を、同期処理と非同期処理の両方で紹介します。
同期的なバッチ処理の例
requests
モジュールを使用して同期的にバッチ処理を行う例です。
import requests
urls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3',
]
responses = [requests.get(url) for url in urls]
for response in responses:
if response.status_code == 200:
print(response.json())
else:
print('Failed to retrieve data')
非同期的なバッチ処理の例
aiohttp
を使用して非同期にバッチ処理を行う例です。
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.json()
async def main():
async with aiohttp.ClientSession() as session:
urls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3',
]
tasks = [fetch(session, url) for url in urls]
responses = await asyncio.gather(*tasks)
for response in responses:
print(response)
asyncio.run(main())
バッチ処理のメリット
- パフォーマンス向上: 一度に複数のリクエストを処理することで、全体の処理時間を短縮できます。
- リソースの効率利用: ネットワークやサーバーの負荷を分散し、効率的に利用できます。
- シンプルなエラーハンドリング: まとめて処理するため、一括でエラーハンドリングを実装しやすくなります。
バッチ処理を適用することで、HTTPリクエストのパフォーマンスが向上し、システム全体の効率が高まります。次のセクションでは、レスポンス時間の計測と最適化について説明します。
レスポンス時間の計測と最適化
HTTPリクエストのパフォーマンスを改善するためには、レスポンス時間の計測とその最適化が不可欠です。レスポンス時間を正確に計測し、ボトルネックを特定することで、効率的な最適化が可能となります。
レスポンス時間の計測
レスポンス時間の計測には、Pythonの標準ライブラリや外部ツールを使用します。以下に、requests
モジュールを使用した基本的な計測方法を紹介します。
requestsモジュールによる計測
以下のコード例では、requests
モジュールを使用してHTTPリクエストのレスポンス時間を計測します。
import requests
import time
url = 'https://api.example.com/data'
start_time = time.time()
response = requests.get(url)
end_time = time.time()
response_time = end_time - start_time
print(f'Response time: {response_time} seconds')
aiohttpによる計測
非同期処理を用いた計測方法も示します。
import aiohttp
import asyncio
import time
async def fetch(session, url):
start_time = time.time()
async with session.get(url) as response:
end_time = time.time()
response_time = end_time - start_time
print(f'Response time: {response_time} seconds')
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
url = 'https://api.example.com/data'
await fetch(session, url)
asyncio.run(main())
レスポンス時間の最適化手法
計測したレスポンス時間を基に、以下の方法で最適化を行います。
キャッシュの利用
同じリクエストを繰り返す場合、キャッシュを利用することでレスポンス時間を短縮できます。
データ圧縮
リクエストやレスポンスのデータを圧縮することで、転送時間を短縮します。サーバーがgzip
やbrotli
などの圧縮をサポートしている場合は、それを活用します。
response = requests.get(url, headers={'Accept-Encoding': 'gzip'})
接続プールの使用
接続プールを使用することで、複数のリクエスト間で接続を再利用し、接続確立時間を削減します。
session = requests.Session()
adapter = requests.adapters.HTTPAdapter(pool_connections=10, pool_maxsize=10)
session.mount('http://', adapter)
session.mount('https://', adapter)
response = session.get(url)
サーバーサイドの最適化
サーバー側の設定を見直し、リクエスト処理の効率化を図ります。キャッシュポリシーやデータベースクエリの最適化などが含まれます。
レスポンス時間の計測と最適化を行うことで、HTTPリクエストのパフォーマンスが向上し、ユーザーエクスペリエンスが改善されます。次のセクションでは、エラーハンドリングとリトライ戦略について説明します。
エラーハンドリングとリトライ戦略
HTTPリクエストの処理中には、ネットワークの問題やサーバーの不具合などによりエラーが発生することがあります。これらのエラーに対処するためには、適切なエラーハンドリングとリトライ戦略が必要です。
エラーハンドリングの基本
エラーハンドリングは、エラーが発生した際に適切な対処を行うための手法です。Pythonでは、try-except
ブロックを使用してエラーをキャッチし、処理を続行することができます。
基本的なエラーハンドリングの例
以下のコード例では、requests
モジュールを使用してHTTPリクエストを送信し、エラーが発生した場合に対処する方法を示します。
import requests
url = 'https://api.example.com/data'
try:
response = requests.get(url)
response.raise_for_status() # HTTPステータスコードが200番台でない場合に例外を発生させる
data = response.json()
print(data)
except requests.exceptions.HTTPError as http_err:
print(f'HTTP error occurred: {http_err}')
except requests.exceptions.ConnectionError as conn_err:
print(f'Connection error occurred: {conn_err}')
except requests.exceptions.Timeout as timeout_err:
print(f'Timeout error occurred: {timeout_err}')
except requests.exceptions.RequestException as req_err:
print(f'An error occurred: {req_err}')
リトライ戦略
一時的なネットワークの問題やサーバーの過負荷など、リクエストが失敗する理由はいくつかあります。リトライ戦略を実装することで、こうした一時的なエラーに対処し、リクエストの成功率を高めることができます。
基本的なリトライの例
以下のコード例では、エラーが発生した際にリトライを行う方法を示します。
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
url = 'https://api.example.com/data'
session = requests.Session()
retry = Retry(
total=5, # リトライ回数
backoff_factor=0.3, # リトライ間隔の指数バックオフ係数
status_forcelist=[500, 502, 503, 504] # リトライ対象のHTTPステータスコード
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
try:
response = session.get(url)
response.raise_for_status()
data = response.json()
print(data)
except requests.exceptions.RequestException as req_err:
print(f'An error occurred: {req_err}')
非同期処理でのエラーハンドリングとリトライ
非同期処理を使用する場合も、エラーハンドリングとリトライ戦略を適用することが重要です。以下にaiohttp
を使用した例を示します。
import aiohttp
import asyncio
async def fetch(session, url):
for _ in range(5): # 最大5回のリトライ
try:
async with session.get(url) as response:
response.raise_for_status()
return await response.text()
except aiohttp.ClientError as e:
print(f'Error: {e}')
await asyncio.sleep(1) # リトライ前に1秒待機
async def main():
async with aiohttp.ClientSession() as session:
url = 'https://api.example.com/data'
result = await fetch(session, url)
print(result)
asyncio.run(main())
エラーハンドリングとリトライ戦略を適切に実装することで、HTTPリクエストの信頼性が向上し、アプリケーションの堅牢性が強化されます。次のセクションでは、キャッシュの活用について説明します。
キャッシュの活用
キャッシュを活用することで、HTTPリクエストのパフォーマンスを大幅に向上させることができます。キャッシュは、頻繁にアクセスされるデータを一時的に保存し、同じリクエストに対して再度サーバーに問い合わせることなく、迅速に応答を返す仕組みです。
キャッシュの基本
キャッシュは、クライアント側、サーバー側、またはCDN(コンテンツデリバリーネットワーク)で行われます。ここでは、クライアント側でのキャッシュの使用方法に焦点を当てます。
Pythonでのキャッシュ実装
Pythonでは、requests-cache
というライブラリを使用して、HTTPリクエストをキャッシュすることができます。このライブラリを使用すると、簡単にキャッシュを実装できます。
requests-cacheのインストール
まず、requests-cache
ライブラリをインストールします。
pip install requests-cache
キャッシュの使用例
以下のコード例では、requests-cache
を使用してHTTPリクエストをキャッシュする方法を示します。
import requests
import requests_cache
# キャッシュの有効期限を設定(例:1時間)
requests_cache.install_cache('http_cache', expire_after=3600)
url = 'https://api.example.com/data'
# キャッシュを利用してリクエストを送信
response = requests.get(url)
data = response.json()
print(data)
この例では、初回のリクエスト時にデータがキャッシュされ、次回以降のリクエストではキャッシュからデータが取得されます。キャッシュの有効期限が過ぎると、新しいリクエストがサーバーに送信され、キャッシュが更新されます。
キャッシュのメリット
- パフォーマンス向上: キャッシュを使用することで、サーバーへのリクエスト数が減り、レスポンス時間が短縮されます。
- 帯域幅の節約: 同じデータを再度ダウンロードする必要がなくなるため、ネットワーク帯域幅が節約されます。
- サーバー負荷の軽減: サーバーへのリクエスト数が減ることで、サーバーの負荷が軽減されます。
キャッシュの管理
キャッシュを適切に管理することも重要です。以下の方法でキャッシュを管理できます:
- 有効期限の設定: キャッシュの有効期限を設定し、古いデータが使用されないようにする。
- 手動でのキャッシュクリア: 必要に応じてキャッシュを手動でクリアする。
requests_cache.clear()
キャッシュを効果的に活用することで、HTTPリクエストのパフォーマンスが向上し、アプリケーション全体の効率が高まります。次のセクションでは、HTTPリクエストのセキュリティ考慮について説明します。
セキュリティ考慮
HTTPリクエストを送信する際には、セキュリティを確保することが重要です。不正なアクセスやデータ漏洩を防ぐために、以下のベストプラクティスを実践します。
HTTPSを使用する
通信の暗号化を行うために、必ずHTTPSを使用します。これにより、送信されるデータが第三者に傍受されるリスクを減らせます。
url = 'https://secure-api.example.com/data'
response = requests.get(url)
認証と認可
APIにアクセスする際には、適切な認証と認可を設定します。以下に代表的な認証方法を示します。
Basic認証
簡単な認証方法ですが、ベーシック認証は暗号化されていないため、HTTPSと併用する必要があります。
from requests.auth import HTTPBasicAuth
response = requests.get('https://secure-api.example.com/data', auth=HTTPBasicAuth('user', 'pass'))
トークン認証
よりセキュアな方法として、トークン認証があります。APIキーやJWT(JSON Web Token)を使用します。
headers = {'Authorization': 'Bearer YOUR_ACCESS_TOKEN'}
response = requests.get('https://secure-api.example.com/data', headers=headers)
パラメータのエスケープ
URLに含まれるクエリパラメータは適切にエスケープし、インジェクション攻撃を防ぎます。
from urllib.parse import urlencode
params = {'search': 'example query', 'page': 1}
url = f"https://secure-api.example.com/search?{urlencode(params)}"
response = requests.get(url)
セッション管理
セッションを適切に管理し、不要になったセッションは速やかに閉じます。これにより、セッションハイジャックのリスクを軽減します。
session = requests.Session()
response = session.get('https://secure-api.example.com/data')
# セッションを閉じる
session.close()
タイムアウトの設定
タイムアウトを設定することで、応答の遅いリクエストに対して無限に待機するのを防ぎます。
response = requests.get('https://secure-api.example.com/data', timeout=10)
エラーハンドリング
エラーハンドリングを適切に実装し、セキュリティリスクが発生した際には迅速に対処できるようにします。
try:
response = requests.get('https://secure-api.example.com/data')
response.raise_for_status()
except requests.exceptions.HTTPError as http_err:
print(f'HTTP error occurred: {http_err}')
except requests.exceptions.ConnectionError as conn_err:
print(f'Connection error occurred: {conn_err}')
except requests.exceptions.Timeout as timeout_err:
print(f'Timeout error occurred: {timeout_err}')
except requests.exceptions.RequestException as req_err:
print(f'An error occurred: {req_err}')
これらのセキュリティ対策を講じることで、HTTPリクエストの安全性を高め、アプリケーションをより堅牢にすることができます。次のセクションでは、応用例と実践的な演習について説明します。
応用例と実践的な演習
HTTPリクエストのパフォーマンスとセキュリティを向上させるための実践的な手法を学んだら、それを実際のプロジェクトに応用してみましょう。このセクションでは、応用例と演習問題を通じて理解を深めます。
応用例
ここでは、実際のプロジェクトでのHTTPリクエストの応用例を紹介します。
APIクライアントの作成
複数のAPIエンドポイントにアクセスするためのカスタムAPIクライアントを作成します。キャッシュや非同期処理、エラーハンドリングを実装して、効率的なデータ取得を行います。
import aiohttp
import asyncio
import requests_cache
class CustomAPIClient:
def __init__(self, base_url, cache_expiry=3600):
self.base_url = base_url
requests_cache.install_cache('api_cache', expire_after=cache_expiry)
async def fetch(self, endpoint):
async with aiohttp.ClientSession() as session:
url = f"{self.base_url}/{endpoint}"
async with session.get(url) as response:
response.raise_for_status()
return await response.json()
def get(self, endpoint):
url = f"{self.base_url}/{endpoint}"
response = requests.get(url)
response.raise_for_status()
return response.json()
async def main():
client = CustomAPIClient('https://api.example.com')
data = await client.fetch('data')
print(data)
asyncio.run(main())
データ取得とキャッシュの活用
外部APIからデータを取得し、ローカルにキャッシュして、効率的にデータを再利用するシステムを構築します。
import requests_cache
import requests
class DataFetcher:
def __init__(self, base_url, cache_expiry=3600):
self.base_url = base_url
requests_cache.install_cache('data_cache', expire_after=cache_expiry)
def fetch_data(self, endpoint):
url = f"{self.base_url}/{endpoint}"
response = requests.get(url)
response.raise_for_status()
return response.json()
fetcher = DataFetcher('https://api.example.com')
data = fetcher.fetch_data('data')
print(data)
実践的な演習
これまでに学んだ手法を応用するための演習問題を提供します。
演習1: 非同期APIクライアントの作成
aiohttp
を使用して、非同期APIクライアントを作成し、複数のエンドポイントに並行してリクエストを送信するプログラムを実装してください。
演習2: リトライ戦略の実装
HTTPリクエストが失敗した場合に、一定回数リトライを行う戦略を実装してください。リトライの間隔を指数バックオフで設定することを試みてください。
演習3: セキュアなAPIアクセス
APIキーを使用して認証を行うAPIクライアントを作成し、HTTPSを使用して安全な通信を行うプログラムを実装してください。
演習4: キャッシュの効果測定
キャッシュを使用したHTTPリクエストと、キャッシュを使用しないHTTPリクエストのパフォーマンスを比較し、キャッシュの効果を測定するプログラムを作成してください。
これらの演習を通じて、HTTPリクエストのパフォーマンスとセキュリティの向上手法を実践的に習得することができます。次のセクションでは、記事のまとめを行います。
まとめ
本記事では、Pythonを使用してHTTPリクエストのパフォーマンスと速度を改善するための実践的な手法を紹介しました。各セクションで取り上げた主要なポイントを以下にまとめます。
HTTPリクエストの基礎知識
HTTPリクエストの基本的な概念と、Pythonでの実装方法について説明しました。
非同期処理を活用したパフォーマンス向上
asyncio
とaiohttp
を使用して、非同期に複数のHTTPリクエストを処理する方法を解説しました。
接続の再利用による効率化
セッションを再利用することで、HTTPリクエストのパフォーマンスを向上させる方法を示しました。
高速なライブラリの選定
requests
、aiohttp
、httpx
などのライブラリを比較し、適切なライブラリを選定するポイントを紹介しました。
リクエストのバッチ処理
複数のHTTPリクエストを一括で処理するバッチ処理の手法について説明しました。
レスポンス時間の計測と最適化
HTTPリクエストのレスポンス時間を計測し、最適化するための具体的な方法を紹介しました。
エラーハンドリングとリトライ戦略
HTTPリクエストにおけるエラーハンドリングとリトライ戦略の実装方法を説明しました。
キャッシュの活用
キャッシュを利用してHTTPリクエストのパフォーマンスを向上させる手法を示しました。
セキュリティ考慮
HTTPリクエストのセキュリティを向上させるためのベストプラクティスについて説明しました。
応用例と実践的な演習
実際のプロジェクトでHTTPリクエストを効率化するための応用例と演習問題を提供しました。
これらの手法を実践することで、Pythonを使用したHTTPリクエストのパフォーマンスと速度を大幅に改善し、効率的でセキュアなアプリケーションを構築することができます。継続的に学び、最適化を進めることで、より高品質なソフトウェアを開発できるようになるでしょう。
コメント