14章学習記録 » 履歴 » バージョン 1
Tatsuya ISHIGAKI, 2025/08/06 13:57
| 1 | 1 | Tatsuya ISHIGAKI | # 第14章 インターネット上のデータを扱う |
|---|---|---|---|
| 2 | |||
| 3 | ## 14.1 URL をパースする urllib.parse |
||
| 4 | |||
| 5 | ### URL をパースする urllib.urlparse() |
||
| 6 | URL を構成要素 (アドレススキーム、ネットワークロケーション、パス、クエリ 等) に分解できる |
||
| 7 | |||
| 8 | - `urlparse(urlstring, scheme='', allow_fragments=True)` |
||
| 9 | - `urlstring` パース対象 URL |
||
| 10 | - `scheme` URL スキームを指定 (URL 内にスキーム指定が無い場合のみ有効) |
||
| 11 | - `allow_fragments` True の場合、フラグメント識別子をパースする |
||
| 12 | - **戻り値** `urllib.parse.ParseResult` インスタンス |
||
| 13 | - `ParseResult` は 6 要素の named_tuple で、他にも属性持つ |
||
| 14 | |||
| 15 | |属性|インデックス|値|該当箇所無しの場合の値| |
||
| 16 | |---|---|---|---| |
||
| 17 | |`scheme`|0|URL スキーム|scheme パラメータ| |
||
| 18 | |`netloc`|1|ネットワーク上の位置|空文字列| |
||
| 19 | |`path`|2|パス階層|空文字列| |
||
| 20 | |`params`|3|URL 引数 (`;` 以降の文字列)|空文字列| |
||
| 21 | |`query`|4|クエリ文字列 (`?` 以降の文字列)|空文字列| |
||
| 22 | |`fragment`|5|フラグメント識別子 (`#` 以降の文字列)|空文字列| |
||
| 23 | |`username`||ユーザー名|None| |
||
| 24 | |`password`||パスワード|None| |
||
| 25 | |`hostname`||ホスト名|None| |
||
| 26 | |`port`||ポート番号|None| |
||
| 27 | |||
| 28 | |||
| 29 | ```python |
||
| 30 | >>> from urllib.parse import urlparse |
||
| 31 | >>> o = urlparse("http://docs.python.org:80/3/library/urllib.parse.html?" |
||
| 32 | ... "highlight=params#url-parsing") |
||
| 33 | >>> o |
||
| 34 | ParseResult(scheme='http', netloc='docs.python.org:80', path='/3/library/urllib.parse.html', params='', query='highlight=params', fragment='url-parsing') |
||
| 35 | >>> o.scheme |
||
| 36 | 'http' |
||
| 37 | >>> o.port |
||
| 38 | 80 |
||
| 39 | >>> o[2] # path |
||
| 40 | '/3/library/urllib.parse.html' |
||
| 41 | ``` |
||
| 42 | |||
| 43 | ### クエリ文字列をパースする parse_qs() |
||
| 44 | - クエリ文字列をパースして辞書を返す |
||
| 45 | - `parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&')` |
||
| 46 | - `qs` クエリ文字列 |
||
| 47 | - `keep_blank_values` False の場合、ブランク文字列を無視する |
||
| 48 | - `strict_parsing` False の場合、パース処理中のエラーを無視する |
||
| 49 | - `encoding` エンコードする際の文字コードを指定 |
||
| 50 | - `errors` エンコードする際の動作を指定 |
||
| 51 | - `max_num_fields` 読み取るフィールドの最大数を指定 (最大数を超えると ValueError) |
||
| 52 | - `separator` 分離に使用する文字列を指定 |
||
| 53 | - **戻り値** dict |
||
| 54 | - 形式は {_key1_: [_val1-1_,_val2_,...], _key2_: [_val2-1_, _val2-2_, ...], ...} |
||
| 55 | - キーに対して、(値が1つの場合でも) 値のリスト |
||
| 56 | - 同様の関数に `parse_qsl()` があり、こちらはペア (2要素タプル) のリストを返す |
||
| 57 | - 同一キーに複数の値が設定されている場合の戻り値に注意 |
||
| 58 | - `parse_qs` では辞書の単一キーにリストで複数の値 |
||
| 59 | - `parse_qsl` では1つ目の要素が同じ複数タプルがリストに含まれる |
||
| 60 | |||
| 61 | ```python |
||
| 62 | >>> from urllib import parse |
||
| 63 | >>> result = parse.urlparse('https://www.google.co.jp/search?q=python&oq=python&sourceid=chrome&ie=UTF-8') |
||
| 64 | >>> result.query |
||
| 65 | 'q=python&oq=python&sourceid=chrome&ie=UTF-8' |
||
| 66 | >>> parse.parse_qs(result.query) # パース結果を辞書として受け取りたい場合 |
||
| 67 | {'q': ['python'], 'oq': ['python'], 'sourceid': ['chrome'], 'ie': ['UTF-8']} |
||
| 68 | >>> parse.parse_qs('key=1&key=2') # 1つのキーに対して値が複数ある場合の例 |
||
| 69 | {'key': ['1', '2']} |
||
| 70 | >>> parse.parse_qsl(result.query) # パース結果をタプルのリストとして受け取りたい場合 |
||
| 71 | [('q', 'python'), ('oq', 'python'), ('sourceid', 'chrome'), ('ie', 'UTF-8')] |
||
| 72 | >>> parse.parse_qsl('key=1&key=2') # 値が複数ある場合、parse_qsとは異なり2つのタプルとなる |
||
| 73 | [('key', '1'), ('key', '2')] |
||
| 74 | ``` |
||
| 75 | |||
| 76 | ### クエリ文字列を組み立てる urlencode() |
||
| 77 | - `urlencode(query, doseq=False, safe='', encoding=None, errors=Noen, quote_via=quote_plus)` |
||
| 78 | - `query` クエリ文字列へ変換するデータ構造 (マッピングオブジェクト、または2要素タプルのシーケンス) |
||
| 79 | - `doseq` マッピングの値、タプルの第2要素がシーケンスの場合の動作を指定 |
||
| 80 | - True の場合、(同一キーの) 複数クエリへ分解される |
||
| 81 | - False の場合、シーケンス部分がそのまま文字列値扱い |
||
| 82 | - `safe` URL エンコードしない文字を指定 |
||
| 83 | - `encoding` エンコードする際の文字コードを指定 |
||
| 84 | - `errors` エンコードする際の動作を指定 |
||
| 85 | - `quote_via` エンコードに使用する関数を指定 `quate_plus` `quate` |
||
| 86 | - **戻り値** str |
||
| 87 | |||
| 88 | ```python |
||
| 89 | >>> from urllib import parse |
||
| 90 | >>> dic = {"name": "smith", "age": 41} |
||
| 91 | >>> tpl = [("name", "smith"), ("age", 41)] |
||
| 92 | >>> qs_dic = parse.urlencode(dic) |
||
| 93 | >>> qs_dic |
||
| 94 | 'name=smith&age=41' |
||
| 95 | >>> qs_tpl = parse.urlencode(tpl) |
||
| 96 | >>> qs_tpl |
||
| 97 | 'name=smith&age=41' |
||
| 98 | >>> tpl2 = [("name", "smith"), ("birthday", [9, 28])] # 値にシーケンスを指定 |
||
| 99 | >>> qs_tpl2 = parse.urlencode(tpl2) |
||
| 100 | >>> qs_tpl2 |
||
| 101 | 'name=smith&birthday=%5B9%2C+28%5D' # doseq=False (デフォルト) の場合の文字列 |
||
| 102 | >>> qs_tpl3 = parse.urlencode(tpl2, doseq=True) |
||
| 103 | >>> qs_tpl3 |
||
| 104 | 'name=smith&birthday=9&birthday=28' # doseq=True の場合の文字列 |
||
| 105 | >>> dic2 = {"name": "smith", "birthday": [9, 28]} # 値にシーケンスを指定 |
||
| 106 | >>> qs_dic2 = parse.urlencode(dic2) |
||
| 107 | >>> qs_dic2 |
||
| 108 | 'name=smith&birthday=%5B9%2C+28%5D' # doseq=False (タプルと同じ) |
||
| 109 | >>> qs_dic3 = parse.urlencode(dic2, doseq=True) |
||
| 110 | >>> qs_dic3 |
||
| 111 | 'name=smith&birthday=9&birthday=28' # doseq=True (タプルと同じ) |
||
| 112 | >>> parse.parse_qs(qs_dic3) |
||
| 113 | {'name': ['smith'], 'birthday': ['9', '28']} # doseq=True の場合のクエリをパースすると戻る |
||
| 114 | >>> parse.parse_qs(qs_dic2) |
||
| 115 | {'name': ['smith'], 'birthday': ['[9, 28]']} # doseq=False の場合、文字列 '[9, 28]' が値となっていた |
||
| 116 | ``` |
||
| 117 | |||
| 118 | ### URL として使用できる文字列に変換する quate(), quote_plus() |
||
| 119 | 文字列を URL として使用できるようにパーセントエンコードする |
||
| 120 | |||
| 121 | - `quote(string, safe='/', encoding=None, errors=None)` |
||
| 122 | - `string` エンコード対象文字列 |
||
| 123 | - `safe` パーセントエンコードしない文字を指定 |
||
| 124 | - `encoding` パーセントエンコードする際の文字エンコードを指定 |
||
| 125 | - `errors` パーセントエンコードする際の動作を指定 |
||
| 126 | - **戻り値** str または bytes |
||
| 127 | - 同様の関数に `quote_plus()` がある |
||
| 128 | |||
| 129 | ||スペース文字|`safe`| |
||
| 130 | |---|---|---| |
||
| 131 | |`quote()`|`%20` へ変換|`/`| |
||
| 132 | |`quote_plus()`|`+` へ変換|(空文字)| |
||
| 133 | |||
| 134 | ### URL を結合する urljoin() |
||
| 135 | - `urljoin(base, url, allow_fragments=True)` |
||
| 136 | - `base` ベースとなる URL |
||
| 137 | - `url` 結合に使用する URL やパス |
||
| 138 | - `allow_fragments` True の場合、フラグメント識別子をパースする |
||
| 139 | - **戻り値** str |
||
| 140 | - `url` には相対パスも指定可能 (`../../menu` など) |
||
| 141 | - `base` `url` 両方に URL を指定した場合、`url` が返る |
||
| 142 | |||
| 143 | ## 14.2 URL を開く urllib.request |
||
| 144 | URL を開くためのインターフェースを提供する標準ライブラリ (ただし、より高水準な「Requests」パッケージが公式でも推奨されている) |
||
| 145 | |||
| 146 | ### 指定の URL を開く urllib.request.urlopen |
||
| 147 | - 関数 `urlopen(url, data=None[, timeout], *, cafile=None, capath=None, cadefault=False, context=None)` |
||
| 148 | - `url` URL を文字列または `Request` オブジェクトで指定 |
||
| 149 | - `data` URL に POST するデータを bytes あるいは file オブジェクトで指定 (GET の場合は None である必要がある) |
||
| 150 | - `timeout` タイムアウト時間を秒で指定 |
||
| 151 | - `context` `ssl.SSLContext` クラスのインスタンスを指定 |
||
| 152 | - **戻り値** HTTP(S) の場合は `http.client.Response`、他は基本 `rullib.response.addinfourl` |
||
| 153 | - cafile, capath, cadefault は 3.6 以降で非推奨となり、context が推奨 |
||
| 154 | - `urlopen` には HTTP メソッド指定は無く、URL 指定のみなら **GET** に (クエリ文字列で情報は与えられる)、data を指定すれば **POST** 扱いとなる |
||
| 155 | - その他のメソッドは url に `urllib.request.Request` インスタンス (メソッドを指定しておく) を渡す |
||
| 156 | |||
| 157 | ```python |
||
| 158 | # GET リクエスト |
||
| 159 | >>> from urllib import request |
||
| 160 | >>> with request.urlopen('https://httpbin.org/get') as f: |
||
| 161 | ... res = f.read()[:92] |
||
| 162 | >>> res |
||
| 163 | b'{\n "args": {}, \n "headers": {\n "Accept-Encoding": "identity", \n "Host": "httpbin.org' |
||
| 164 | ``` |
||
| 165 | |||
| 166 | ```python |
||
| 167 | # クエリ付き GET リクエスト |
||
| 168 | >>> res = request.urlopen('hppts://httpbin.org/get?key1=value1') |
||
| 169 | ``` |
||
| 170 | |||
| 171 | ```python |
||
| 172 | # POST リクエスト (data を指定) |
||
| 173 | >>> data = 'key1=value1&key2=value2' |
||
| 174 | >>> res = request.urlopen('https://httpbin.org/post', data=data.encode()) |
||
| 175 | >>> res.status |
||
| 176 | 200 |
||
| 177 | ``` |
||
| 178 | |||
| 179 | ### GET, POST 以外の HTTP メソッドを扱う urllib.request.Request |
||
| 180 | - class `Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)` |
||
| 181 | - `url` URL を指定 |
||
| 182 | - `data` URL に送信するデータを bytes または file-like オブジェクトで指定 |
||
| 183 | - `headers` HTTP ヘッダーを辞書で指定 |
||
| 184 | - `method` HTTP メソッドを指定 |
||
| 185 | - Request インスタンスを urlopen の url へ指定することで、任意の HTTP メソッドを使用して URL へリクエストできる |
||
| 186 | |||
| 187 | ```python |
||
| 188 | # DELETE メソッド |
||
| 189 | >>> from urllib import request |
||
| 190 | >>> data = 'key1=value1&key2=value2' |
||
| 191 | >>> req = request.Request('https://httpbin.org/delete', data=data.encode(), method='DELETE') # DELETEメソッドを使うリクエストを作成 |
||
| 192 | >>> with request.urlopen(req) as f: |
||
| 193 | ... res_body = f.read()[:110] |
||
| 194 | ... res_status = f.status |
||
| 195 | ... |
||
| 196 | >>> res_status |
||
| 197 | 200 |
||
| 198 | >>> res_body |
||
| 199 | b'{\n "args": {}, \n "data": "", \n "files": {}, \n "form": {\n "key1": "value1", \n "key2": "value2"\n }, \n' |
||
| 200 | ``` |
||
| 201 | |||
| 202 | ### レスポンスモジュール urllib.response |
||
| 203 | urllib で使用するレスポンスモジュール `urllib.response` は file-like オブジェクトで、`read()` `readline()` 等のメソッドが使用可能. 実際に取得されるのは `urllib.response.addinfourl` インスタンス |
||
| 204 | - `addinfourl` の属性 |
||
| 205 | - `url` |
||
| 206 | - `headers` |
||
| 207 | - `status` |
||
| 208 | |||
| 209 | ## 14.3 ヒューマンフレンドリーな HTTP クライアント Requests |
||
| 210 | urllib.request と同様に GET や POST リクエストを行う機能を提供 |
||
| 211 | インポートは `import requests` |
||
| 212 | |||
| 213 | ### 指定の URL を開く |
||
| 214 | Requests では HTTP メソッドごとに対応するインターフェースが存在 |
||
| 215 | |||
| 216 | |HTTP メソッド|対応インターフェース| |
||
| 217 | |---|---| |
||
| 218 | |GET|`requests.get()`| |
||
| 219 | |HEAD|`requests.head()`| |
||
| 220 | |POST|`requests.post()`| |
||
| 221 | |PATCH|`requests.patch()`| |
||
| 222 | |PUT|`requests.put()`| |
||
| 223 | |DELETE|`requests.delete()`| |
||
| 224 | |OPTIONS|`requests.options()`| |
||
| 225 | |||
| 226 | ```python |
||
| 227 | >>> import requests |
||
| 228 | >>> r = requests.get('http://httpbin.org/get') |
||
| 229 | >>> r |
||
| 230 | <Response [200]> |
||
| 231 | |||
| 232 | >>> r.text |
||
| 233 | '{\n "args": {}, \n "headers": {\n "Accept": "*/*", \n "Accept-Encoding": "gzip, deflate", \n "Host": "httpbin.org", \n "User-Agent": "python-requests/2.23.0", \n "X-Amzn-Trace-Id": "Root=1-6058a4b8-363cb0c415a43cc3406ae42c"\n }, \n "origin": "219.121.30.187", \n "url": "http://httpbin.org/get"\n}\n' |
||
| 234 | >>> r = requests.get('http://httpbin.org/get', params='example') # クエリ付き GET |
||
| 235 | >>> r.url |
||
| 236 | 'http://httpbin.org/get?example' |
||
| 237 | >>> r = requests.get('http://httpbin.org/get', params={'key': 'value'}) # クエリ付き GET (辞書指定) |
||
| 238 | >>> r.url |
||
| 239 | 'http://httpbin.org/get?key=value' |
||
| 240 | ``` |
||
| 241 | |||
| 242 | - レスポンスオブジェクト |
||
| 243 | - Requests では HTTP リクエストの結果を `requests.models.Response` オブジェクトで返す |
||
| 244 | |||
| 245 | |属性|解説| |
||
| 246 | |---|---| |
||
| 247 | |`request`|リクエスト情報を保持するオブジェクト| |
||
| 248 | |`url`|リクエスト時の URL 文字列| |
||
| 249 | |`cookies`|レスポンスに含まれる Cookie 情報を保持するオブジェクト| |
||
| 250 | |`headers`|辞書形式のレスポンスヘッダー| |
||
| 251 | |`status_code`|レスポンスの HTTP ステータスコード| |
||
| 252 | |`ok`|レスポンスの HTTP ステータスコードが正常である場合は True、そうでない場合は False| |
||
| 253 | |`text`|文字列にエンコード済みのレスポンスボディ| |
||
| 254 | |`iter_lines()`|レスポンスボディを1行ずつ返すイテレーターを返す (文字列では無くバイト列を返す)| |
||
| 255 | |`json()`|レスポンスボディを JSON フォーマットとしてパースし、辞書を返す| |
||
| 256 | |||
| 257 | - Requests オブジェクトは bool として評価すると以下の通り値を返す為、分岐に利用できる |
||
| 258 | - HTTP ステータスが 400 未満: True |
||
| 259 | - HTTP ステータスが 400 以上: False |
||
| 260 | |||
| 261 | - Requests では Session モードをサポートしている |
||
| 262 | - ログインが必要な Web サイトにおいても、永続的コネクションや Cookie を使用できる |
||
| 263 | - `requests.Session()` で生成した `Session` オブジェクトのメソッドとして `get()` `post()` 等を使用する |
||
| 264 | |||
| 265 | ```python |
||
| 266 | >>> import requests |
||
| 267 | >>> session = requests.Session() |
||
| 268 | >>> response = session.get('https://httpbin.org/cookies/set?title=pylibbook2&libName=requests') |
||
| 269 | >>> session.cookies.get_dict() # クエリ文字列がCookieとして保存されていることを確認 |
||
| 270 | {'libName': 'requests', 'title': 'pylibbook2'} |
||
| 271 | # さらに別のクエリ文字列を追加してみる |
||
| 272 | >>> response = session.get('https://httpbin.org/cookies/set?description=sessionTest') |
||
| 273 | >>> session.cookies.get_dict() # Cookieが追加されていることを確認 |
||
| 274 | {'description': 'sessionTest', 'libName': 'requests', 'title': 'pylibbook2'} |
||
| 275 | ``` |
||
| 276 | |||
| 277 | ## 14.4 Base16, Base64 などへエンコードする base64 |
||
| 278 | データのエンコード、デコードを扱う base64 モジュール |
||
| 279 | |||
| 280 | - base64 では以下のエンコード方式を扱うことが可能 |
||
| 281 | - Base16 |
||
| 282 | - Base32 |
||
| 283 | - Base64 |
||
| 284 | - Base85 |
||
| 285 | |||
| 286 | これらのエンコード方式は、アルファベットと数字だけなどの限られた文字種類しか扱えない環境において、それ以外の文字 (マルチバイト文字、バイトデータ等) を扱う為に利用される. 最も広く利用されている Base64 は、電子メールや URL の一部、 HTTP リクエストの一部に使われている |
||
| 287 | |||
| 288 | ### Base64 にエンコードする base64.b64encode() |
||
| 289 | - 関数 `b64encode(s, altchars=None)` |
||
| 290 | - `s` Base64 アルファベットにエンコードする **バイトデータ** を指定 |
||
| 291 | - `altchars` + と / の代わりに使用する **バイト列** を指定 |
||
| 292 | - **戻り値** bytes |
||
| 293 | |||
| 294 | <br>Base64 エンコードで扱うのはバイト列であり、文字列を指定すると TypeError となる (文字列を扱う場合は `encode()` でバイト列化して使用する) |
||
| 295 | |||
| 296 | ```python |
||
| 297 | >>> import base64 |
||
| 298 | >>> s = 'Python は簡単に習得でき、それでいて強力な言語の1つです。' |
||
| 299 | >>> base64.b64encode(s) # 文字列を渡すとエラー |
||
| 300 | Traceback (most recent call last): |
||
| 301 | File "<stdin>", line 1, in <module> |
||
| 302 | File "/xxxxxxx/python3.9/base64.py", line 58, in b64encode |
||
| 303 | encoded = binascii.b2a_base64(s, newline=False) |
||
| 304 | TypeError: a bytes-like object is required, not 'str' |
||
| 305 | >>> base64.b64encode(s.encode()) # バイト文字列にエンコードして渡す |
||
| 306 | b'UHl0aG9uIOOBr+ewoeWNmOOBq+e/kuW+l+OBp+OBjeOAgeOBneOCjOOBp+OBhOOBpuW8t+WKm+OBquiogOiqnuOBruS4gOOBpOOBp+OBmeOAgg==' |
||
| 307 | # +と/の代わりに使用する文字列をaltcharsで指定する |
||
| 308 | >>> base64.b64encode(s.encode(), altchars=b'@*') |
||
| 309 | b'UHl0aG9uIOOBr@ewoeWNmOOBq@e*kuW@l@OBp@OBjeOAgeOBneOCjOOBp@OBhOOBpuW8t@WKm@OBquiogOiqnuOBruS4gOOBpOOBp@OBmeOAgg==' |
||
| 310 | ``` |
||
| 311 | |||
| 312 | `altchar` の指定で + と / の置き換えが指定できるが、URL で安全に利用可能なエンコード文字列を返す `urlsafe_b64encode()` もある (`+` は `-` に、`/` は `_` になる) |
||
| 313 | |||
| 314 | ### Base64 からデコードする base64.b64decode() |
||
| 315 | - 関数 `b64decode(s, altchars=None, validate=False)` |
||
| 316 | - `s` デコードする **バイト列** を指定 |
||
| 317 | - `altchar` + と / の代わりに使用する **バイト列** を指定 |
||
| 318 | - `validate` True の場合、入力に Base64 アルファベット以外の文字があると binascii.Error を返す |
||
| 319 | - **戻り値** bytes |
||
| 320 | |||
| 321 | ```python |
||
| 322 | >>> s = 'Python は簡単に習得でき、それでいて強力な言語の1つです。' |
||
| 323 | # Base64エンコード/デコード |
||
| 324 | >>> enc_s = base64.b64encode(s.encode()) |
||
| 325 | >>> base64.b64decode(enc_s).decode() |
||
| 326 | 'Python は簡単に習得でき、それでいて強力な言語の1つです。' |
||
| 327 | # Base64アルファベット以外のaltcharsを指定したものをvalidate=Trueでデコードするとエラーになる |
||
| 328 | >>> enc_s = base64.b64encode(s.encode(), altchars=b'-_') |
||
| 329 | >>> base64.b64decode(enc_s, validate=True) |
||
| 330 | Traceback (most recent call last): |
||
| 331 | File "<stdin>", line 1, in <module> |
||
| 332 | File "/xxxx/python3.9/base64.py", line 86, in b64decode |
||
| 333 | raise binascii.Error('Non-base64 digit found') |
||
| 334 | binascii.Error: Non-base64 digit found |
||
| 335 | ``` |
||
| 336 | |||
| 337 | `b64encode()` に対する `urlsafe_b64encode` と同様に、`b64decode()` に対する `urlsafe_b64decode()` も存在する |
||
| 338 | |||
| 339 | ### base64 の使われ方 |
||
| 340 | 文字列しか扱えないがバイナリデータを送受信したい場面で利用される |
||
| 341 | - 例えば |
||
| 342 | - 電子メールにバイナリを添付 |
||
| 343 | - HTTP リクエストでバイナリを送信 |
||
| 344 | - JSON にバイナリ (画像等) を含める |
||
| 345 | |||
| 346 | ## 14.5 電子メールのデータを処理する email |
||
| 347 | 電子メールメッセージや MIME (Multipurpose Internae Mail Extensions) などのメッセージ文書を管理する機能を提供 |
||
| 348 | |||
| 349 | - メッセージデータを管理 `email.message` |
||
| 350 | - メールのメッセージを解析 `email.parser` |
||
| 351 | |||
| 352 | ### メッセージのデータを管理する email.message |
||
| 353 | 最も使用されるのは `EmailMessage` クラス |
||
| 354 | |||
| 355 | |メソッド名|解説|戻り値| |
||
| 356 | |---|---|---| |
||
| 357 | |`as_string(unixfrom=False, maxheaderlen=None, policy=None)`|メッセージ全体を文字列で返す|str| |
||
| 358 | |`as_bytes(unixfrom=None, policy=None)`|メッセージ全体をバイト列で返す|bytes| |
||
| 359 | |`is_multipart()`|メッセージのペイロードがマルチパート (複数のデータを含む) 場合に True|bool| |
||
| 360 | |`keys()`|ヘッダーのフィールド名のリストを返す|list| |
||
| 361 | |`values()`|メッセージ内のすべてのフィールドの値を返す|list| |
||
| 362 | |`items()`|ヘッダーのすべてのフィールドと値のタプルのリストを返す|list| |
||
| 363 | |`get(name, failobj=None)`|指定したヘッダーフィールドの値を返す|str| |
||
| 364 | |`get_all(name, failobj=None)`|指定したフィールドのすべての値を返す|list| |
||
| 365 | |`add_header(_name, _value, **_params)`|拡張ヘッダーを設定する|None| |
||
| 366 | |`get_content_charset(failobj=None)`|Content-Type の charset パラメータの値を返す|str| |
||
| 367 | |`get_content_type()`|Content-Type の値を返す|str| |
||
| 368 | |`set_content(msg, obj, *args, **kw)`|email.contentmanager.ContentManager クラスを呼び出し、メッセージを設定する|None| |
||
| 369 | |`add_attachment(*args, content_manager=None, **kw)`|multipart/mixed の添付ファイルを指定する|None| |
||
| 370 | |||
| 371 | ```python |
||
| 372 | >>> import email.message |
||
| 373 | >>> msg = email.message.EmailMessage() |
||
| 374 | # ヘッダーをセット |
||
| 375 | >>> msg.add_header("From", "kadowaki@example.com") |
||
| 376 | >>> msg.add_header("To", "somebody@example.com, anyone@example.com") |
||
| 377 | >>> msg.add_header("Subject", "Test Mail") |
||
| 378 | # メッセージをセット |
||
| 379 | >>> msg_body = """ |
||
| 380 | ... Hello Python! |
||
| 381 | ... |
||
| 382 | ... Bye!! |
||
| 383 | ... """ |
||
| 384 | >>> msg.set_content(msg_body) |
||
| 385 | >>> msg.is_multipart() # マルチパートか確認 |
||
| 386 | False |
||
| 387 | >>> msg.keys() # ヘッダーの一覧を取得 |
||
| 388 | ['From', 'To', 'Subject', 'Content-Type', 'Content-Transfer-Encoding', 'MIME-Version'] |
||
| 389 | >>> msg.values() # ヘッダーの値の一覧を取得 |
||
| 390 | ['kadowaki@example.com', 'somebody@example.com, anyone@example.com', 'Test Mail', 'text/plain; charset="utf-8"', '7bit', '1.0'] |
||
| 391 | >>> msg.get("From") # Fromの値を取得 |
||
| 392 | 'kadowaki@example.com' |
||
| 393 | >>> msg.get_payload() # ペイロード(本文)を取得 |
||
| 394 | '\nHello Python!\n\nBye!!\n' |
||
| 395 | >>> msg.as_string() # メッセージ全体を文字列で取得 |
||
| 396 | 'From: kadowaki@example.com\nTo: somebody@example.com, anyone@example.com\nSubject: Test Mail\nContent-Type: text/plain; charset="utf-8"\nContent-Transfer-Encoding: 7bit\nMIME-Version: 1.0\n\n\nHello Python!\n\nBye!!\n' |
||
| 397 | # メッセージにファイルを添付する例 |
||
| 398 | >>> with open('email.txt', 'rb') as f: |
||
| 399 | ... data = f.read() |
||
| 400 | ... |
||
| 401 | >>> msg.add_attachment(data, maintype='text', subtype='plain') |
||
| 402 | >>> msg.add_header('Content-Disposition', 'attachment', filename='email.txt') |
||
| 403 | >>> msg.is_multipart() |
||
| 404 | True |
||
| 405 | ``` |
||
| 406 | |||
| 407 | ### メールを解析する email.parser |
||
| 408 | メールのメッセージを解析する |
||
| 409 | |||
| 410 | - class `Parser(_class=None, *, policy=policy.compat32)` |
||
| 411 | - テキストをパースするオブジェクトを生成 |
||
| 412 | |||
| 413 | |メソッド名|解説|戻り値| |
||
| 414 | |---|---|---| |
||
| 415 | |`parse(fp, headersonly=False)`|テキストストリーム `fp` を解析しメッセージを生成する<br>`headersonly` が True の場合、ヘッダー部分のみ解析する|email.message.Message| |
||
| 416 | |`parsestr(text, headersonly=False)`|指定された文字列を解析する|email.message.Message| |
||
| 417 | |||
| 418 | - class `BytesParser(_class=None, *, policy=policy.compat32)` |
||
| 419 | - バイナリ (バイト列) をパースするオブジェクトを生成 |
||
| 420 | |||
| 421 | |メソッド名|解説|戻り値| |
||
| 422 | |---|---|---| |
||
| 423 | |`parse(fp, headersonly=False)`|バイナリストリーム `fp` を解析しメッセージを生成する<br>`headersonly` が True の場合、ヘッダー部分のみ解析する|email.message.Message| |
||
| 424 | |`parsebytes(bytes, headersonly=False)`|指定された bytes-like オブジェクトを解析する|email.message.Message| |
||
| 425 | |||
| 426 | - パーサオブジェクトを生成せずに直接パースする関数もある |
||
| 427 | - `email.message_from_file(fp)`: Parser().parse(fp) 相当 |
||
| 428 | - `email.message_from_string(s)`: Parser().parsestr(s) 相当 |
||
| 429 | - `email.message_from_binary_file(fp)`: BytesParser().parse(fp) 相当 |
||
| 430 | - `email.message_from_byptes(s)`: BytesParser().parsebytes(s) 相当 |
||
| 431 | |||
| 432 | - `Parser` `BytesParser` は policy を指定しないと (`email.message.EmailMessage` ではなく) `email.message.Message` を返すが、これは後方互換の為に policy=policy.compat32 となっているから |
||
| 433 | - policy=email.policy.default とすることで `EmailMessage` が取得できる |
||
| 434 | |||
| 435 | ### email モジュール とメール送信 |
||
| 436 | - email モジュールはメッセージ自体の管理を提供する |
||
| 437 | - メール送信については設計されていない |
||
| 438 | - メール送信には別途 smtplib モジュール等の SMTP 機能を利用する |