1. urllibモジュールの概要
urllibはPythonに標準搭載されているHTTPクライアントパッケージであり、スクリプトからWebサーバーに対してリクエストを送信し、レスポンスを処理する基盤機能を提供します。Python 3環境では、HTTP通信の制御を担うurllib.requestと、URLの解析やエンコードを処理するurllib.parseが主要なサブモジュールとして利用されます。
2. 基礎的なHTMLコンテンツの取得
指定したエンドポイントに対してGETリクエストを実行し、サーバーから返されたHTMLソースを取得する実装例を以下に示します。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from urllib.request import urlopen
def retrieve_web_content(request_url):
# 指定URLへリクエストを送信し、レスポンスオブジェクトを取得
server_res = urlopen(request_url)
# レスポンスボディをバイト列として読み込み
raw_payload = server_res.read()
return raw_payload
if __name__ == '__main__':
target_site = 'https://example.com'
html_bytes = retrieve_web_content(target_site)
# バイト列をUTF-8でデコードしてコンソールに出力
print(html_bytes.decode('utf-8'))
urlopen関数はターゲットURLを受け取り、通信が成功するとレスポンスオブジェクトを返します。取得されたデータはデフォルトでbytes型であるため、文字列として扱う場合は適切なエンコーディングでデコードする処理が必須です。また、レスポンスオブジェクトからはステータスコードやヘッダー情報などのメタデータも参照可能です。
3. レスポンスデータのローカル保存
取得したHTMLデータをファイルとして永続化するには、標準のファイルI/O操作と組み合わせます。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from urllib.request import urlopen
if __name__ == '__main__':
endpoint = 'https://example.com'
http_res = urlopen(endpoint)
# バイト列を文字列に変換
text_content = http_res.read().decode('utf-8')
# コンテキストマネージャを用いてテキストファイルに書き込み
with open('local_archive.html', 'w', encoding='utf-8') as file_stream:
file_stream.write(text_content)
print('ローカルファイルへの書き込みが完了しました。')
open関数の書き込みモード('w')を使用し、エンコーディングを明示的に指定することで文字化れを防ぎながらデータをディスクに出力します。
4. バイナリデータ(画像)のダウンロード処理
画像やPDFなどの非テキストデータを取得する場合は、文字コード変換を行わず、そのままのバイト列をバイナリモードで保存します。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from urllib.request import urlopen
import ssl
# 環境によってはHTTPS検証でエラーが出るため、一時的に検証を無効化
ssl._create_default_https_context = ssl._create_unverified_context
if __name__ == '__main__':
asset_url = 'https://via.placeholder.com/150'
res_obj = urlopen(asset_url)
img_bytes = res_obj.read()
# バイナリ書き込みモード('wb')で直接保存
with open('sample_image.jpg', 'wb') as binary_file:
binary_file.write(img_bytes)
print('メディアファイルの保存に成功しました。')
バイナリデータに対してdecode()を実行すると例外が発生するため、'wb'モードで直接書き込むことが正しいアプローチとなります。
5. 非ASCII文字列を含むURLのエンコード
URL仕様上、パスやクエリパラメータに日本語や特殊記号を直接含めることはできません。検索ワードなどのパラメータをURLに組み込む際は、パーセントエンコーディングを適用する必要があります。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from urllib.request import urlopen
from urllib.parse import urlencode
if __name__ == '__main__':
base_endpoint = 'https://example.com/search'
# 辞書形式でパラメータを定義
query_data = {
'keyword': '機械学習入門',
'category': 'tech'
}
# パラメータをURLエンコードしてクエリ文字列を生成
encoded_query = urlencode(query_data)
complete_url = f'{base_endpoint}?{encoded_query}'
print(f'生成されたリクエストURL: {complete_url}')
api_res = urlopen(complete_url)
result_data = api_res.read()
with open('search_results.html', 'wb') as out_f:
out_f.write(result_data)
urllib.parse.urlencodeを使用することで、辞書内のキーと値が自動的にkey=value形式に変換され、非ASCII文字が安全な形式にエンコードされます。
6. カスタムリクエストヘッダーによるアクセス制御回避
多くのWebサービスは、リクエストヘッダーのUser-Agentフィールドを監視し、ボットやスクリプトからのアクセスをフィルタリングします。標準のurlopenのみではヘッダーの変更が困難なため、urllib.request.Requestオブジェクトを明示的に生成してヘッダー情報を上書きします。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from urllib.request import Request, urlopen
if __name__ == '__main__':
secured_url = 'https://example.com/api/data'
# 一般的なデスクトップブラウザの識別情報を模倣
mock_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
'Accept-Language': 'ja,en;q=0.9'
}
# ヘッダー情報を含めたリクエストオブジェクトを生成
browser_req = Request(url=secured_url, headers=mock_headers)
# カスタムリクエストを実行
final_res = urlopen(browser_req)
html_body = final_res.read().decode('utf-8')
print(f'通信ステータス: {final_res.status}')
# 取得したコンテンツを解析または保存
Requestクラスのインスタンス生成時にheaders引数を渡すことで、任意のHTTPヘッダーをリクエストに埋め込むことが可能です。これにより、サーバー側のUAチェックを通過し、正常なコンテンツの取得が期待できます。