Python

Python入門ガイド: WEB開発の世界へようこそ【WEBを解きほぐす】

Pythonは多くの開発者にとって信頼性の高い言語として広く知られていますが、その利用範囲はウェブ開発にも及んでいます。ウェブは現代社会で不可欠な要素であり、Pythonを使ってウェブを解きほぐすことは、より効果的なウェブアプリケーションやサービスを構築するための重要なスキルとなっています。

この記事では、Pythonにおけるウェブ開発について詳しく探求します。まず、ウェブクライアントの基本的なテスト方法として、telnet、curl、httpieの活用法を学びます。次に、Pythonの標準ウェブライブラリを使用してウェブクライアントを構築する方法を探求します。さらに、requestsという強力なライブラリを使い、標準ライブラリを超えたウェブクライアントの機能を体験します。

クロールとスクレイピングについても詳しく探求します。Scrapy、BeautifulSoup、Requests-HTMLといったツールを使用してウェブページのクローリングやスクレイピングを行い、データの収集や分析に活用する方法を学びます。

これまで10個位の記事に分けて書いてきた【Python入門ガイド】は、この記事で最終回になります。今後のPythonの記事では、これらの知識に加えて更にライブラリーを活用した応用であったり実務に即活かせる内容を発信していきます。
勿論、触れてこれなかった部分もあるので、完全な初心者向けの記事も追加します。

目次

ウェブを解きほぐす

Pythonを使ってウェブ開発を行うための基礎から応用までをカバーします。ウェブクライアントやウェブサーバ、ウェブフレームワーク、データベースフレームワークなど、さまざまなトピックに焦点を当て、Pythonの強力なツールセットを活用してウェブ開発をより効率的に行う方法を解説します。

ウェブクライアント

ウェブクライアントは、ウェブサーバと通信するために使用されるツールやライブラリです。本節では、いくつかのウェブクライアントツールについて説明します。

telnetによるテスト

telnetは、ネットワーク上のサーバに接続するためのプロトコルです。telnetを使用してウェブサーバに接続し、HTTPリクエストを手動で送信することができます。

以下にtelnetを使用してウェブサーバに接続し、GETリクエストを送信する例を示します。

$ telnet example.com 80
GET / HTTP/1.1
Host: example.com

Pythonのtelnetlibモジュールを使用してTelnetを介したWEBテストの手順を以下に解説します。

telnetlibモジュールのインポート
import telnetlib
Telnet接続の確立
host = "example.com"  # 接続先のホスト名またはIPアドレス
port = 80  # 接続先のポート番号 (通常は80番ポートを使用)

# Telnet接続を確立
tn = telnetlib.Telnet(host, port)
HTTPリクエストを送信する
request = "GET /path/to/page HTTP/1.1\r\n"  # 取得したいページのパス
request += "Host: example.com\r\n"  # ホスト名
request += "Connection: close\r\n\r\n"  # 接続を閉じる

tn.write(request.encode('ascii'))
サーバーからのレスポンスを受け取る
response = tn.read_all().decode('ascii')

上記のコードでは、tn.read_all()メソッドを使用してサーバーからのすべてのデータを受信しています。decode('ascii')メソッドを使用して、受信したデータを文字列にデコードしています。

Telnet接続を閉じる
tn.close()

これでTelnetを使用してWEBテストを行うための基本的な手順が完了しました。ただし、この方法は基本的なHTTPリクエスト/レスポンスの送受信を行うためのものであり、JavaScriptや動的なコンテンツを含む場合にはうまく動作しないことがあります。

Pythonのtelnetlibモジュールは、Telnetプロトコルをサポートしているため、WEBテスト以外にもさまざまなネットワークテストや自動化タスクに利用することができますので、今後色々と解説していきたいと思っています。

curlによるテスト

curlはコマンドライン上で使用することができるツールで、HTTPやFTPを含むさまざまなプロトコルを使用してデータを転送することができます。以下にcurlの一般的な使用例とオプションのいくつかを示します。

curlコマンドのオプション
  1. -X, --request <command>: HTTPメソッドを指定します。デフォルトはGETですが、POSTPUTなどの他のメソッドも指定できます。
  2. -H, --header <header>: リクエストヘッダを追加します。複数のヘッダを指定する場合は、このオプションを複数回使用します。
  3. -d, --data <data>: POSTリクエストのデータを指定します。データはURLエンコードされた形式で指定します。
  4. -F, --form <name=content>: マルチパートフォームデータを送信します。フォームフィールドの名前と内容を指定します。
  5. -u, --user <user:password>: Basic認証のユーザー名とパスワードを指定します。
  6. -i, --include: レスポンスヘッダを表示します。
  7. -o, --output <file>: レスポンスを指定したファイルに保存します。
  8. -s, --silent: 静かなモードで実行し、進行状況やエラーメッセージを表示しません。
  9. -v, --verbose: 詳細な出力を表示します。

これらのオプションを使用してWEBテストを行う簡単な例をいくつか示します。

URLにGETリクエストを送信する例
$ curl http://example.com
URLにPOSTリクエストを送信する例
$ curl -X POST http://example.com
レスポンスヘッダも含めて詳細な情報を表示する例
$ curl -i http://example.com
レスポンスのボディのみを表示する例
$ curl -s http://example.com
レスポンスをファイルに保存する例
$ curl -o filename.txt http://example.com
Basic認証を使用してリクエストを送信する例
$ curl -u username:password http://example.com
POSTリクエストでパラメータを渡す方法
$ curl -X POST -d "param1=value1¶m2=value2" http://example.com

上記の例では、-X POSTオプションを使用してPOSTリクエストを指定し、-d "param1=value1&param2=value2"オプションでパラメータを指定しています。パラメータはkey=valueの形式で指定し、複数のパラメータを指定する場合は&で区切ります。

GETリクエストでパラメータを渡す方法
$ curl "http://example.com?param1=value1¶m2=value2"

上記の例では、URLにパラメータを含めることでGETリクエストでパラメータを渡しています。http://example.comの後に?を追加し、それに続けてパラメータをkey=value形式で指定します。複数のパラメータを指定する場合は、&で区切ります。

パラメータに特殊文字が含まれる場合は、適切にエンコードする必要があります。一般的にはURLエンコードを使用します。curlコマンドは一部の特殊文字を自動的にエンコードする場合がありますが、正確さを保証するために手動でエンコードすることをおすすめします。

curlを使用すると、簡単にGETやPOSTなどのHTTPリクエストを送信することができ、また上で示した様にパラメータを渡すこともできますので、ターミナル上で簡単にテストを行う事が可能です。

Pythonのcurlと同様の機能を提供するモジュールとしては、requestsがあります。

httpieによるテスト

HTTPieは、コマンドラインでHTTPクライアントを操作するためのツールです。Pythonで開発されており、シンプルで使いやすいインターフェースを提供しています。以下に、PythonのHTTPieを使用したWEBテストの解説を詳しく説明します。

HTTPieのインストール

HTTPieを使用するには、まずPythonパッケージとしてインストールする必要があります。以下のコマンドを使用して、HTTPieをインストールします。

$ pip install httpie
GETリクエストの送信

HTTPieを使用してGETリクエストを送信するには、以下のようなコマンドを使用します。

$ http GET <URL>

例えば、http GET https://api.example.com/usersのようにURLを指定して実行すると、指定したURLにGETリクエストが送信されます。

POSTリクエストの送信

HTTPieを使用してPOSTリクエストを送信するには、以下のようなコマンドを使用します。

$ http POST <URL> <パラメーター1>=<値1> <パラメーター2>=<値2> ...

例えば、http POST https://api.example.com/users name=John age=25のようにURLとパラメーターを指定して実行すると、指定したURLにPOSTリクエストが送信されます。

レスポンスの表示

HTTPieを使用してリクエストを送信すると、レスポンスが表示されます。以下のような形式でレスポンスが表示されます。

HTTP/1.1 200 OK
Content-Type: application/json

{
    "key1": "value1",
    "key2": "value2"
}

レスポンスヘッダーとレスポンスボディが表示されます。JSON形式の場合、ボディの内容も表示されます。

レスポンスの内容の抽出

レスポンスの内容を抽出して使用する場合、HTTPieは便利な機能を提供しています。例えば、レスポンスボディの特定のキーの値を抽出する場合は、以下のようなコマンドを使用します。

$ http GET <URL> | jq .<キー>

jqは、JSONデータを操作するためのツールです。このコマンドを使用することで、指定したキーの値のみを抽出することができます。

認証の追加

サーバーに対して認証が必要な場合、HTTPieを使用して認証情報を指定することができます。以下のように認証情報を指定します。

$ http --auth <ユーザー名>:<パスワード> GET <URL>

ユーザー名とパスワードを指定することで、認証情報を含めたリクエストが送信されます。

ヘッダーの追加

HTTPieを使用してリクエストヘッダーを追加するには、以下のようなコマンドを使用します。

$ http GET <URL> <ヘッダー名>:<値>

例えば、http GET https://api.example.com/users User-Agent:MyAppのように、User-Agentヘッダーを指定して実行すると、指定したヘッダーを含むリクエストが送信されます。

クッキーの送信

HTTPieを使用してクッキーを送信するには、以下のようなコマンドを使用します。

$ http GET <URL> Cookie:<クッキー名>=<値>

例えば、http GET https://api.example.com/users Cookie:session_id=abc123のように、Cookieヘッダーを指定して実行すると、指定したクッキーを含むリクエストが送信されます。

以上が、PythonのHTTPieを使用したWEBテストの解説です。HTTPieはシンプルなインターフェースを持つため、直感的に操作することができます。

httpbinによるテスト

httpbinは、HTTPリクエストとレスポンスのテストを行うための便利なツールです。Pythonのrequestsライブラリを使用してhttpbinにリクエストを送信し、さまざまなテストシナリオを実行することができます。以下では、httpbinを使用したPythonによるWEBテストの手順を詳しく説明します。

requestsライブラリのインストール

最初に、Pythonのrequestsライブラリをインストールする必要があります。以下のコマンドを使用してインストールします。

$ pip install requests
requestsライブラリのインポート

Pythonスクリプトの先頭でrequestsライブラリをインポートします。

import requests
GETリクエストの送信

最も基本的なテストシナリオは、httpbinにGETリクエストを送信してレスポンスを取得することです。以下のコードを使用してGETリクエストを送信し、レスポンスを表示します。

response = requests.get('https://httpbin.org/get')
print(response.text)

上記のコードでは、https://httpbin.org/getにGETリクエストを送信しています。レスポンスはresponse変数に格納され、response.textを使用してテキスト形式で表示されます。

POSTリクエストの送信

次のテストシナリオは、httpbinにPOSTリクエストを送信することです。以下のコードを使用してPOSTリクエストを送信し、レスポンスを表示します。

data = {'key': 'value'}
response = requests.post('https://httpbin.org/post', data=data)
print(response.text)

上記のコードでは、dataという名前の辞書オブジェクトを作成し、POSTリクエストのデータとして使用しています。response変数にはレスポンスが格納され、response.textを使用してテキスト形式で表示されます。

レスポンスの解析

レスポンスの解析も重要なテストシナリオです。requestsライブラリは、レスポンスを解析し、さまざまな方法でアクセスするための便利な機能を提供しています。以下の例では、JSON形式のレスポンスから特定のフィールドを取得します。

response = requests.get('https://httpbin.org/get')
data = response.json()
print(data['origin'])

上記のコードでは、response.json()を使用してレスポンスをJSON形式で解析し、data変数に格納しています。次に、data['origin']を使用してレスポンスのoriginフィールドの値を取得して表示しています。

クエリパラメータの送信

httpbinでは、クエリパラメータを使用してテストを行うこともできます。以下の例では、クエリパラメータを指定してGETリクエストを送信します。

params = {'key': 'value'}
response = requests.get('https://httpbin.org/get', params=params)
print(response.text)

上記のコードでは、paramsという名前の辞書オブジェクトを作成し、クエリパラメータとして使用しています。response変数にはレスポンスが格納され、response.textを使用してテキスト形式で表示されます。

ヘッダーの設定

テストする際に、カスタムヘッダーをリクエストに追加することもできます。以下の例では、Authorizationヘッダーを設定してGETリクエストを送信します。

headers = {'Authorization': 'Bearer my_token'}
response = requests.get('https://httpbin.org/get', headers=headers)
print(response.text)

上記のコードでは、headersという名前の辞書オブジェクトを作成し、Authorizationヘッダーを追加しています。response変数にはレスポンスが格納され、response.textを使用してテキスト形式で表示されます。

httpbinを使用すると、さまざまなテスト用エンドポイントに対してリクエストを送信し、その結果を確認することができます。

Pythonの標準ウェブライブラリ

Pythonには、標準ライブラリとしてhttp.clientモジュールが提供されています。このモジュールを使用すると、ウェブサーバとの低レベルな通信を行うことができます。

以下にhttp.clientを使用してウェブテストを行う例と簡単な解説を示します。コメントも併せてご参照ください。

import http.client

conn = http.client.HTTPSConnection("example.com")
conn.request("GET", "/")

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))

上記のサンプルコードは以下のような機能を持っています。

  1. send_get_request(): http.client.HTTPSConnectionオブジェクトを作成し、GETリクエストを送信します。レスポンスを取得して表示します。
    • send_get_request()関数では、http.client.HTTPSConnectionオブジェクトを作成しています。引数にはリクエスト先のホスト名(ここではwww.example.com)を指定します。
    • conn.request("GET", "/")はGETリクエストを送信しています。第1引数にはHTTPメソッドを指定し、第2引数にはリクエスト先のパスを指定します(ここではルートパスを指定しています)。
    • response = conn.getresponse()でレスポンスを取得します。responseオブジェクトにはレスポンスのステータスコードやレスポンスヘッダーなどの情報が含まれます。
    • data = response.read()でレスポンスのデータを読み取ります。ここではresponse.read()の戻り値はバイナリデータなので、data.decode()でデコードして表示します。
  2. send_post_request(): http.client.HTTPSConnectionオブジェクトを作成し、POSTリクエストを送信します。ヘッダーとパラメータをカスタマイズし、レスポンスを取得して表示します。
    • send_post_request()関数では、POSTリクエストを送信しています。headers変数にはリクエストヘッダーを指定しています。ここではContent-typeヘッダーを設定しています。
    • params変数にはリクエストパラメータを指定しています。ここではparam1=value1&param2=value2のような形式で指定しています。
    • conn.request("POST", "/", params, headers)でPOSTリクエストを送信します。第3引数にはパラメータ、第4引数にはヘッダーを指定します。
  3. customize_headers(): http.client.HTTPSConnectionオブジェクトを作成し、GETリクエストを送信します。カスタムHTTPヘッダーを設定してレスポンスを取得して表示します。
    • customize_headers()関数では、カスタムHTTPヘッダーを指定してGETリクエストを送信しています。headers変数にはカスタムヘッダーを辞書形式で指定します。ここでは{"Custom-Header": "Value"}というヘッダーを指定しています。
    • conn.request("GET", "/", headers=headers)でGETリクエストを送信し、第3引数にヘッダーを指定します。
  4. disable_ssl_verification(): http.client.HTTPSConnectionオブジェクトを作成し、GETリクエストを送信します。SSL証明書の検証を無効化してレスポンスを取得して表示します。
    • disable_ssl_verification()関数では、SSL証明書の検証を無効化してGETリクエストを送信しています。
    • http.client.HTTPSConnectionの引数としてcontext=http.client._create_unverified_context()を指定することで、SSL証明書の検証を無効化します。

これらのサンプルコードを使用することで、http.clientモジュールを使ったWEBテストが行えます。各関数は異なる機能を持ち、GETリクエストやPOSTリクエストの送信、ヘッダーのカスタマイズ、SSL証明書の検証の有効化/無効化などが可能です。

標準ライブラリを越えて:requests

requestsは、Pythonの外部ライブラリであり、ウェブサーバとのHTTP通信を簡単に行うことができます。requestsは、より高水準の抽象化を提供し、より使いやすいインタフェースを持っています。

インストール

$ pip install requests

使用例

Pythonのrequestsモジュールを使用してWEBテストを行うためのサンプルコードです。

import requests

# 基本的なGETリクエスト
response = requests.get('https://www.example.com')
print(response.status_code)  # ステータスコードを表示
print(response.text)  # レスポンスボディを表示

# クエリパラメータを含むGETリクエスト
params = {'key1': 'value1', 'key2': 'value2'}
response = requests.get('https://www.example.com', params=params)
print(response.url)  # リクエストURLを表示

# ヘッダーを指定したGETリクエスト
headers = {'User-Agent': 'Mozilla/5.0'}
response = requests.get('https://www.example.com', headers=headers)

# POSTリクエスト
data = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://www.example.com', data=data)

# JSONデータを含むPOSTリクエスト
import json
data = {'key1': 'value1', 'key2': 'value2'}
json_data = json.dumps(data)  # PythonオブジェクトをJSONに変換
response = requests.post('https://www.example.com', json=json_data, headers=headers)

# レスポンスのエラーハンドリング
response = requests.get('https://www.example.com')
if response.status_code == 200:
    print('成功')
else:
    print('エラーが発生しました')

上記のサンプルコードでは、requestsモジュールを使用してさまざまなWEBテストのパターンを示しています。以下でそれぞれのパターンについて詳しく解説します。

  1. 基本的なGETリクエスト: この例では、requests.get()関数を使用してhttps://www.example.comにGETリクエストを送信します。responseオブジェクトには、レスポンスの情報が格納されます。response.status_codeを使用してステータスコードを表示し、response.textを使用してレスポンスボディを表示しています。
  2. クエリパラメータを含むGETリクエスト: params変数を使用してクエリパラメータを指定することができます。requests.get()関数にparams引数として渡すことで、クエリパラメータを含むGETリクエストを送信できます。response.urlを使用すると、リクエストURL全体を表示することができます。
  3. ヘッダーを指定したGETリクエスト: headers変数を使用してヘッダーを指定することができます。requests.get()関数にheaders引数として渡すことで、ヘッダーを含むGETリクエストを送信できます。ヘッダーは、User-AgentやAuthorizationなどの情報を含めるために使用されます。上記の例では、headers変数にUser-Agentを指定しています。
  4. POSTリクエスト: requests.post()関数を使用すると、POSTリクエストを送信できます。データはdata引数に辞書形式で指定します。この例では、data変数にkey1key2の値を指定しています。
  5. JSONデータを含むPOSTリクエスト: POSTリクエストでJSONデータを送信する場合、json引数を使用してデータを指定できます。まず、data変数に辞書形式のデータを指定し、json.dumps()関数を使用してPythonオブジェクトをJSON形式の文字列に変換します。そして、json引数にJSONデータを指定してPOSTリクエストを送信します。
  6. レスポンスのエラーハンドリング: レスポンスのステータスコードを確認して、エラーハンドリングを行うことができます。この例では、GETリクエストを送信してレスポンスのステータスコードを確認し、ステータスコードが200の場合には「成功」と表示し、それ以外の場合には「エラーが発生しました」と表示しています。

上で示した基本的なパターンを応用して、より複雑なWEBテストを実装することができます。

ウェブサーバ

ウェブサーバは、ウェブクライアントからのリクエストを受け取り、適切なレスポンスを返す役割を果たします。本節では、Pythonを使用してウェブサーバを作成する方法について説明します。

Pythonによるもっとも単純なウェブサーバ

Pythonのhttp.serverモジュールは、HTTPプロトコルを使用してファイルを提供するためのシンプルなWebサーバーを作成するためのモジュールです。このモジュールを使用すると、Pythonの標準ライブラリを利用して簡単にWebサーバーを作成することができます。

以下に、いくつかの一般的なパターンのサンプルコードを示します。それぞれのサンプルコードの下には、コードの解説がコメントとして書かれています。

# サンプルコード1: デフォルトのポート8000でWebサーバーを起動し、カレントディレクトリのファイルを提供する

import http.server
import socketserver

# ポート番号
PORT = 8000

# カレントディレクトリをルートとするハンドラーを作成
handler = http.server.SimpleHTTPRequestHandler

# ポート番号とハンドラーを指定してサーバーを起動
with socketserver.TCPServer(("", PORT), handler) as httpd:
    print("サーバーを開始しました。ポート番号: ", PORT)
    httpd.serve_forever()

このサンプルコードでは、デフォルトのポート番号8000でWebサーバーを起動しています。http.server.SimpleHTTPRequestHandlerクラスを使用して、カレントディレクトリのファイルを提供するハンドラーを作成しています。TCPServerクラスを使用して、指定したポート番号とハンドラーを持つサーバーを起動します。serve_forever()メソッドを呼び出すことで、サーバーはリクエストを受け付け続けます。

# サンプルコード2: 特定のポート番号でサーバーを起動し、カスタムのハンドラーを使用する

import http.server
import socketserver

# ポート番号
PORT = 8080

# カスタムのハンドラークラスを定義
class MyHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        # レスポンスのヘッダーを送信
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

        # レスポンスの本文を送信
        self.wfile.write(b"<h1>Hello, World!</h1>")

# ポート番号とカスタムのハンドラーを指定してサーバーを起動
with socketserver.TCPServer(("", PORT), MyHandler) as httpd:
    print("サーバーを開始しました。ポート番号: ", PORT)
    httpd.serve_forever()

このサンプルコードでは、カスタムのハンドラークラスを定義しています。MyHandlerクラスはhttp.server.SimpleHTTPRequestHandlerを継承し、do_GETメソッドをオーバーライドしています。このメソッドでは、HTTP GETリクエストが受信された際に実行される処理をカスタマイズしています。

do_GETメソッド内では、まずレスポンスのヘッダーを送信しています。send_responseメソッドを使用して200 OKのステータスコードを送信し、send_headerメソッドを使用してContent-typeヘッダーを設定しています。この例では、text/htmlを指定しています。

次に、レスポンスの本文を送信しています。wfile属性を使用して、レスポンスの本文をバイト列として送信しています。この例では、単純なHTMLタグを含むレスポンスを送信しています。

最後に、ポート番号とカスタムのハンドラーを指定してサーバーを起動しています。TCPServerクラスを使用してサーバーを作成し、指定したポート番号とカスタムのハンドラーを設定しています。serve_forever()メソッドを呼び出すことで、サーバーはリクエストを受け付け続けます。

これらのサンプルコードは、http.serverモジュールを使用して簡単にPythonのWebサーバーを作成する方法を示しています。カレントディレクトリのファイルを提供するデフォルトのハンドラーを使用するか、カスタムのハンドラーを作成して特定の処理を行うことができます。必要に応じて、さまざまなHTTPメソッドやリクエストヘッダーに対応するメソッドをオーバーライドすることもできます。

WSGI

WSGI(Web Server Gateway Interface)は、PythonのWebアプリケーションとWebサーバーの間の通信プロトコルです。WSGIを使用すると、異なるWebサーバーとアプリケーションフレームワークの組み合わせが可能になります。以下に、WSGIの基本的な使い方とサンプルコードを示します。

WSGIアプリケーションの作成

まず、WSGIアプリケーションを作成する必要があります。WSGIアプリケーションは、Webサーバーから要求を受け取り、レスポンスを返すための関数です。以下は、簡単なWSGIアプリケーションの例です。

def application(environ, start_response):
    status = '200 OK'
    headers = [('Content-type', 'text/plain')]
    start_response(status, headers)
    return [b'Hello, World!']

この例では、applicationという名前の関数がWSGIアプリケーションを表しています。この関数は、2つの引数(environstart_response)を受け取ります。environは辞書オブジェクトで、要求の環境変数などの情報を含んでいます。start_responseはレスポンスのステータスコードとヘッダーを設定するための関数です。

この例では、ステータスコードを200 OK、コンテンツのタイプをtext/plainとして設定しています。そして、start_responseを呼び出してレスポンスヘッダーを送信し、return文でレスポンスの本文を返しています。

WSGIサーバーの使用

次に、作成したWSGIアプリケーションを実行するためのWSGIサーバーを使用します。WSGIサーバーは、Webサーバーとアプリケーションの間のインタフェースとして機能し、HTTP要求を受け取り、WSGIアプリケーションに渡します。以下は、簡単なWSGIサーバーの例です。

from wsgiref.simple_server import make_server

# WSGIアプリケーションのインポート
from myapp import application

# サーバーの作成と起動
with make_server('', 8000, application) as httpd:
    print("Serving on port 8000...")
    httpd.serve_forever()

この例では、wsgirefモジュールからmake_server関数をインポートしています。make_server関数は、WSGIサーバーを作成するために使用されます。

また、myappというモジュールからapplication関数をインポートしています。application関数は先ほど作成したWSGIアプリケーションを表しています。

make_server関数を使用して、ホスト名(空文字列はすべてのインタフェースをバインド)、ポート番号(8000)、およびWSGIアプリケーションを指定してWSGIサーバーを作成します。そして、httpdオブジェクトを介してサーバーを起動します。

この例では、サーバーをポート番号8000で起動しています。サーバーが起動すると、指定したポートで要求を待ち受けます。

以上で、WSGIアプリケーションの作成とWSGIサーバーの起動の基本的な手順が示されました。これにより、Webアプリケーションの開発や実行にWSGIを利用することができます。

なお、上記のサンプルコードは標準ライブラリであるwsgirefを使用しています。実際のプロダクション環境では、より高度なWSGIサーバー(例: Gunicorn、uWSGI)やフレームワーク(例: Flask、Django)を使用することが一般的です。これらのツールは、より高速でスケーラブルなWSGIサーバーの機能を提供します。

ASGI

ASGI(Asynchronous Server Gateway Interface)は、非同期なウェブアプリケーションとウェブサーバの間の標準化されたインタフェースです。ASGIを使用することで、非同期な処理をサポートするウェブアプリケーションを作成することができます。

ASGIアプリケーションの基本的な構造

async def app(scope, receive, send):
    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            (b'content-type', b'text/plain'),
        ]
    })
    await send({
        'type': 'http.response.body',
        'body': b'Hello, ASGI!'
    })

このコードは、最も基本的なASGIアプリケーションの構造を示しています。app関数は、3つのパラメータを受け取ります。

  1. scopeは、リクエストの詳細情報を含む辞書です(例: プロトコル、パス、ヘッダーなど)。
  2. receiveは、リクエストのデータを非同期に受信するためのコールバック関数です。
  3. sendは、レスポンスのデータを非同期に送信するためのコールバック関数です。

このコードでは、send関数を使用して、HTTPレスポンスの開始とボディを送信しています。最初のsend呼び出しでは、レスポンスのステータスコード(200)とヘッダー(’content-type’)を設定しています。次のsend呼び出しでは、レスポンスのボディ(’Hello, ASGI!’)を送信しています。

WebSocket接続の処理

async def app(scope, receive, send):
    if scope['type'] == 'http':
        await send({
            'type': 'http.response.start',
            'status': 200,
            'headers': [
                (b'content-type', b'text/html'),
            ]
        })
        await send({
            'type': 'http.response.body',
            'body': b'<html><body>Hello, ASGI!</body></html>',
        })
    elif scope['type'] == 'websocket':
        websocket = await receive()
        await websocket.send_text('Hello, WebSocket!')
        await websocket.close()

このコードは、WebSocket接続の処理を示しています。scopetype'http'の場合は、HTTPリクエストを処理し、send関数を使用してHTMLレスポンスを送信します。

scopetype'websocket'の場合は、WebSocket接続を処理します。receive関数を使用してWebSocketメッセージを受信し、send_text関数を使用してメッセージを送信します。最後に、close関数を呼び出してWebSocket接続を閉じます。

この例では、ASGIを使用してHTTPおよびWebSocketの両方のリクエストを処理する柔軟性が示されています。

ASGIフレームワーク(FastAPI)を使用したアプリケーション

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello, ASGI!"}

このコードは、FastAPIというASGIフレームワークを使用したアプリケーションの例です。FastAPIクラスのインスタンスを作成し、@app.get("/")デコレータを使用してルートエンドポイントの処理関数を定義しています。

root関数は、HTTP GETリクエストがルートパス(”/”)に送信された場合に実行されます。関数は非同期で実装されており、JSONレスポンスを返します。

FastAPIはASGIをサポートしており、高速でパフォーマンスの高いWebアプリケーションの構築を容易にします。

これらのサンプルコードは、ASGIアプリケーションの基本的な構造と使用方法を示しています。ASGIは非同期処理を活用するため、リクエストの処理をブロックせずに他のタスクを実行できます。このような仕組みにより、PythonのWebアプリケーションのパフォーマンスとスケーラビリティが向上します。

Apache

Apacheは、広く使用されているウェブサーバソフトウェアです。Pythonを使用してウェブアプリケーションを開発する場合、Apacheと連携して動作させることができます。

PythonとApacheを連携させるためのいくつかのパターンのサンプルコードと解説を示します。

CGI(Common Gateway Interface)を使用する方法

#!/usr/bin/env python
print("Content-type: text/html")
print()
print("<html>")
print("<head><title>Hello World</title></head>")
print("<body>")
print("<h1>Hello World!</h1>")
print("</body>")
print("</html>")

このサンプルコードは、PythonのスクリプトをCGIとして実行するためのものです。最初の行で、スクリプトがどのインタープリタを使用して実行されるべきかを指定しています。次に、HTTPレスポンスヘッダーを出力し、改行します。その後、HTMLコンテンツを出力してブラウザに表示されるようにします。

mod_wsgiを使用する方法

def application(environ, start_response):
    status = '200 OK'
    output = b"Hello World!"
    response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]

このサンプルコードは、PythonのWSGI(Web Server Gateway Interface)アプリケーションを作成するためのものです。application関数は、WSGIサーバから呼び出され、HTTPレスポンスを生成します。environパラメータには、リクエストに関する情報が含まれており、start_response関数を使用してレスポンスのステータスとヘッダーを設定します。

これらのサンプルコードは、PythonとApacheを連携させるための一般的な方法です。CGIを使用する場合、Apacheの設定ファイルでCGIディレクトリを指定し、Pythonスクリプトを配置します。mod_wsgiを使用する場合、Apacheの設定ファイルでWSGIScriptAliasディレクティブを使用してPythonアプリケーションを指定します。

NGINX

NGINXも人気のあるウェブサーバソフトウェアであり、Pythonウェブアプリケーションをデプロイするために使用することができます。

PythonとNGINXの連携に関するサンプルコードと解説を提供します。まずは、PythonでWebアプリケーションを作成し、その後にNGINXを使用してアプリケーションをリバースプロキシとして配置する方法を説明します。

PythonでのWebアプリケーションの作成

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello, World!"

if __name__ == '__main__':
    app.run()

上記のコードは、Flaskフレームワークを使用して簡単なWebアプリケーションを作成するものです。hello()関数はルートURL(‘/’)にアクセスしたときに実行され、”Hello, World!”というメッセージを返します。

NGINXの設定ファイルの作成

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

上記の設定ファイルでは、NGINXがポート80でリクエストを待ち受けるように設定しています。また、proxy_passディレクティブを使用して、NGINXが受け取ったリクエストをhttp://localhost:5000にリバースプロキシします。これにより、NGINXがリクエストを受け取り、PythonのWebアプリケーションが動作するサーバーにリクエストを転送します。

PythonアプリケーションとNGINXの連携

PythonアプリケーションとNGINXを連携させるには、次の手順に従います。

  1. Pythonアプリケーションを実行します。
  2. NGINXの設定ファイルを作成し、NGINXを起動します。

具体的には、次の手順を実行します。

Pythonアプリケーション実行

Pythonアプリケーションを実行するには、ターミナルまたはコマンドプロンプトで以下のコマンドを実行します。

$ python app.py
NGINXの設定ファイルの作成と起動

NGINXの設定ファイルを作成します。例えば、/etc/nginx/sites-available/ディレクトリにexample.confという名前のファイルを作成します。

$ sudo vi /etc/nginx/sites-available/example.conf

テキストエディタが開いたら、先ほどの例の設定ファイルの内容をコピーして貼り付けます。

server_nameディレクティブには、自分のドメイン名またはIPアドレスを指定します。

proxy_passディレクティブには、Pythonアプリケーションが動作しているURLを指定します。上記の例では、http://localhost:5000となっています。

設定ファイルを保存して閉じます。

作成した設定ファイルを有効にするために、シンボリックリンクを作成します。

$ sudo ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/

NGINXを再起動します。

$ sudo service nginx restart

これでNGINXが起動し、Pythonアプリケーションとの連携が確立されます。

Pythonアプリケーションは、Flaskを使用して実行することが前提となっていますが、他のWebフレームワークを使用する場合でも基本的な概念は同じです。NGINXは、リバースプロキシとして動作し、クライアントからのリクエストを受け取ってPythonアプリケーションに転送する役割を果たします。

以上が、PythonとNGINXの連携に関する簡単な説明です。この連携を活用することで、より効率的なWebアプリケーションのデプロイやスケーリングが可能となります。

その他のPythonベースWSGIサーバ

Pythonには他にもいくつかのWSGIサーバがあります。例えば、GunicornやuWSGIなどがあります。色々試してみて、ご自身にあったものをお使いください。

ウェブサーバフレームワーク

ウェブサーバフレームワークは、ウェブアプリケーションの開発を簡素化するためのツールやライブラリの集合です。以下ではいくつかの人気のあるウェブサーバフレームワークについて説明します。これらのフレームワークは、とても1記事で解説しきれるものではないので、簡単な紹介に留めます。今後、これらのフレームワークを利用したチュートリアルなどを考えています。

必要に応じて、pip install を行なって下さい。

Bottle

PythonのウェブフレームワークであるBottleについて、パターンごとのサンプルコードと解説を提供します。Bottleはシンプルで軽量なフレームワークであり、ウェブアプリケーションの開発を容易にします。

ルートURLへのリクエストを処理する

from bottle import Bottle, run

app = Bottle()

@app.route('/')
def index():
    return "Hello, World!"

if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このサンプルコードでは、ルートURL (“/”) へのリクエストを処理するシンプルなウェブアプリケーションが作成されています。@app.route('/') デコレータは、ルートURLへのリクエストがあったときに実行される関数を指定します。index() 関数では、”Hello, World!” の文字列を返しています。run() 関数はアプリケーションを起動し、指定したホストとポート番号でリクエストを待ち受けます。

パスパラメータを使用する

from bottle import Bottle, run

app = Bottle()

@app.route('/hello/<name>')
def hello(name):
    return f"Hello, {name}!"

if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このサンプルコードでは、/<name> のようなパスパラメータを使用して、URL内の動的な値を取得します。name パラメータは hello() 関数の引数として渡され、応答メッセージに挿入されます。たとえば、URLが “/hello/John” の場合、応答は “Hello, John!” となります。

GETとPOSTリクエストを処理する

from bottle import Bottle, run, request

app = Bottle()

@app.route('/login', method=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.forms.get('username')
        password = request.forms.get('password')
        # ユーザー名とパスワードのバリデーションなどの処理を実行する
        return f"Welcome, {username}!"
    else:
        return '''
            <form action="/login" method="post">
                <input name="username" type="text" placeholder="Username" />
                <input name="password" type="password" placeholder="Password" />
                <input type="submit" value="Login" />
            </form>
        '''

if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このサンプルコードでは、”/login” ルートに対してGETとPOSTリクエストの両方を処理する方法を示しています。@app.route('/login', method=['GET', 'POST']) のように method パラメータにリクエストメソッドを指定することで、対応するHTTPメソッドでのリクエストを処理することができます。

login() 関数では、POSTリクエストの場合には送信されたフォームデータからユーザー名とパスワードを取得し、バリデーションなどの処理を行います。その後、ユーザー名を含んだウェルカムメッセージを返します。

一方、GETリクエストの場合には、ログインフォームを表示するHTMLフォームが返されます。ユーザーはフォームにユーザー名とパスワードを入力し、送信ボタンをクリックすることでPOSTリクエストが発生します。

静的ファイルの提供

from bottle import Bottle, run, static_file

app = Bottle()

@app.route('/static/<filename>')
def serve_static(filename):
    return static_file(filename, root='./static')

if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このサンプルコードでは、”/static/<filename>” のようなパスで静的ファイルを提供します。serve_static() 関数では、static_file() 関数を使用して指定されたファイルを提供します。filename パラメータはパス内のファイル名として使用され、root パラメータは静的ファイルのディレクトリを指定します。この例では、./static ディレクトリ内のファイルが提供されます。

これにより、ウェブアプリケーション内でCSSファイルや画像などの静的ファイルを効果的に提供することができます。

以上が、PythonのBottleフレームワークの解説と各パターンのサンプルコードです。Bottleはシンプルで扱いやすいフレームワークでありながら、機能豊富なウェブアプリケーションを構築するためのツールです。

Flask

Python Flaskは、Pythonで作成されたマイクロフレームワークの1つであり、ウェブアプリケーションの構築に使用されます。Flaskは軽量でシンプルな設計を特徴としており、他の多くのフレームワークよりも柔軟性があります。FlaskはHTTPリクエストを処理し、レスポンスを生成するためのツールを提供します。

Hello World

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run()

このサンプルコードは、最も基本的なFlaskアプリケーションです。Flaskクラスをインポートし、appオブジェクトを作成します。@app.route('/')デコレータは、ルートURL(‘/’)に対するリクエストを処理する関数hello_worldを指定しています。hello_world関数は文字列Hello, World!を返します。最後に、app.run()を呼び出すことでアプリケーションを実行します。

変数を含むルート

from flask import Flask

app = Flask(__name__)

@app.route('/hello/<name>')
def hello_name(name):
    return f'Hello, {name}!'

if __name__ == '__main__':
    app.run()

このサンプルコードでは、URLの一部として変数nameを含むルートを示しています。<name>は動的に値が設定され、関数hello_nameに渡されます。関数はf'Hello, {name}!'というメッセージを生成し、それを返します。このようにして、変数を含むURLパターンを処理できます。

POSTリクエストの処理

from flask import Flask, request

app = Flask(__name__)

@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']
    # ログイン処理を実行するコード

if __name__ == '__main__':
    app.run()

このサンプルコードでは、POSTリクエストの処理方法を示しています。@app.route('/login', methods=['POST'])デコレータは、/loginルートに対してのPOSTメソッドのリクエストを処理します。requestオブジェクトを使用して、リクエストのデータにアクセスできます。この例では、request.formを使用して、フォームデータからユーザ名とパスワードを取得しています。この情報を使用して、ログイン処理を実行するコードを追加することができます。

テンプレートの使用

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run()

このサンプルコードでは、Flaskアプリケーションでテンプレートを使用する方法を示しています。render_template関数を使用して、指定されたテンプレートファイル(ここではindex.html)をレンダリングしています。index.htmlはテンプレートエンジンによって処理され、ブラウザに返されます。

これらはいくつかの一般的なパターンの例ですが、Flaskは機能が豊富で柔軟性があります。

Django

Python Djangoは、Pythonで開発されたオープンソースのWebアプリケーションフレームワークです。Djangoは、高速な開発と堅牢なアプリケーションの構築を可能にするために設計されています。簡単な使用例のみ提示するので参考にして下さい。

インストールとプロジェクトの作成

まず、Python Djangoをインストールする必要があります。以下のコマンドを使用して、Djangoをインストールします。

$ pip install django

Djangoがインストールされたら、次にDjangoプロジェクトを作成します。以下のコマンドを使用します。

$ django-admin startproject myproject

上記のコマンドを実行すると、myprojectという名前の新しいディレクトリが作成され、Djangoプロジェクトの骨格が作成されます。

アプリケーションの作成

Djangoでは、アプリケーションを作成してプロジェクトに追加することができます。アプリケーションは、特定の機能を実装するためのコードとテンプレートのグループです。以下のコマンドを使用して、新しいアプリケーションを作成します。

$ python manage.py startapp myapp

上記のコマンドを実行すると、myappという名前の新しいディレクトリが作成され、Djangoアプリケーションの骨格が作成されます。

モデルの作成

Djangoでは、データベースとの対話を簡単に行うためのモデルを定義することができます。モデルは、データベースのテーブルとしてマッピングされます。以下は、簡単なモデルの例です。

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    publication_date = models.DateField()

上記のコードでは、Bookという名前のモデルを作成しています。Bookモデルには、titleauthorpublication_dateという3つのフィールドを用意しました。

マイグレーションの実行

モデルを作成した後、データベースに対してマイグレーションを実行する必要があります。マイグレーションは、データベースのスキーマを作成または更新するための手順です。以下のコマンドを使用して、マイグレーションを実行します。

$ python manage.py makemigrations
$ python manage.py migrate

上記のコマンドを実行すると、Djangoはモデルの変更を検出し、対応するデータベースのスキーマを作成または更新します。

ビューの作成

ビューは、ユーザーからのリクエストを処理し、適切なレスポンスを返すための関数またはクラスです。以下は、簡単なビューの例です。

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello, Django!")

上記のコードでは、helloという名前のビュー関数を定義しています。このビューは、ユーザーがアクセスすると単純なテキストレスポンス「Hello, Django!」を返します。

URLの設定

ビューを使用するためには、URLとビューの対応付けを設定する必要があります。これは、URLパターンとビュー関数のマッピングを定義することで行います。以下は、URL設定の例です。

from django.urls import path
from myapp.views import hello

urlpatterns = [
    path('hello/', hello, name='hello'),
]

上記のコードでは、/hello/というURLに対してhelloビューを関連付けています。

テンプレートの作成

Djangoでは、HTMLテンプレートを使用して動的なコンテンツを生成することができます。テンプレートは、ビューで処理されたデータを表示するためのマークアップファイルです。以下は、簡単なテンプレートの例です。

<!DOCTYPE html>
<html>
<head>
    <title>MyApp - Hello</title>
</head>
<body>
    <h1>Hello, Django!</h1>
</body>
</html>

上記のコードでは、<h1>要素を使用して「Hello, Django!」というテキストを表示するシンプルなHTMLテンプレートが定義されています。

ビューとテンプレートの結びつけ

ビューで処理したデータをテンプレートに渡すためには、ビュー関数の中でテンプレートをレンダリングする必要があります。以下は、ビューとテンプレートの結びつけの例です。

from django.shortcuts import render

def hello(request):
    return render(request, 'hello.html')

上記のコードでは、render関数を使用してhello.htmlテンプレートをレンダリングしています。

これらの基本的な要素を組み合わせることで、Python Djangoを使用してWebアプリケーションを開発することができます。

Djangoには多くの機能があり、データベースの操作、ユーザー認証、セッション管理、フォーム処理など、さまざまな領域で便利な機能を提供しています。

その他のフレームワーク

他にもTornadoやPyramidなど、さまざまなPythonベースのウェブサーバフレームワークが存在します。

データベースフレームワーク

データベースフレームワークを使用すると、ウェブアプリケーションとデータベースの間のデータのやり取りを簡単に行うことができます。Pythonには多くのデータベースフレームワークがありますが、代表的なものとしてはSQLAlchemyやDjango ORMがあります。

ウェブサービスとオートメーション

ウェブサービスとオートメーションは、ウェブアプリケーションの自動化や他のウェブサービスとの連携を可能にします。

webbrowser

Pythonのwebbrowserモジュールは、PythonプログラムからWebブラウザを制御するための機能を提供します。このモジュールを使用すると、Pythonプログラム内からURLを開いたり、特定のWebページを表示したりすることができます。

import webbrowser

# ブラウザでURLを開く
webbrowser.open('https://www.example.com')

# 新しいウィンドウまたはタブでURLを開く
webbrowser.open_new('https://www.example.com')

# 新しいウィンドウでURLを開く
webbrowser.open_new_window('https://www.example.com')

# ブラウザの種類を指定してURLを開く
webbrowser.get('firefox').open('https://www.example.com')
  1. webbrowser.open('https://www.example.com'):デフォルトのWebブラウザで指定したURLを開きます。URLを引数に指定します。
  2. webbrowser.open_new('https://www.example.com'):新しいウィンドウまたはタブで指定したURLを開きます。ブラウザの設定によって新しいウィンドウまたは新しいタブが開かれます。
  3. webbrowser.open_new_window('https://www.example.com'):新しいウィンドウで指定したURLを開きます。新しいウィンドウが開かれます。
  4. webbrowser.get('firefox').open('https://www.example.com'):指定したブラウザでURLを開きます。ブラウザの種類を指定するためにget()メソッドを使用し、open()メソッドでURLを開きます。この例では、Firefoxブラウザが使用されます。

webbrowserモジュールには他にも便利な機能がありますが、上記のサンプルコードは基本的な使い方を示しています。プログラム内でブラウザを制御する必要がある場合や、特定のWebページを開いたり表示したりする必要がある場合に役立ちます。

自分の環境に入っていないブラウザを指定すると、webbrowser.Errorが送出されます。

webview

PythonのWebviewは、PythonアプリケーションでWebコンテンツを表示するためのライブラリです。Webviewは、ネイティブのウェブブラウザウィンドウを作成し、その中にWebコンテンツを表示します。これにより、Pythonで作成したアプリケーション内で簡単にWebベースのユーザーインターフェースを組み込むことができます。

最小限のWebviewウィンドウを表示する

import webview

def main():
    webview.create_window("Hello World", "https://www.example.com")

if __name__ == '__main__':
    main()

このサンプルコードでは、webviewモジュールをインポートしています。create_window関数を使用して、タイトルが “Hello World” でURLが “https://www.example.com” のWebviewウィンドウを作成します。

イベントハンドリングとコールバック関数の追加

import webview

def on_loaded():
    print("Webviewウィンドウが読み込まれました。")

def on_closing():
    print("Webviewウィンドウが閉じられました。")

def main():
    webview.create_window("Event Handling", "https://www.example.com", on_loaded=on_loaded, on_closing=on_closing)

if __name__ == '__main__':
    main()

このサンプルコードでは、on_loaded関数とon_closing関数を定義しています。create_window関数のon_loadedパラメータとon_closingパラメータにそれぞれこれらの関数を渡すことで、ウィンドウの読み込み完了時と閉じる際にそれぞれの関数が呼び出されるようになります。このようにイベントハンドリングとコールバック関数を追加することで、Webviewウィンドウの状態を制御することができます。

カスタムのHTMLコンテンツを表示する

import webview

def main():
    html_content = """
    <html>
    <body>
    <h1>Hello World</h1>
    <p>This is a custom HTML content displayed in a Webview window.</p>
    </body>
    </html>
    """
    webview.create_window("Custom HTML Content", content=html_content)

if __name__ == '__main__':
    main()

このサンプルコードでは、html_content変数にカスタムのHTMLコンテンツを代入しています。create_window関数のcontentパラメータにこの変数を渡すことで、カスタムのHTMLコンテンツを表示するWebviewウィンドウを作成します。この方法を使用すると、Pythonコード内で動的なHTMLコンテンツを生成して表示することもできます。

これらの基本的な機能に加えて、ウィンドウのサイズや位置の設定、JavaScriptとの対話、ファイルのアップロードなどの機能も提供しています。

Web APIとREST

Web APIは、ウェブ上で提供されるプログラムインタフェースです。REST(Representational State Transfer)は、Web APIの設計原則の一つであり、リソースの表現と状態の転送を行います。

Pythonを使用してWeb APIを作成する場合、前述のFlaskやDjangoなどのウェブフレームワークを使用することが一般的です。

今後、ウェブフレームワークのチュートリアル記事を書いた際に実装方法などを詳しく解説します。

クロールとスクレイピング

クロールとスクレイピングは、ウェブ上の情報を収集するための技術です。

Scrapy

Scrapyは、Pythonで書かれた強力なウェブスクレイピングフレームワークです。Scrapyを使用すると、ウェブサイトからデータを抽出するための柔軟なスクレイピングパイプラインを作成できます。以下では、Scrapyの基本的な使い方をサンプルコードと共に解説します。

まず、Scrapyを使用するためには、Scrapyパッケージをインストールする必要があります。次のコマンドを使用して、Scrapyをインストールします。

$ pip install scrapy

インストールが完了したら、Scrapyプロジェクトを作成しましょう。以下のコマンドを使用します。

$ scrapy startproject myproject

これにより、myprojectという名前の新しいディレクトリが作成され、Scrapyプロジェクトのファイルが配置されます。

次に、Scrapyのスパイダー(Spider)を作成します。スパイダーは、ウェブサイト上をクロールしてデータを抽出するためのルールを定義します。以下のコマンドを使用して、スパイダーを作成します。

$ cd myproject
$ scrapy genspider myspider example.com

上記のコマンドを実行すると、myspiderという名前の新しいスパイダーファイルが作成されます。example.comはクロールするウェブサイトのドメイン名です。

スパイダーファイルを開き、以下のようなサンプルコードを追加します。

import scrapy

class MySpider(scrapy.Spider):
    name = 'myspider'
    start_urls = ['http://www.example.com']

    def parse(self, response):
        # レスポンスの解析とデータの抽出
        # 例えば、タイトルの抽出
        title = response.css('h1::text').get()
        yield {'title': title}

このサンプルコードでは、start_urlsに指定したURL(ここではhttp://www.example.com)をクロールし、parseメソッドでレスポンスを解析してデータを抽出しています。ここでは、response.css('h1::text').get()を使用して、h1要素のテキストを抽出しています。

解析したデータは、yieldステートメントを使用して返されます。ここでは、{'title': title}というディクショナリが返されます。

次に、以下のコマンドを使用してスパイダーを実行します。

$ scrapy crawl myspider

データが抽出された後、Scrapyは指定した出力方法に従ってデータを処理します。デフォルトでは、抽出されたデータはコンソールに表示されますが、ScrapyはデータをCSV、JSON、または他の形式で保存することもできます。

import scrapy

class MySpider(scrapy.Spider):
    name = 'myspider'
    start_urls = ['http://www.example.com']

    def parse(self, response):
        # レスポンスの解析とデータの抽出
        # 例えば、タイトルの抽出
        title = response.css('h1::text').get()
        yield {'title': title}
  1. MySpiderクラスはscrapy.Spiderを継承しています。これにより、Scrapyの基本的なスパイダー機能を利用できます。
  2. name属性はスパイダーの名前を指定します。スパイダーを実行するときに使用されます。
  3. start_urls属性にはクロールを開始するURLのリストを指定します。この例では、http://www.example.comを指定しています。
  4. parseメソッドはスパイダーのメインロジックを記述します。レスポンスを受け取り、データを抽出する処理が行われます。
  5. response.css('h1::text').get()はCSSセレクタを使用して、h1要素のテキストを抽出します。::textはテキストのみを選択する擬似セレクタです。
  6. yield {'title': title}は抽出されたデータを返します。ここではtitleというキーでタイトルの値を持つディクショナリを返しています。

以上のコードを実行すると、http://www.example.comからタイトルが抽出され、コンソールに表示されます。もしデータをファイルに保存したい場合は、Scrapyの設定で指定することができます。

これはScrapyの基本的な使い方の一例です。Scrapyはさまざまな機能を提供しており、リンクのフォロー、データのパイプライン処理、クローリングの制御などを柔軟に行うことができます。

BeautifulSoup

BeautifulSoupは、Pythonのライブラリであり、HTMLやXMLからデータを取得するためのパーサーです。BeautifulSoupを使用すると、ウェブページからデータを抽出することができます。

$ pip install bs4

まず次のコマンドでインストールを行います。

BeautifulSoupを使ったHTMLの解析の基本的なパターンを解説します。

from bs4 import BeautifulSoup

# HTMLのサンプルデータ
html_doc = """
<html>
<head>
    <title>BeautifulSoupの解説</title>
</head>
<body>
    <h1>タイトル</h1>
    <p class="content">本文の内容です。</p>
    <ul>
        <li>項目1</li>
        <li>項目2</li>
        <li>項目3</li>
    </ul>
</body>
</html>
"""

# BeautifulSoupオブジェクトの作成
soup = BeautifulSoup(html_doc, 'html.parser')

# タイトルの取得
title = soup.title
print("タイトル:", title.text)

# h1要素の取得
h1 = soup.find('h1')
print("h1要素:", h1.text)

# p要素の取得
p = soup.find('p', class_='content')
print("p要素:", p.text)

# ul要素の取得
ul = soup.find('ul')
print("ul要素:")
for li in ul.find_all('li'):
    print(li.text)

このサンプルコードでは、html_doc変数にHTMLのサンプルデータを格納しています。次に、BeautifulSoupオブジェクトを作成し、HTMLを解析します。解析が完了すると、soupオブジェクトを使ってデータを取得できます。

上記のサンプルコードでは、以下のような解析の手順が示されています:

  1. soup.titleを使ってHTML内のタイトル要素を取得し、そのテキストを表示します。
  2. soup.find('h1')を使ってh1要素を取得し、そのテキストを表示します。
  3. soup.find('p', class_='content')を使ってp要素を取得し、そのテキストを表示します。クラス属性の指定はclass_という名前で行います。
  4. soup.find('ul')を使ってul要素を取得し、その中のli要素を順番に取得し、そのテキストを表示します。
  5. soup.titleを使ってHTML内のタイトル要素を取得し、そのテキストを表示します。
    • soup.titleはHTML内の<title>要素を取得します。.textを使って要素内のテキストを取得します。
  6. soup.find('h1')を使ってh1要素を取得し、そのテキストを表示します。
    • soup.find('h1')はHTML内の最初の<h1>要素を取得します。.textを使って要素内のテキストを取得します。
  7. soup.find('p', class_='content')を使ってp要素を取得し、そのテキストを表示します。
    • soup.find('p', class_='content')はHTML内の最初の<p>要素で、class属性が"content"である要素を取得します。.textを使って要素内のテキストを取得します。
  8. soup.find('ul')を使ってul要素を取得し、その中のli要素を順番に取得し、そのテキストを表示します。
    • soup.find('ul')はHTML内の最初の<ul>要素を取得します。
    • ul.find_all('li')を使ってul要素の中の全ての<li>要素を取得します。find_all()はマッチする全ての要素をリストとして返します。
    • ループを使用して、各li要素のテキストを表示します。

これらの手法を使用することで、BeautifulSoupを使ってHTMLから要素を取得することができます。実際のウェブスクレイピングの場合、解析したいHTMLの構造に合わせて必要な要素を指定し、データの抽出や操作を行うことができます。

また、BeautifulSoupはさまざまな解析器(パーサー)をサポートしています。上記の例ではhtml.parserを使用していますが、他にもlxmlhtml5libといったパーサーも利用できます。適切なパーサーを選択することで、特定のHTMLやXMLに対して最適な解析結果を得ることができます。

Requests-HTML

Requests-HTMLは、ウェブページからデータを取得するための強力なライブラリであり、シンプルで使いやすいインターフェースを提供します。

まず最初に、Requests-HTMLをインストールする必要があります。以下のコマンドを使用して、pipを介してライブラリをインストールします。

$ pip install requests-html

以下に、Requests-HTMLのサンプルを示します。

from requests_html import HTMLSession

# HTMLSessionオブジェクトの作成
session = HTMLSession()

# GETリクエストを送信し、レスポンスを取得する
response = session.get('https://example.com')

# ページのタイトルを表示する
print(response.html.title.text)

# 特定の要素を取得する
element = response.html.find('#my-element', first=True)
print(element.text)

# リンクを取得する
links = response.html.links
print(links)

# ページ内のすべてのテキストを取得する
text = response.html.text
print(text)

# JavaScriptを実行してページを操作する
response.html.render()
element = response.html.find('#my-element', first=True)
print(element.text)

# 指定したCSSセレクタに基づいて要素を取得する
elements = response.html.find('.my-class')
for element in elements:
    print(element.text)

# フォームを送信する
form = response.html.find('#my-form', first=True)
form['username'] = 'my_username'
form['password'] = 'my_password'
response = form.submit()

# ページ内のすべての画像をダウンロードする
images = response.html.find('img')
for image in images:
    image_url = image.attrs['src']
    response = session.get(image_url)
    with open('image.jpg', 'wb') as f:
        f.write(response.content)
  1. まず、HTMLSessionオブジェクトを作成します。このオブジェクトは、セッションを管理し、ウェブページへのリクエストとレスポンスを処理します。
  2. getメソッドを使用して、指定したURLへのGETリクエストを送信し、レスポンスを取得します。
  3. レスポンスのhtml属性を使用して、ウェブページのHTMLを解析します。
  4. title属性を使用して、ページのタイトルを取得します。
  5. findメソッドを使用して、指定したCSSセレクタを使用して要素を取得します。findメソッドのfirstパラメータをTrueに設定することで、最初の要素のみを取得します。
  6. links属性を使用して、ページ内のすべてのリンクを取得します。取得されるリンクは、相対URLの形式で返されます。
  7. text属性を使用して、ページ内のすべてのテキストを取得します。これにはHTMLタグやスクリプトなどのマークアップは含まれません。
  8. renderメソッドを使用して、JavaScriptを実行し、ページを操作します。これにより、動的に生成されたコンテンツやスクリプトに基づいてページが更新されます。
  9. findメソッドを使用して、指定したCSSセレクタに基づいて要素を取得します。返される要素はリスト形式で取得され、ループを使用してそれぞれの要素にアクセスできます。
  10. フォームを操作する場合、まず対応する<form>要素を取得します。次に、各フィールドに対して値を設定し、submitメソッドを呼び出してフォームを送信します。
  11. 画像をダウンロードする場合、まず対応する<img>要素を取得します。次に、src属性から画像のURLを取得し、GETリクエストを使用して画像のバイナリデータを取得します。最後に、バイナリデータをファイルに書き込みます。

これらのサンプルコードと解説を使用すると、Requests-HTMLを使用してウェブスクレイピングを行う際に基本的なタスクを実行できます。ただし、ウェブスクレイピングはウェブサイトの利用規約に適合し、適切なマナーを守る必要があります。

応用アプリケーション

今回の記事で解説したスクレイピングの技術は、うまく利用するととても便利な使い方ができます。2つサンプルを用意したので、便利さを体感して下さい。
また、これらのサンプルを更に拡張して見ることで、ご自身の理解も深まりますので、是非、取り組んでみて下さい。

楽天市場から売れ筋ランキングを取得する

一つ目の応用アプリケーションは、「キーワードを引数として受け取り、楽天市場からそのキーワードの商品情報を売れ筋ランキングで取得する」コードのサンプルを作ってみます。このコードでは、Requestsライブラリと楽天APIを使用しています。

import requests

def search_product(keyword):
    endpoint = "https://app.rakuten.co.jp/services/api/IchibaItem/Ranking/20170628"
    params = {
        "format": "json",
        "applicationId": "<Your_Rakuten_API_Application_ID>",
        "keyword": keyword,
        "genreId": "0",
        "period": "daily",
        "elements": "itemName,itemPrice",
        "hits": "10"
    }

    response = requests.get(endpoint, params=params)
    data = response.json()

    if "Items" in data:
        items = data["Items"]
        for i, item in enumerate(items, 1):
            item_name = item["Item"]["itemName"]
            item_price = item["Item"]["itemPrice"]
            print(f"{i}. {item_name} - {item_price}円")
    else:
        print("No results found.")

def main():
    keyword = input("Enter a keyword: ")
    search_product(keyword)

if __name__ == "__main__":
    main()

このコードでは、<Your_Rakuten_API_Application_ID>の部分に、実際の楽天APIのアプリケーションIDを入力する必要があります。楽天デベロッパーネットワークに登録し、アプリケーションIDを取得してください。

コードを実行すると、ユーザーにキーワードの入力を求めます。入力されたキーワードに基づいて、楽天市場から該当する商品情報を売れ筋ランキング順に表示します。

このサンプルコードをベースに、さらに機能を追加して、取得する商品のジャンルや表示する情報の項目をカスタマイズすることもできます。また、ウェブフレームワークを使用して、APIエンドポイントを作成し、外部からキーワードを受け取って商品情報を返すAPIとして展開することもできます。

ニュースを複数のサイトから収集し、ブログ記事を自動生成

このサンプルが動かない場合、news_sitesオブジェクト内にあるセレクタを修正して下さい。

実際のページを開き、セレクタを調べ、欲しい情報に変更する事で任意の項目を取得できます。

もう一つ応用アプリケーションの例を作ります。「ニュースを複数のサイトから収集し、ブログ記事」に組み立てるサンプルです。

このサンプルを応用すると、キューレーションメディアを作成したり、ワードプレスに最新のニュースを自動投稿したり、自分の関心のあるニュースを定期的に取得したりなど応用範囲がとても広く汎用的に使用できます。

import requests
from bs4 import BeautifulSoup

def scrape_news_sites():
    # 取得したいサイトを追加する、また、どのセレクタを指定するのかの指定も必要
    # 取得できない場合、セレクタを修正して下さい。
    news_sites = [
        {
            'name': 'CNN Japan',
            'url': 'https://www.cnn.co.jp',
            'selectors': '.top_newslist_area .top_newslist',
        },
        {
            'name': 'NHK News',
            'url': 'https://www3.nhk.or.jp/news/',
            'selectors': '.top-news-inner .content',
        },
    ]

    articles = []
    for site in news_sites:
        name = site['name']
        url = site['url']
        selectors = site['selectors']
        
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'html.parser')
        news_elements = soup.select(selectors)

        for element in news_elements:
            title = element.find('a').text.strip()
            link = url + element.find('a')['href']
            article = f"{title}\n{link}\n"
            articles.append(article)

    return articles

def generate_blog_post(articles):
    post = "# 最新ニュース\n\n"
    for i, article in enumerate(articles, 1):
        post += f"## 記事{i}\n\n"
        post += article
        post += "---\n\n"

    return post

def main():
    articles = scrape_news_sites()
    blog_post = generate_blog_post(articles)
    print(blog_post)

if __name__ == "__main__":
    main()

CNN Japan、NHK Newsの2つのニュースサイトから最新の記事を収集します。各サイトのURLと記事を選択するためのセレクター(CSSセレクター)が定義されています。

scrape_news_sites関数では、各ニュースサイトから記事を収集し、タイトルとリンクを抽出してarticlesリストに追加します。

generate_blog_post関数では、articlesリストの記事をブログ記事の形式に組み立てます。

main関数では、上記の関数を呼び出し、最新の記事を収集し、ブログ記事として表示します。このコードを実行すると、最新のニュース記事がブログ記事の形式で表示されます。

CRONやタスクスケジューラーで定期実行する設定にしておくと、自動で記事収集が可能です。

このサンプルコードをベースに、さらにニュースサイトを追加したり、記事の詳細情報や画像を収集してブログ記事に組み込んだりすることもできます。また、ウェブフレームワークなどを利用して、キューレーションメディアを作成することも可能です。

# Flaskに組み込んだ例

from flask import Flask, render_template
import requests
from bs4 import BeautifulSoup

app = Flask(__name__)

def scrape_news_sites():
    news_sites = [
        {
            'name': 'CNN Japan',
            'url': 'https://www.cnn.co.jp',
            'selectors': '.top_newslist_area .top_newslist',
        },
        {
            'name': 'NHK News',
            'url': 'https://www3.nhk.or.jp/news/',
            'selectors': '.top-news-inner .content',
        },
    ]

    articles = []
    for site in news_sites:
        name = site['name']
        url = site['url']
        selectors = site['selectors']
        
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'html.parser')
        news_elements = soup.select(selectors)

        for element in news_elements:
            title = element.find('a').text.strip()
            link = url + element.find('a')['href']
            article = {'title': title, 'link': link}
            articles.append(article)

    return articles

@app.route('/')
def home():
    articles = scrape_news_sites()
    return render_template('blog.html', articles=articles)

if __name__ == '__main__':
    app.run(debug=True)

Flaskフレームワークを使用してウェブアプリケーションを構築しています。scrape_news_sites関数は前述と同様の記事収集の処理を行い、記事のリストを返します。

home関数はFlaskのルートルートとして指定されており、記事を収集してblog.htmlテンプレートに渡します。

blog.htmlテンプレートでは、受け取った記事のリストをループしてブログ記事のHTMLを生成し、表示します。

Flaskアプリケーションを実行すると、ローカルサーバーが起動し、ブラウザでアプリケーションにアクセスできるようになります。アクセスすると、収集した記事がブログ記事として表示されます。

このように、Flaskを使用することでウェブフレームワークを通じて最新のニュースを提供することができます。必要に応じてCSSやJavaScriptを追加してデザインをカスタマイズしたり、ページネーション機能や検索機能を追加したりすることも可能です。応用することで、色々なサービスを作れると思うので、是非活用してみて下さい。

まとめ

以上がPythonにおけるウェブ開発の概要です。ウェブクライアントやウェブサーバ、ウェブフレームワーク、データベースフレームワーク、ウェブサービス、クロールとスクレイピング、さらには映画の検索まで、様々な要素をカバーしました。Pythonの豊富なライブラリとツールを駆使して、パワフルなウェブアプリケーションを開発することができます。

10回以上に渡って続けてきた、「Python入門ガイド」も、これでおしまいです。応用アプリケーションや、実用例などをなるべく入れることを心がけてきたので、少しは記事を読んでくださる方のお役に立てたかとは思います。

是非、これらの知識を活用して自身のウェブ開発のスキルを向上させてください。Happy coding!