PythonからXserverのデータベース(MySQL・MariaDB)を操作する方法って、必要な値があちこちの画面に散らばっていて絶妙にわかりにくいですよね
そこで接続に必要な情報の集め方から、そのまま使えるサンプルプログラムまで画像多めでまとめてみました
外部からブログ記事を投入したり、スクレイピングした結果をためたりするのに便利なので、私もわりと肝になる機能として使っています
※MariaDB・MySQLどちらでも同じコードで動きます
この記事は2024年に公開したものを2026年に見直しました
認証情報を.envに分ける書き方と、paramikoのバージョンを固定しないとエラーになる点を追記しています
Xserverの画面で集める接続情報
プログラムの中で使う値が、Xserverのサーバーパネルのあちこちにちりばめられています
まずは必要な項目を画面ごとに拾っていきましょう
トップ画面で控える項目
取得する項目を赤枠、この先で使う画面を緑枠で囲っています
| 項目 | 値 | 備考 |
|---|---|---|
| サーバーID | xs****** | 上部にある初期値なら”xs”で始まる値のはず |
| サーバー番号 | sv***** | 左部のアカウントデータにある初期値なら”sv”で始まる値のはず |

SSH設定画面で控える項目
まず「SSH設定タブ」で状態をONにするへ切り替えます
この画面でしれっと接続ポートの補足が出ているので控えておきましょう
| 項目 | 値 | 備考 |
|---|---|---|
| SSH接続ポート | 10022 | XserverじゃないSSH接続の場合は一般的に22らしい |

「公開鍵認証用鍵ペアの生成タブ」ではパスフレーズを設定します
| 項目 | 値 | 備考 |
|---|---|---|
| パスフレーズ | 自由設定 | 全角3文字以上(半角6文字以上)で好きな文字を設定 |

“生成する”ボタンを押すと「{サーバーID}.key」というファイル名の秘密鍵ファイルがダウンロードされます
ここまでやれば設定は完了です

WordPress簡単インストール画面で控える項目
「インストール済みWordPress一覧タブ」まで進むと、設定済みの値が並んでいるので拾うだけです
| 項目 | 値 | 備考 |
|---|---|---|
| MySQLデータベース名 | {サーバーID}_*** | 設定済みの値が表示されている |
| MySQLユーザー名 | {サーバーID}_*** | 設定済みの値が表示されている |
| MySQLパスワード | ******** | 右の目玉アイコンをクリックで値表示される |

MySQL設定画面で控える項目
「MySQL情報タブ」に出ているホスト名を取得します
| 項目 | 値 | 備考 |
|---|---|---|
| {DB名}{バージョン}ホスト名 | 表示されている値 | “localhost”が基本的な値? 昔は”mysql****.xserver.jp”だった? |

画面に出てこないけど必要な項目
画面からは確認できない(たぶん)けれど、プログラムの中で設定が必要な値もあります
| 項目 | 値 | 備考 |
|---|---|---|
| DB接続ポート | 3306 | MySQL、MariaDBともに接続用のデフォルト設定は3306 |
| 文字コード | UTF-8 | 特に意識していなければ”UTF-8″で設定されているはず |
必要なパッケージをインストールする
必要な値が集まったら、Pythonで使うパッケージを入れていきます
今回使うのは次の4つです
- mysql-connector-python … MySQL/MariaDBに接続する純正コネクター
- sshtunnel … XserverへSSHトンネルを張る
- python-dotenv … .envから認証情報を読み込む
- paramiko … sshtunnelが内部で使う(バージョン固定が必要)
データベースに接続するmysql-connector-pythonは、Oracleが出している純正のコネクターなのでこれを使います
SSHトンネルを張るsshtunnel、認証情報を読むpython-dotenv、それに後で説明するparamikoのバージョン固定がセットになります
pip install mysql-connector-python
pip install sshtunnel
pip install python-dotenv
pip install paramiko==3.5.1paramikoはバージョンを固定しないとエラーになる
ここが今回いちばん伝えたいポイントです
sshtunnelをバージョン指定なしで入れると、内部で使うparamikoが最新版で一緒に入ります
ところがこの組み合わせだと、接続しようとした瞬間に次のエラーで止まってしまいます
AttributeError: module 'paramiko' has no attribute 'DSSKey'原因は2つのパッケージの世代差です
sshtunnelは2026年6月時点でも2021年公開の0.4.0が最新で、更新が止まっています
その中で、新しいparamikoでは廃止されたparamiko.DSSKey(DSA鍵の処理)を今も呼び出しているんです
新しいparamiko(特に2025年8月の4.0以降)でDSA鍵のサポートが消えたので、組み合わせるとDSSKeyが見つからず落ちる、という流れになります
やっかいなのは、自分が使う鍵がRSAでもこのエラーが出ること
鍵の種類は関係なく、読み込みの段階で止まります
ジャベ雄このエラー、検索しても古い情報ばかりで半日溶かしました…
回避はシンプルで、paramikoを3系に固定して入れ直すだけです
私の環境ではparamiko==3.5.1で問題なく動いています(2026年6月時点で確認した限り)
sshtunnelを後から入れ直すと、paramikoが最新版に戻ってしまうことがあります
パッケージを入れたあとは、最後にpip install paramiko==3.5.1を実行して3系に揃っているか確認しておくのがおすすめです
認証情報は.envに分けてハードコードを避ける
元の記事では、パスワードや秘密鍵のパスをプログラムに直接書いていました
手元で動かすだけなら手軽ですが、このコードをそのままGitHubなどに上げると、認証情報まで一緒に公開されてしまいます
そこで今回は、パスワードなどの秘密情報を.envという別ファイルに分けて、プログラムからは読み込むだけにします
こうしておけば、うっかり公開してしまう事故を防ぎやすくなります



鍵をそのままアップして冷や汗、の前に分けておきたいよね
.envファイルを用意する
プログラムと同じフォルダに.envという名前のファイルを作り、集めてきた値を「キー=値」の形で書いていきます
{}の部分は、自分のXserverの値に置き換えてください
SSH_HOST={サーバー番号}.xserver.jp
SSH_PORT=10022
SSH_USER={サーバーID}
SSH_PASSWORD={パスフレーズ}
SSH_PKEY={秘密鍵ファイルのフルパス}
DB_NAME={MySQLデータベース名}
DB_USER={MySQLユーザー名}
DB_PASSWORD={MySQLパスワード}
DB_HOST={ホスト名}
DB_PORT=3306
DB_CHARSET=utf8python-dotenvは名前にちょっとクセがあります
インストールはpip install python-dotenv、でもコードで読み込むときはfrom dotenv import load_dotenvとdotenvになります
“pip install dotenv”と打つと別物が入ってしまうので注意です
.gitignoreで.envを管理対象から外す
せっかく分けても、.env自体をGitHubに上げてしまっては意味がありません
そこで.gitignoreに.envを書いて、アップロードの対象から外しておきます
.env.gitignoreは、Gitに「このファイルは管理しないでね(=GitHubにもアップしないでね)」と伝えるためのリストです
ここに.envを1行書いておけば、秘密情報を含む.envがうっかり公開される事故を防げます
Pythonのコネクタープログラム
準備ができたら、いよいよ接続用のプログラムです
サンプルと言いつつ、そのままモジュールとして使えるので便利ですよ
db_connector.py(.env対応版)
↓のプログラムが本体です
さきほどの.envから値を読み込むので、パスワードなどをコードに直接書かずに済みます
import os
import mysql.connector
from dotenv import load_dotenv
from sshtunnel import SSHTunnelForwarder
# .env を読み込んで環境変数として使えるようにする
load_dotenv()
class xserver_class:
def __init__(self):
self.ssh_host = os.getenv('SSH_HOST')
self.ssh_port = int(os.getenv('SSH_PORT'))
self.ssh_user = os.getenv('SSH_USER')
self.ssh_password = os.getenv('SSH_PASSWORD')
self.ssh_pkey = os.getenv('SSH_PKEY')
self.db_name = os.getenv('DB_NAME')
self.db_user = os.getenv('DB_USER')
self.db_password = os.getenv('DB_PASSWORD')
self.db_host = os.getenv('DB_HOST')
self.db_port = int(os.getenv('DB_PORT'))
self.db_charset = os.getenv('DB_CHARSET')
def __connect__(self):
self.server = SSHTunnelForwarder(
(self.ssh_host, self.ssh_port),
ssh_username=self.ssh_user,
ssh_password=self.ssh_password,
ssh_pkey=self.ssh_pkey,
remote_bind_address=(self.db_host, self.db_port),
)
self.server.start()
# connectのリファレンスはコチラ
# https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html
self.con = mysql.connector.connect(
host=self.db_host,
port=self.server.local_bind_port,
user=self.db_user,
passwd=self.db_password,
db=self.db_name,
charset=self.db_charset,
use_pure=True,
)
# 扱いやすいdict型を指定しておく
self.cur = self.con.cursor(dictionary=True)
# コネクションの設定
self.con.autocommit = False
def __disconnect__(self):
self.con.close()
self.server.stop()
def fetch(self, sql):
self.con.ping(reconnect=True)
self.cur.execute(sql)
result = self.cur.fetchall()
return result
def execute(self, sql):
self.con.ping(reconnect=True)
self.cur.execute(sql)
self.con.commit()
def open(self):
self.__connect__()
def close(self):
self.__disconnect__()
ポートだけはint()で数値に変換しています
.envから読んだ値はすべて文字列になるので、ポート番号のように数値で渡したい項目はint()で囲むのがポイントです
モジュールとして呼び出すサンプル
try / exceptでエラーハンドリングした方がベターですが、サンプルなので最低限にしています
from db_connector import xserver_class
db = xserver_class()
db.open()
# SELECT の場合はfetchを使ってdict型でレコード取得する
sql = """
SELECT
*
FROM
sample_table;
"""
ret = db.fetch(sql)
# for でループしながらカラム名を指定してレコード毎にデータ取得できる
for row in ret:
print(row["{カラム名}"])
# SELECT 以外はexecuteでcommitまでする
sql = """
INSERT INTO sample_table(id, col1, col2, create_date)
values (0, "test", "hoge", NOW());
"""
db.execute(sql)
db.close()接続が進まないときはuse_pureを付ける
とあるクライアントからの依頼でXserverにデータ登録することになって、まさにこのプログラムで接続していたら、mysql.connector.connectの部分がエラーにもならず処理が止まる事象にぶつかりまして…
結論から言うと、use_pure=Trueを足したらこの事象は解決しました
詳しい説明は↓の公式ページに譲りますが、C拡張機能を使うかどうかの判定らしく、私にはいまいち掴めていません
ちなみに私が契約しているXserverでは、そもそも不要な引数でした
どうやら環境によって要否が変わるようですね
どちらの環境でもuse_pure=Trueならエラーにならなかったので、とりあえず付けています
気になる方は外しても大丈夫かと
https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html
https://dev.mysql.com/doc/connector-python/en/connector-python-cext-development.html
AIでMCPサーバを作るときの接続部品にも使える
最近は、ClaudeのようなAIに自分のデータベースを検索させたり書き込ませたりする「MCPサーバ」を自作する人も増えてきました
MCPサーバは、AIに外部のデータや機能を渡すための受け皿のようなものです
このMCPサーバでMySQLを扱う場合、中身はだいたいこの記事と同じ部品でできています
データベースにつなぐmysql-connector-python、認証情報を環境変数で渡すpython-dotenv、そして外部から触るためのsshtunnelとparamiko、顔ぶれは見覚えがありますよね?
とくにXserverのような共用サーバーは外から直接つなげないので、SSHトンネルを張る部分がそのまま必要になります
この記事のコネクターは、その入り口をまるごと用意できるので、MCPサーバの土台として流用しやすいんです



自分のデータをAIに渡すMCP、まず詰まるのがこの接続部分なんですよね
sshtunnelを使う以上、MCPサーバ側でもparamiko==3.5.1のバージョン固定は同じく必要です
前の章のエラー対策がそのまま効いてきます
MCPサーバそのものの仕組みは、Claude Code拡張機構入門でMCPを含めて解説しているので、興味があればどうぞ
あとがき
純粋なブログ運営にはあまり使い道がないかもしれませんが、私はスクレイピングの結果をXserverへ投入して、その検索ページを作ったりしています
そういう用途では結構肝になる機能なんです
スクレイピングでデータを集める側の話は、CSSセレクタの書き方でまとめているので、あわせてどうぞ
全体像をまとめたページは↓です
Xserverはブログだけじゃないので、参考にしてみてください













コメント